Suggérer une traduction
 
Suggestions d'autres utilisateurs :

progress indicator
Aucune autre suggestion.
TechNet Magazine > Accueil > Tous les numéros > 2009 > TechNet Magazine Août 2009 >  Infrastructure Web : le cache Web ASP.NET favor...
Affichage du contenu :  côte à côteAffichage du contenu : côte à côte
Ce contenu traduit automatiquement peut être modifié par les membres de la communauté. Nous vous invitons à améliorer la traduction en cliquant sur le lien « Modifier » associé aux phrases ci-dessous.
Web Infrastructure
ASP.NET Web Cache Spurs Performance and Scalability
Iqbal Khan
 
At a Glance:
  • Dramatic bottleneck reduction
  • Static and dynamic Web caching
  • Must-have features: expirations, database dependency, PDF partial content, more
  • Special benefits for global organizations
  • Web-cache server clusters
  • Free and commercial solutions

Contents
Applications based on ASP.NET, Microsoft's Web-application framework, are making greater inroads into the enterprise. At the same time, bottlenecks resulting from growing numbers of users and transactions continue to prompt IT professional to call for improved performance and scalability.

The Problem: ASP.NET Bottlenecks
Bottlenecks can occur in ASP.NET applications for a variety of reasons. The most obvious: Data-storage technology isn't as scalable as Web-applications architecture. Any place in an ASP.NET application that deals with data storage or data access immediately becomes a logjam when you try to scale your application. Two areas where this happens are Session State storage and application data from a relational or mainframe database (see Figure 1).
Figure 1 Common areas of performance bottlenecks in ASP.NET applications.
Another bottleneck occurs if your ASP.NET application is making service- oriented architecture (SOA) calls to Web services. Here, the slowdown happens because the Web services have the same issues as your ASP.NET application (namely, in data storage and access). Chances are that a Web-services farm is being shared across multiple applications and, therefore, being stressed much more than any one ASP.NET application, creating the scalability bottleneck.
Bottlenecks can also occur between the user's browser and the ASP.NET Web farm. These clogs are related to the fact that ASP.NET pages have to be executed repeatedly at time involving intensive CPU processing. This process also involves sending heavy data elements (images, documents, etc.) to the user again and again.
In a previous TechNet Magazine article, I discussed ASP.NET performance and scalability issues, focusing on Session State and application data (see "Providing Scalability for ASP.NET Applications," June 2009). In that article, I covered how those problems occur, including the reasons that the ASP.NET Session State becomes a logjam as a Web farm grows. I discussed the fact that distributed in-memory cache is a superior alternative to Microsoft's existing storage option for ASP.NET Session State. I described how application data coming from a database can cause scalability bottlenecks. I also detailed how distributed caching resolves those ASP.NET Session State storage bottlenecks with the help of different caching topologies that each offer different features, but all address scalability and assure 100 percent uptime.
Finally, I generically profiled the different distributed caching options available in the market. Some options are free with limited capabilities, while others are more robust and feature-rich commercial products. However, for best performance and scalability, it's prudent to consider top-of-the-line commercial products.

The Solution: ASP.NET Web Cache
With that problem definition as a backdrop, this article's primary focus is on performance and scalability bottlenecks between the user's browser and the Web server or Web farm. Ideally, you want to reduce the number of times that the Web page itself executes. If the Web page is executed once, and its output isn't changing even briefly, then why execute it again? Why not just cache the output? Then the next time a user can just fetch that page's output directly from the cache, rather than re-executing it. Re-executing the page involves the CPU, consumes memory and uses other Web-server resources—and then, of course, there are the scalability bottleneck problems from data storage.
An ASP.NET page's output can be cached on the Web server itself; Microsoft provides the ASP.NET Output Cache mechanism to allow you to do that, and it works well. However, I do have two concerns about the ASP.NET Output Cache.
First, it requires you to change your ASP.NET code and, at the minimum, put tags on these pages to indicate that you want to cache their output. That's not always possible for an IT person who is managing both internally developed and externally purchased ASP.NET applications. Also, anytime you change your application code, you must go through quality-assurance efforts to make sure that nothing broke in the process. This increases the cost of incorporating caching.
Second, ASP.NET Output Cache caches page output local to each Web server and, in fact, inside each ASP.NET worker process. This creates major issues in terms of consistency and scalability if you have a Web garden (meaning multiple worker processes on a Web server) or a load-balanced Web farm. In these cases, you have multiple disconnected copies of the cache; for high traffic Web sites, this could become a management nightmare. In ASP.NET 4.0, Microsoft is promising an extensible caching framework that would allow you to keep the cache in a separate process or tier by incorporating a third-party distributed cache.
In light of this development, I prefer to cache page output not on the Web server, but in a separate Web-cache server that sits between users and your Web farm (kind of like a reverse proxy; see Figure 2). If a lot of user requests don't make it to the Web farm and are served from a cache in between instead, you're reducing the load on your Web farm and increasing the Web farm's scalability. Fetching output of a Web page from the cache and returning it to the user requires considerably fewer resources than actually executing that Web page. That's because the cache is a high-performance and scalable in-memory storage, unlike any disk storage that can have problems with performance and scalability.
Figure 2 Web-cache servers sitting between users and Web servers.
In this context, I'll discuss how caching the output of Web pages can resolve bottlenecks and considerably boost scalability and performance. A Web-cache server can play an important role in achieving these goals.
A Web-cache server intercepts http requests that users make for Web pages and checks to see whether those pages' output already exists in the cache. If it does, the Web-cache server returns that output to the user. The user request never even makes it to the Web servers. Because it's being fetched from the cache, the return is extremely fast. And because it's in memory and the page doesn't have to be re-executed, a lot of CPU processing is saved as well.
A Web-cache server can work with any back-end Web-technology platform. As long as they're all talking HTML and JavaScript, it doesn't matter whether the Web application is developed in Java, .NET, PHP or some other language. However, a Web-cache server can include some platform-specific features, so features differ from solution to solution.
There are two types of Web-caching solutions. One primarily caches fairly static data, meaning that every page being cached is presumed to be either totally static or to change at predictable intervals. The entire page is cached for a certain amount of time, after which it expires and is removed from the cache. The other type is for dynamic caching, which is more appropriate for dynamic Web sites or Web applications.
If your Web site or Web application is dynamic, where data changes frequently and unpredictably, then you should opt for dynamic caching. These days, most Web sites change at least some of their content frequently. You should be able to cache something for as little as 15 to 30 seconds, but normally for anywhere from a few minutes to a few hours—and in some cases, for days or even weeks.
Web caching offers an important benefit to large worldwide corporations: the ability to geographically disperse Web-caching servers. In a global organization, your main Web site application may be hosted in New York, but you have users all over the world—in San Francisco and London and Tokyo and Sydney and Dubai. Now it's relatively easy to have Web-caching servers geographically located in each of these areas. All requests coming from Europe will go through the European Web-cache server before they hit your Web site. That way, they don't have to cross the Atlantic Ocean and incur that 100-millisecond latency that every packet has to go through. They can basically get a copy of it from a nearby cache.
Let's take another example. You have a server in Dubai serving the Middle East and South Asia regions, and you've got hundreds of thousands of users hitting your Web site simultaneously. With Web caching, traffic to your main data center in New York will drop significantly. Not all the traffic is stopped because you don't cache everything, and whatever you are caching is also removed from the cache (that is, invalidated) at times. But depending on the nature of your application, you've probably reduced the traffic by 30 to 50 percent.

Must-Have Features in Web Cache
Over time, Web sites have transformed from only showing static content to becoming fully interactive Web applications with dynamic data that changes frequently. That means that, today, a Web cache must cater to all requirements of a dynamic Web site. The goal is to cache as much of the Web-site content as possible, while at the same time ensuring that the cached content is correct and not stale or out-of-sync with the underlying data in the database. To handle all that, the Web cache needs certain features to avoid data-integrity problems while boosting performance and scalability.
A typical Web-cache solution includes the following features.

Expirations
Expiration capability allows you to specify rules about which Web pages to cache and for how long. And it allows you to expire pages on either absolute or sliding time. Absolute time means you are going to expire something at a certain time, whether it's midnight today or 10 minutes from now. Sliding time depends on whether a certain page is constantly being accessed. If a page isn't being accessed—if it's not being used at all—you may want to expire it. An idle time would expire a page if it doesn't get used for more than a certain amount of time—for example, 10 or 20 minutes.
Absolute-time expiration is probably the most important time of expiration for Web pages. Web-caching products allow you to specify rules and choose which URL patterns (known as "URI") to cache. Web caching allows you to specify that certain URLs should never be cached. It allows you to specify certain types of URLs to cache for a certain lengths of time.
It should also allow you to specify when to expire various URLs based on information provided in the HTTP headers that comes with the URL output. Every page's HTTP header can contain information about how long it can be cached, when to expire it and when was it last changed. Those are the items Web cache can check to monitor whether a page's content has been changed and whether it needs to upload new content into the cache. Without this feature, you don't have a way to invalidate and remove stale data.

Reload Pages on Expirations
Another important feature is being able to automatically reload a page when it expires for any reason, whether due to absolute or idle-time expiration. For instance, you might say: "This page is good for the next 20 minutes." After 20 minutes, the Web cache automatically re-fetches that page so that it always has the latest copy.
This way, you don't wait for the next request from the user for that page. That's because when the request comes, you don't want the user to go through the delay for fetching that page again from the Web farm. Because you can fetch it in the background, it may take you 5 to 10 seconds to fetch it from the Web server by executing it first. But that's fine, because by the time the user gets it, you'll be able to return it with a sub-second response time, depending on how far away the user is.

Partial-Page Caching
Some of the pages that show up in a browser contain multiple items that each have their own URLs. So for a page to be rendered, the Web browser must call multiple URLs. This achieves the same result as a partial page—but it's not called "partial page" because on the server side, each URL represents a separate page and each page is cached independently and for a different duration, depending on the nature of its content.
In other situations, a single Web page is developed in such a way that its content is divided up into sections. Some sections are static and don't change; some portions are dynamic, with each portion changing after a different interval. In effect, partial-page caching caches page sections based on whether they're static or dynamic and for how long they should be cached, rather than just caching the entire page.
ASP.NET allows you to do partial-page caching through two means: control caching and post-cache substitution. Both require you to modify the particular ASP.NET pages where you want to do this caching. That may not be possible if you don't have your own development resources and you didn't develop this ASP.NET application in-house. Nonetheless, a description of each type of partial-page caching in ASP.NET follows.
You can do partial-page caching in ASP.NET by creating user controls to contain the cached content and then marking the user controls "cacheable." This allows you to cache some parts of the page as user controls so that when the page is re-executed, these portions are simply fetched from the cache and not re-executed. Only those parts of the page that aren't designated as user controls and are not marked "cacheable are re-executed."
With post-cache substitution, the page is cached, but some portions or fragments inside it are marked "dynamic" or "non-cacheable." Then, when this page is re-executed, only the dynamic or non-cacheable portions are actually executed. The rest of the page is obtained from the cache, and both cached and dynamic portions are combined to return the output of the page.
Interestingly, partial-page caching can only be performed on the Web server. For that reason, some programming is necessary. In the case of ASP.NET, partial-page caching is done by programming in the ASP.NET pages to determine what—and what not—to cache. But this caching is performed on the Web server itself and still executes the ASP.NET page, at least portions of it.
In ASP.NET, partial-page caching is implemented based on Microsoft's specification, but on the Java platform, a partial-page caching standard called Edge Service Includes (ESI) has emerged. ESI defines a simple XML-based markup language that defines cacheable and non-cacheable Web-page components that can be aggregated, assembled and delivered at the network edge, whether it's in a content-delivery network, an end user's browser or a Web-cache server acting as a reverse proxy between users' browsers and the Web server.
So, partial-page caching is highly platform-specific—and, of course, for ASP.NET, you must use Microsoft's approach.

Database Dependency
Another key feature is database dependency, which allows a page output to be invalidated from the cache when corresponding data in the database changes. The pages' output is often generated based on data in the database. The data they are depicting comes from one or more rows in one or more database tables. Therefore, if those rows change, then these pages must be removed from the cache. For that reason, database synchronization is an important feature. This means that when data changes in the database, these pages' output should be invalidated and should be removed from the cache. This capability allows you to automatically determine when certain pages should be removed from the cache.
One way to create this dependency is by specifying an SQL "select" statement (or a stored procedure call containing a select statement) that corresponds to the page in question, then mapping some of the page GET/POST parameters with parameters in the SQL statement. At run-time, the Web page parameters are used to execute the SQL statement and a SqlCacheDependency is created against a SQL Server 2005/2008 or Oracle 10g R2 or later database. Then when the corresponding row in the database changes, the database server fires a .NET event that's captured by the Web-cache server. Then the corresponding Web page output is removed from the cache (see Figure 3).
Figure 3 Page removed from Web cache if database row changes.

File Dependency
Another key feature is file dependency. You may associate a page output with a file in the system with the instructions: "If this file is ever updated or removed, please invalidate this page." Then the Web cache monitors that file, which is kept in a shared folder. If that file is ever updated or removed, the Web cache automatically invalidates the corresponding URL from the cache. This enables you to update that file from anywhere in your system, whether it involves another application or even a trigger in the database server based on when some related data changes. For example, if your data is stored on a mainframe rather than in SQL 2005/2008 or Oracle databases, you could use a file dependency to invalidate a cache page.
All this allows you to notify the cache when to invalidate if certain things happen in your data store or in your environment, which aren't directly accessible by the Web cache.

PDF Partial Content
Many people now access PDF files online. The common usage pattern is that they read one page at a time, going through the entire PDF file page by page. Few people download an entire PDF and then read it locally; most read it in their browsers. When they're viewing the information that way, they typically don't read the entire document; they abandon it after getting through some portion of it.
So serving the entire PDF is often a waste of resources; in fact could be the differentiating factor between acceptable and unacceptable performance during peak hours. For that reason, PDF Partial Content handling is an important feature in a Web cache. It reduces the bandwidth load on the Web server and improves overall scalability.

ViewState Caching
Among the most important features in ASP.NET is the ability to declare controls that run on the server and post-back to the same page. Prior to ASP.NET, in classic ASP, you ended up creating multiple pages to handle different operations that, logically, belonged to one page—for example, loading data, saving data or taking other actions. But in ASP.NET, you no longer have to do that. Form fields and other controls can now be declared to run on the server and the server simply posts the page back to itself.
To handle these post-backs, a ViewState is created that remembers the identity of the controls and any dynamic information assigned to these controls. In essence, ViewState preserves the state of a page's controls across multiple posts.
ViewState is important for ASP.NET applications. Essentially, it's information sent by the Web server to the browser so that the browser can send the same information back to the server the next time user does a post for the same page.
For example, you may load a customer on the customer.aspx page. Then, you make some changes in the customer data and click "Save." The Save button again calls customer.aspx, but also sends the ViewState so that the customer.aspx knows how to handle this post-back. The ViewState contains the information that customer.aspx had sent to the browser, and the post-back contains the new data that the user has perhaps modified. That allows customer.aspx to determine what changed and what to do about it. This is only a simple example; ViewState can also contain other dynamically created data for each control on the page.
Although ViewState is highly useful in ASP.NET, it also carries cost of transferring data back and forth from a Web server to the user's browser. This cost could have a performance and scalability impact during peak loads of the application and when the users are far from the Web server and across a slow Internet connection.
But the ViewState often doesn't have to travel all the way to the browser if it can be cached in the Web cache. In that case, only a tag or a unique ID could be sent to the browser so that if the browser comes back, the Web cache would re-insert a ViewState and give it back to the Web server based on the unique ID. All a Web server requires is that the next time the browser sends the request, it contains the ViewState from the previous time. It doesn't matter whether the ViewState reaches the browser because the browser never uses that information—only the Web server does.
In technical terms, a ViewState is used for post-back, so if you ever do post-backs, you'll need a ViewState, and a Web cache can cache a ViewState. That also saves considerable bandwidth, because a ViewState could be just a few kilobytes in size.

Gzip Compression
These days, most browsers can uncompress gzip-compressed content. But not all Web servers are configured to automatically compress Web pages' output. And even if compression is turned on, it consumes a lot of unnecessary CPU on each Web server, which is already being stressed by high traffic. However, if the compression is done by an intermediary proxy Web-cache server, it becomes more scalable.
It's easiest to compress static data that never changes. However, most pages in an ASP.NET application are dynamic and their content should only be compressed if the page output isn't changing every time. Otherwise, compression would put an unreasonable load on the CPU, perhaps dwarfing the gains in bandwidth usage. But because a Web cache is already intelligent about figuring out which dynamic pages output is cacheable (meaning that it doesn't change for at least a brief period of time), it's also able to automatically compress any cache pages. Then these cached pages are served to the clients multiple times in compressed form and considerably reduced bandwidth usage.
A typical gzip compression reduces the content by almost 80 percent, unless the content is already compressed (for example, PDF, JPEG, TIFF, etc.). A good Web cache should allow the user to specify which URLs to compress and which to ignore for compression.

Scalable and Dynamic Web-Cache Cluster
A Web cache is a server that sits in front of an ASP.NET Web farm (almost like an appliance). Today, ASP.NET Web farms can grow from two servers to 100-plus servers with a load balancer. Therefore, a single Web-cache server is unable to handle the load of a growing Web farm. A good rule of thumb is that for every five Web servers in the farm, you should have one Web cache server.
Having multiple Web-cache servers not only improves scalability, but also allows the Web cache to replicate so that if any one server goes down or is taken down, the cache isn't lost and there's no performance degradation (see Figure 4).
Figure 4 Dynamic Web-cache cluster (add or remove servers at runtime).
A good Web-cache server should be able to build a cluster of Web-caching servers to handle reliability through replication and scalability through multiple servers. However many Web caching-servers are involved, it's still considered one logical Web cache. Even if there are multiple copies of the cache in the cluster, they're always kept synchronized. In short, having a cluster of Web-caching servers allows you to scale while keeping the logical correctness of the cache.
Once you have a cache cluster, a good Web cache should allow you to specify different cache-storing options, also known as caching topologies. The main topologies include Replicated Cache, Partitioned Cache and Client Cache.
Replicated Cache means the entire cache is copied to each cache server in the cluster. As a result, each cache server has the entire cache. All "get" operations are always local to that box and, as a result, are very fast. However, updates are made to multiple cache servers, and if there are more than two such servers in the cluster, then the update cost grows.
On the other hand, Partitioned Cache breaks up (or partitions) the cache, storing each partition on a different cache server. The number of partitions equals the number of cache servers. This allows you to increase cache storage capacity by adding more cache servers, which you can't do in Replicated Cache. Partition Cache also allows you to create backups of each partition on a different cache server so that if any of those servers goes down, you don't lose the cache. Partition Cache is the most scalable caching topology for both storage and transactions per second.
Finally, Client Cache is a topology that is combined either with Partitioned or Replicated Cache (especially if the actual cache is hosted on a server other than the Web-cache server). Client Cache keeps a small subset of the cache within the client process so that the frequently used data is always available close by. What's kept in the Client Cache depends on what that client recently fetched. You can specify a maximum size for the Client Cache so when it reaches that size, it starts to evict (or remove) older items to make room for new ones. That way, the Client Cache never consumes more memory than what you have determined is feasible.
If you use multiple Web-cache servers without building a cache cluster, you'll end up with multiple disconnected copies of the cache. That outcome may be acceptable if your Web site is fairly static, but for dynamic Web sites and ASP.NET applications, that may cause data-integrity problems. Additionally, you'll end up sending the user request to the Web server even though another Web Cache server has the output of this page in the cache, thereby increasing the load on the ASP.NET Web farm.

Geographical Cache Distribution
Many ASP.NET application Web sites today have users worldwide even though the Web site itself is hosted in a single location. It's often impossible for the Web site to be located in multiple geographical locations because of the complexity and the cost of its infrastructure. For example, an ASP.NET Web farm also has to have a database server in the same location; database servers aren't usually ideal for geographical distribution when they involve highly transactional applications. As a result, end users experience slow performance because of wide area network (WAN) latency.
One way to remedy that problem is to place Web-cache servers in each geographical location, then route all the traffic from that area through the nearest Web-cache server (see Figure 5). Then if a Web-cache server doesn't have a page already cached, it directly sends the request to the main data center, where another set of Web-cache servers is located.
Figure 5 Web-cache server in geographically distributed environment.
So a good Web cache should have the ability to create a hierarchy of servers so that each Web cache knows where to route the request, even if it doesn't have the page cached.

Stay Away from the Database
As discussed in my June 2009 article, data doesn't change every time; it stays constant. Unfortunately, without distributed caching, you're going through unnecessary cycles to reproduce that same data over and over. But you don't have to go to the database all the time. It's the same data, so why go there? Why not take it from the cache?
Here is an example to highlight this issue. An airline's main web page isn't changing much; it can be cached for a long time. A customer visits to search for flights. The information is constantly shifting because as other users book seats, the information changes on the back end.
If the customer is searching for, say, a flight from New York to San Francisco, seat availability determines the results. Seat availability is based on the number of people already booked, with bookings happening constantly. A harried businessperson may complicate matters by inputting incorrect information or making multiple entries to assure a seat assignment.
The user receives results indicating that a particular flight is available, with that information changing in the cache every five minutes. But once the customer actually wants to reserve a seat, then a real-time check is performed in the database. That's because for every 1,000 people who check for flight availability, probably only about 10 actually make a reservation. It's fine to show flight availability to all those visitors, even though the information provided may not be entirely correct. In such situations, you can cache that page even if it's highly dynamic.
But you can cache it with the idea that it's acceptable to provide information with some risk that it's not completely accurate. However, on the reservations page in the database, it's critical to ensure that all information is accurate and up to date. The point here is that every application has common information that can be cached and a Web-site user doesn't have to be sent to the airline's database every time.
The easiest stage is when you want to cache all the images. You don't change your company logo or your president's picture or standard documents that you've got available for people to read. But then there are other portions that are more dynamic. That's where you can specify rules and say, for example, "I want to cache this page for this long."
With other pages, you might say, "I can't tell how long it's going to be cached, so I want to tie it to the database. If this row in this table changes, I want this page to be invalidated." That means removing it from the cache and reloading it, making a fresh copy. Every page category is different. As long as a Web cache allows you to determine how you want to cache pages, you're creating a situation in which the more you cache, the less you go to the Web farm.

Guidelines
In most cases, you can achieve significant benefits by deploying Web cache. If you've only got one Web server, chances are you don't have enough traffic to experience these types of problems. But if you got 1,000 or more users, you probably already have a load-balanced Web farm. In that case, you're a candidate for exploring ways to optimize performance and scalability.
Plan ahead. Don't wait for problems to occur because once they do, you'll be in panic mode. The best time is when you aren't facing any major issues—but at that point, you must be able to convince top management about why you require funding for such a project. One good way to accomplish that goal: Ask management what it might cost your business if your Web site provided painfully slow response times during peak hours (upward of 30 to 60 seconds per click). And what if your Web site went down for 30 to 60 minutes? Considering those questions can help convince your organization's executives about the need for a Web cache.
As previously noted, both free and commercially Web-caching options are available. With ASP.NET's growing popularity among developers, commercial Web-caching options that support .NET are now emerging. However, at this writing, most Web-caching products support Java and PHP. Most are software-based, but some hardware-appliance options are available as well.
As you consider your choices, stay focused on your organization and Web site. How dynamic is the site? How many users do you have? How much caching is going to really help you?
Then consider what caching features you need. As we've discussed, caching makes transactions blazingly fast and scalable. But it can sometimes give users outdated information. Keep that balance in mind as you consider various solutions.

Iqbal Khan is the President and Technology Evangelist of Alachisoft. Alachisoft provides NWebCache, which is a leading ASP.NET Web cache for boosting performance and scalability. Iqbal received an M.S. degree in Computer Science from Indiana University, Bloomington, in 1990. You can reach him at iqbal@alachisoft.com.

Infrastructure Web
Le cache Web ASP.NET favorise performances et évolutivité
Iqbal Khan
 
Vue d'ensemble :
  • Réduction considérable des goulots d'étranglement
  • Mise en cache Web statique et dynamique
  • Fonctionnalités indispensables : expirations, dépendance des bases de données, contenu PDF partiel, etc.
  • Avantages spécifiques pour les organisations internationales
  • Clusters de serveurs de cache Web
  • Solutions gratuites et commerciales

Contents
Les applications basées sur ASP.NET, l'infrastructure d'application Web de Microsoft, pénètrent de plus en plus l'entreprise. En même temps, les goulots d'étranglement résultant du nombre croissant d'utilisateurs et de transactions continuent de pousser les informaticiens à demander des performances et une évolutivité supérieures.

Le problème : des goulots d'étranglement ASP.NET
Les goulots d'étranglement peuvent se produire dans les applications ASP.NET pour diverses raisons. La plus évidente : la technologie de stockage des données n'est pas aussi évolutive que l'architecture des applications Web. Tout élément d'une application ASP.NET impliqué dans le stockage des données ou l'accès aux données pose immédiatement problème lorsque vous essayez de faire évoluer l'application. Deux domaines où cela se produit sont les données de stockage d'état de session et les données d'application d'une base de données relationnelle ou pour macroordinateur (voir Figure 1).
Figure 1 Lieux courants de goulots d'étranglement des performances dans les applications ASP.NET.
Un autre goulot d'étranglement se produit si votre application ASP.NET effectue des appels SOA (architecture orientée services) aux services Web. Ici, le ralentissement se produit parce que les services Web ont les mêmes problèmes que votre application ASP.NET (à savoir, des problèmes de stockage et d'accès aux données). Il est probable qu'une batterie de serveurs de services Web est partagée entre plusieurs applications et se trouve par conséquent beaucoup plus sollicitée qu'une application ASP.NET, ce qui crée un goulot d'étranglement pour l'évolutivité.
Les goulots d'étranglement peuvent également se produire entre le navigateur de l'utilisateur et la batterie de serveurs Web ASP.NET. Ces engorgements sont liés au fait que les pages ASP.NET doivent parfois être exécutées de façon répétée, ce qui implique une forte consommation des ressources processeur. Ce processus implique également l'envoi répété d'éléments de données volumineux (images, documents, etc.) à l'utilisateur.
Dans un précédent article de TechNet Magazine, j'ai abordé les problèmes de performances et d'évolutivité d'ASP.NET surtout à propos des données d'état de session et des données d'application (voir « Assurer l'évolutivité des applications ASP.NET ", juin 2009). Dans cet article, j'expliquais comment ces difficultés surviennent et pourquoi l'état de session devient un problème en cas d'extension d'une batterie de serveurs Web. J'ai évoqué l'idée que le cache distribué en mémoire était une meilleure solution que l'option de stockage existante de Microsoft pour l'état de session ASP.NET. J'ai décrit comment les données d'application provenant d'une base de données pouvaient entraîner des goulots d'étranglement pour l'évolutivité. J'ai également détaillé la façon dont le cache distribué résolvait ces engorgements du stockage de l'état de session ASP.NET à l'aide de différentes topologies de mise en cache offrant chacune différentes fonctionnalités, mais résolvant toutes les problèmes d'évolutivité et garantissant une disponibilité à 100 %.
Enfin, j'ai dressé un profil générique des différentes options de mise en cache distribué disponibles sur le marché. Certaines options sont gratuites, avec des fonctionnalités limitées, tandis que d'autres sont des produits commerciaux plus performants et plus complets. Toutefois, pour optimiser les performances et évolutivité, il est prudent d'envisager des produits commerciaux haut de gamme.

La solution : le cache Web ASP.NET
Gardant ce problème posé en toile de fond, cet article s'attache principalement aux goulots d'étranglement des performances et de l'évolutivité entre le navigateur de l'utilisateur et le serveur ou la batterie de serveurs Web. Dans l'idéal, il est souhaitable de réduire le nombre d'exécutions de la page Web. Si la page Web est exécutée une fois et que son résultat ne change pas, même brièvement, pourquoi l'exécuter à nouveau ? Pourquoi ne pas simplement mettre son résultat en cache ? La fois suivante, il suffira à l'utilisateur d'extraire le résultat de cette page directement du cache, sans l'exécuter une nouvelle fois. La ré-exécution de la page implique le processeur, consomme de la mémoire et utilise d'autres ressources du serveur Web. Ensuite, bien sûr, se posent les problèmes de goulot d'étranglement au niveau de l'évolutivité, dus au stockage des données.
Un résultat de page ASP.NET peut être mis en cache sur le serveur Web lui-même ; pour cela, Microsoft fournit un mécanisme efficace de cache de résultat ASP.NET. Cependant, ce cache de résultat ASP.NET me préoccupe pour deux raisons.
Tout d'abord, il exige de modifier votre code ASP.NET et, au minimum, de placer des balises sur ces pages pour indiquer que vous souhaitez mettre leur résultat en cache. Cela n'est pas toujours possible pour un informaticien qui doit gérer à la fois les applications ASP.NET développées en interne et celles achetées dans le commerce. Chaque fois que vous modifiez votre code d'application, vous devez faire des travaux d'assurance qualité pour vérifier que rien n'a été perturbé dans le processus. Cela augmente le coût d'intégration de la mise en cache.
Deuxièmement, le cache de résultat ASP.NET met en cache le résultat de page local de chaque serveur Web et, en fait, de chaque processus de travail d'ASP.NET. Cela crée des problèmes majeurs en termes de cohérence et d'évolutivité si vous avez un domaine Web privé (c'est-à-dire plusieurs processus de travail sur un serveur Web) ou une batterie de serveurs Web à charge équilibrée. Dans ce cas, vous avez plusieurs copies déconnectées du cache ; pour les sites Web à fort trafic, leur gestion peut devenir un cauchemar. Dans ASP.NET 4.0, Microsoft promet une infrastructure de mise en cache extensible qui permet de conserver le cache dans un processus ou un niveau distinct en incorporant un cache tiers distribué.
Au vu de ce développement, je préfère que le résultat du cache de page ne réside pas sur le serveur Web, mais sur un serveur de cache Web distinct placé entre les utilisateurs et votre batterie de serveurs (un peu comme un proxy inverse ; voir la Figure 2). Si de nombreuses requêtes de l'utilisateur ne parviennent pas à la batterie de serveurs Web et proviennent d'un cache placé au milieu, vous réduisez la charge sur votre batterie de serveurs Web et améliorez son évolutivité. Extraire du cache le résultat d'une page Web et le renvoyer à l'utilisateur nécessite beaucoup moins de ressources que l'exécution réelle de cette page Web. C'est parce que le cache est un stockage en mémoire très performant et évolutif, contrairement au stockage sur disque qui peut poser des problèmes de performances et d'évolutivité.
Figure 2 Serveurs de cache Web situés entre les utilisateurs et les serveurs Web.
Dans ce contexte, nous étudierons comment la mise en cache du résultat des pages Web peut résoudre les goulots d'étranglement et améliorer considérablement l'évolutivité et les performances. Un serveur de cache Web peut jouer un rôle important pour atteindre ces objectifs.
Un serveur de cache Web intercepte les requêtes http de pages Web provenant des utilisateurs et vérifie si le résultat de ces pages existe déjà dans le cache. Si tel est le cas, le serveur de cache Web renvoie ce résultat à l'utilisateur. La demande de l'utilisateur ne parvient même pas aux serveurs Web. Le retour est extrêmement rapide puisque le résultat est extrait du cache. La page se trouvant dans la mémoire, elle n'a pas besoin d'être réexécutée, ce qui économise considérablement le traitement processeur.
Un serveur de cache Web peut fonctionner avec n'importe quelle plate-forme de technologie Web back-end. Tant que ces plates-formes n'utilisent pas HTML et JavaScript, peu importe que l'application Web soit développée en Java, .NET, PHP ou un autre langage. En revanche, un serveur de cache Web peut inclure certaines fonctionnalités spécifiques à la plate-forme. Les fonctionnalités peuvent donc différer d'une solution à une autre.
Il existe deux types de solutions de mise en cache Web. On met principalement en cache des données relativement statiques, ce qui signifie que chaque page mise en cache est censée être totalement statique ou modifiée à des intervalles prévisibles. La page entière est mise en cache pendant un certain temps, après quoi elle expire et est supprimée du cache. L'autre type concerne la mise en cache dynamique, plus appropriée pour des sites Web ou des applications Web dynamiques.
Si votre application ou votre site Web est dynamique, avec des données qui changent fréquemment et de façon imprévisible, vous devez opter pour une mise en cache dynamique. De nos jours, la plupart des sites Web modifient fréquemment au moins une partie de leur contenu. Vous devez pouvoir mettre du contenu en cache pour de courtes durées, de 15 à 30 secondes, mais normalement pour des durées de quelques minutes à quelques heures et, dans certains cas, de plusieurs jours, voire de plusieurs semaines.
La mise en cache Web offre un avantage considérable aux grandes entreprises internationales : la possibilité de répartir géographiquement les serveurs de mise en cache Web. Dans une entreprise mondiale, votre application de site principal peut être hébergée à New York, mais être utilisée par des utilisateurs du monde entier, à San Francisco, Londres, Tokyo, Sydney ou Dubaï. Maintenant, il est relativement facile de placer géographiquement des serveurs Web de mise en cache dans chacune de ces régions. Toutes les demandes provenant d'Europe passeront par le serveur de cache Web européen avant d'atteindre votre site Web. Elles n'auront ainsi pas à traverser l'Océan Atlantique et supporter la latence de 100 millisecondes que chaque paquet doit subir. Elles peuvent en réalité obtenir une copie depuis un cache situé à proximité.
Prenons un autre exemple. Vous avez un serveur à Dubaï desservant les régions du Moyen-Orient et de l'Asie méridionale et des centaines de milliers d'utilisateurs accédant simultanément à votre site Web. Avec la mise en cache Web, le trafic vers votre centre de données principal de New York chute considérablement. Tout le trafic n'est pas arrêté, car vous ne mettez pas tout en cache, et tout ce que vous mettez en cache est également supprimé du cache (autrement dit invalidé) de temps à autre. Mais selon la nature de votre application, vous aurez probablement réduit le trafic de 30 à 50 pour cent.

Fonctionnalités indispensables du cache Web
Au fil du temps, les sites Web se sont transformés. Affichant tout d'abord uniquement du contenu statique, ils sont devenus des applications Web entièrement interactives, avec des données dynamiques qui changent fréquemment. Cela signifie qu'un cache Web doit aujourd'hui répondre à toutes les exigences d'un site Web dynamique. L'objectif est de mettre en cache la plus grande partie possible du contenu du site Web, tout en s'assurant que le contenu mis en cache est correct, non périmé ou hors de synchronisation avec les données sous-jacentes de la base de données. Pour gérer tout cela, le cache Web doit posséder certaines fonctionnalités qui lui permettent d'éviter les problèmes d'intégrité des données tout en accélérant les performances et l'évolutivité.
Une solution type de cache Web inclut les fonctionnalités suivantes.

Délais d'expiration
La fonctionnalité d'expiration permet de spécifier des règles déterminant quelles pages Web mettre en cache et pour quelle durée. Elle vous permet aussi de faire expirer les pages à un moment donné, en temps absolu ou décalé. Un temps absolu signifie que vous souhaitez faire expirer quelque chose à un moment donné, que ce soit minuit aujourd'hui ou dans 10 minutes. Le temps décalé dépend de si une certaine page est utilisée en permanence. Si une page n'est pas en cours d'utilisation (si elle n'est pas utilisée du tout), vous souhaiterez peut-être la faire expirer. Un délai d'inactivité fera expirer une page si elle reste inutilisée plus d'un certain temps, par exemple 10 ou 20 minutes.
L'expiration en temps absolu est probablement le temps d'expiration le plus important pour une page Web. Les produits de mise en cache Web permettent de spécifier des règles et de choisir quels modèles d'URL (appelés "URI") mettre en cache. La mise en cache Web vous permet de spécifier que certaines URL ne doivent jamais être mises en cache. Elle permet de spécifier certains types d'URL à mettre en cache pendant un certain temps.
Elle doit également permettre de spécifier quand faire expirer diverses URL en fonction des informations figurant dans les en-têtes HTTP qui accompagnent le résultat de ces URL. Chaque en-tête HTTP de page peut contenir des informations sur la durée de mise en cache à respecter, l'heure d'expiration et l'heure de la dernière modification de la page. Ce sont des éléments que le cache Web peut vérifier pour contrôler si le contenu d'une page a été modifié et s'il faut télécharger un nouveau contenu dans le cache. Sans cette fonctionnalité, vous n'avez aucun moyen d'invalider et de supprimer les données périmées.

Rechargement des pages à expiration
Une autre fonctionnalité importante est la possibilité de recharger automatiquement une page lorsqu'elle expire pour une raison quelconque, que l'expiration soit fixée en temps absolu ou en durée d'inactivité. Par exemple, vous pouvez dire : « Cette page est bonne pour les 20 prochaines minutes ». Après 20 minutes, le cache Web ira chercher à nouveau cette page automatiquement afin de toujours disposer de la dernière copie.
De cette manière, vous n'avez pas à attendre la prochaine demande de l'utilisateur pour cette page. En effet, lorsque cette demande arrive, vous ne souhaitez pas que l'utilisateur subisse un délai dû à l'extraction de la page depuis la batterie de serveurs Web. Puisque vous pouvez l'extraire en arrière-plan, cela peut vous prendre 5 à 10 secondes pour l'extraire du serveur Web en l'exécutant auparavant. Mais cela n'est pas un problème, car d'ici à ce que l'utilisateur l'ait reçue, vous pourrez la renvoyer avec un temps de réponse inférieur à la seconde, selon l'éloignement de l'utilisateur.

Cache de page partielle
Certaines des pages qui apparaissent dans un navigateur contiennent plusieurs éléments qui ont chacun leur propre URL. Par conséquent, pour restituer une page, le navigateur Web doit appeler plusieurs URL. Cela donne le même résultat qu'une page partielle, mais sans la dénomination de « page partielle » car du côté serveur, chaque URL représente une page distincte et chaque page est mise en cache indépendamment et pour une durée différente, selon la nature de son contenu.
Dans d'autres situations, une page Web unique est développée de telle manière que son contenu soit divisé en sections. Certaines sections sont statiques et ne changent pas ; certaines parties sont dynamiques, chaque partie étant modifiée après un intervalle différent. En effet, la mise en cache de page partielle met en cache les sections de pages selon qu'elles sont statiques ou dynamiques et selon la durée de conservation en cache préconisée, plutôt que de mettre simplement en cache la page entière.
ASP.NET vous permet d'effectuer une mise en cache partielle de deux manières : la mise en cache de contrôles et la substitution post-cache. Toutes deux vous obligent à modifier les pages ASP.NET spécifiques que vous souhaitez mettre en cache. Cela risque d'être impossible si vous ne disposez pas de vos propres ressources de développement et si vous n'avez pas développé cette application ASP.NET en interne. Néanmoins, voici une description de chaque type de mise en cache de page partielle dans ASP.NET.
Vous pouvez effectuer une mise en cache de page partielle dans ASP.NET en créant des contrôles utilisateur pour contenir le contenu mis en cache et en marquant ces contrôles comme « pouvant être mis en cache ». Cela permet de mettre en cache certaines parties de la page en tant que contrôles utilisateur afin que lorsque la page est réexécutée, ces parties soient simplement extraites du cache et non réexécutées. Seules les parties de la page qui ne sont pas désignées comme des contrôles utilisateur et ne sont pas marquées comme « pouvant être mises en cache » sont réexécutées.
Avec la substitution post-cache, la page est mise en cache, mais certaines parties ou fragments qu'elle contient sont marqués comme étant « dynamiques » ou « à ne pas mettre en cache ». Lorsque cette page est réexécutée, seules les parties dynamiques ou à ne pas mettre en cache sont réellement exécutées. Le reste de la page est obtenu à partir du cache et les parties mises en cache et dynamiques sont combinées pour renvoyer le résultat de la page.
Il est intéressant de noter que la mise en cache de page partielle ne peut être effectuée que sur le serveur Web. C'est pourquoi un peu de programmation est nécessaire. Dans le cas d'ASP.NET, la mise en cache de page partielle s'effectue avec une programmation dans les pages ASP.NET visant à déterminer celles à mettre ou non en cache. Mais cette mise en cache est effectuée sur le serveur Web lui-même et exécute toujours la page ASP.NET, au moins partiellement.
Dans ASP.NET, la mise en cache de page partielle est implémentée selon les spécifications de Microsoft, mais sur la plate-forme Java, une norme de mise en cache de page partielle appelée Edge Service Includes (ESI) a émergé. ESI définit un langage de balisage simple basé sur XML qui définit des composants de pages Web pouvant ou non être mis en cache, pouvant être agrégés, assemblés et transmis à la périphérie du réseau, qu'il s'agisse d'un réseau de fourniture de contenu, du navigateur d'un utilisateur final ou d'un serveur de cache Web agissant comme un proxy inverse entre les navigateurs des utilisateurs et le serveur Web.
Ainsi, la mise en cache de page partielle est très spécifique à la plate-forme et, bien sûr, pour ASP.NET, vous devez utiliser l'approche de Microsoft.

Dépendance des bases de données
Une autre fonctionnalité clé est la dépendance de la base de données, qui permet d'invalider un résultat de page dans le cache lorsque les données correspondantes changent dans la base de données. Les résultats de pages sont souvent générés d'après les données de la base de données. Les données qu'ils représentent proviennent d'une ou plusieurs lignes dans une ou plusieurs tables de base de données. Par conséquent, si les lignes sont modifiées, ces pages doivent être supprimés du cache. Pour cette raison, la synchronisation de la base de données est une fonctionnalité importante. Cela signifie que lorsque les données changent dans la base, ces résultats de pages doivent être invalidés et supprimés du cache. Cette fonctionnalité permet de déterminer automatiquement si certaines pages doivent être supprimés du cache.
Une façon de créer cette dépendance consiste à spécifier une instruction SQL "select" (ou un appel de procédure stockée contenant une instruction select) qui correspond à la page en question, puis à mapper certains des paramètres GET/POST de la page avec les paramètres de l'instruction SQL. Au moment de l'exécution, les paramètres de la page Web sont utilisés pour exécuter l'instruction SQL et un SqlCacheDependency est créé sur une base de données SQL Server 2005/2008 ou Oracle 10 g R2, ou une version ultérieure. Ainsi, lorsque la ligne correspondante change dans la base de données, le serveur de base de données déclenche un événement .NET capturé par le serveur de cache Web. Le résultat de la page correspondante est alors supprimé du cache (voir la figure 3).
Figure 3 Page supprimée du cache Web si la ligne de la base de données change.

Dépendance des fichiers
Une autre fonctionnalité clé est la dépendance des fichiers. Vous pouvez associer une sortie de page à un fichier du système avec les instructions : "Si ce fichier est déjà mis à jour ou supprimé, invalider cette page." Le cache Web contrôle ensuite ce fichier, qui est conservé dans un dossier partagé. Si ce fichier est déjà mis à jour ou supprimé, le cache Web invalide automatiquement l'URL correspondante dans le cache. Cela permet de mettre à jour des fichiers depuis n'importe quel point du système, même si cela implique une autre application, voire un déclencheur dans le serveur de base de données, en fonction du moment où certaines données connexes sont modifiées. Par exemple, si vos données sont stockées sur un ordinateur central plutôt que dans des bases de données SQL 2005/2008 ou Oracle, vous pouvez utiliser une dépendance de fichier pour invalider une page de cache.
Tout cela permet d'indiquer au cache quand procéder à une invalidation si certaines choses se produisent dans votre banque de données ou dans votre environnement et si le cache Web ne peut pas directement y accéder.

Contenu PDF partiel
De nombreux utilisateurs accèdent désormais en ligne à des fichiers PDF. Le modèle d'utilisation courante est de lire une page à la fois, en parcourant tout le fichier PDF page par page. Peu de gens téléchargent un PDF entier pour le lire en local ; la plupart le lisent dans leur navigateur. Lorsqu'ils visualisent les informations de cette façon, ils ne lisent généralement pas la totalité du document mais l'abandonnent après en avoir lu une partie.
Fournir le document en entier est donc souvent une perte de ressources ; en fait, c'est peut-être un facteur déterminant entre des performances acceptables et inacceptables aux heures de pointe. Pour cette raison, la gestion de contenu PDF partiel est une fonctionnalité importante pour un cache Web. Elle réduit la charge de bande passante sur le serveur Web et améliore l'évolutivité globale.

Mise en cache de ViewState
Parmi les fonctionnalités les plus importantes d'ASP.NET figure la possibilité de déclarer des contrôles qui s'exécutent sur le serveur et sont republiés sur la même page. Avant ASP.NET, dans l'ASP classique, vous finissiez par créer plusieurs pages pour gérer différentes opérations qui, logiquement, appartenaient à une même page, par exemple, le chargement des données, leur enregistrement ou d'autres actions. Dans ASP.NET, cela n'est plus nécessaire. Les champs de formulaires et autres contrôles peuvent maintenant être déclarés comme s'exécutant sur le serveur et le serveur republie simplement la page sur elle-même.
Pour gérer ces renvois, un ViewState est créé. Il mémorise l'identité des contrôles et toutes les informations dynamiques affectées à ces contrôles. Par essence, ViewState conserve l'état des contrôles d'une page dans plusieurs publications.
ViewState est important pour les applications ASP.NET. Fondamentalement, il s'agit d'informations envoyées par le serveur Web au navigateur pour que ce dernier puisse renvoyer ces mêmes informations au serveur la prochaine fois que l'utilisateur publiera la même page.
Par exemple, vous pouvez charger un client sue la page customer.aspx. Vous pouvez ensuite modifier les données du client et cliquer sur "Enregistrer". Le bouton Enregistrer rappelle customer.aspx, mais transmets également le ViewState afin que le customer.aspx sache comment gérer ce renvoi. Le ViewState contient les informations que customer.aspx a envoyées au navigateur et le renvoi contient les nouvelles données que l'utilisateur a peut-être modifiées. Cela permet à customer.aspx de déterminer ce qui a changé et quoi en faire. Cela n'est qu'un exemple simple ; ViewState peut également contenir d'autres données créées dynamiquement pour chaque contrôle de la page.
Bien que ViewState soit très utile dans ASP.NET, il entraîne également le coût du transfert aller-retour des données entre un serveur Web et le navigateur de l'utilisateur. Ce coût peut avoir un impact sur les performances et l'évolutivité lors des pics de charges de l'application, ou lorsque les utilisateurs sont loin du serveur Web et n'ont qu'une connexion Internet lente.
Mais le ViewState n'a que rarement à faire tout le chemin jusqu'au navigateur s'il peut être mis en cache dans le cache Web. Dans ce cas, il suffit d'envoyer une balise ou un ID unique au navigateur afin que si ce dernier revient, le cache Web réinsère un ViewState et le renvoie au serveur Web d'après cet ID unique. Tout ce qu'il faut à un serveur Web, c'est que la prochaine fois que le navigateur envoie la demande, il contienne le ViewState de la fois précédente. Peu importe que le ViewState atteigne le navigateur car celui-ci n'utilise jamais ces informations ; seul le serveur Web s'en sert.
En termes techniques, un ViewState sert aux republications. Si vous les utilisez, il vous faut un ViewState, sachant qu'un cache Web peut mettre un ViewState en cache. Cela économise également beaucoup de bande passante, car un ViewState ne pèse que quelques kilo-octets.

Compression gzip
De nos jours, la plupart des navigateurs peuvent décompresser le contenu compressé gzip. Mais tous les serveurs Web ne sont pas configurés pour compresser automatiquement le résultat des pages Web. Et même si la compression est activée, elle consomme inutilement beaucoup de ressources processeur sur chaque serveur Web, alors que ces derniers sont déjà sollicités par un trafic important. Cependant, si la compression est effectuée par un serveur de cache Web proxy intermédiaire, elle devient plus évolutive.
Il est plus facile de compresser des données statiques qui ne changent jamais. Toutefois, la plupart des pages d'une application ASP.NET sont dynamiques et leur contenu ne doit être compressé que si le résultat de la page ne change pas chaque fois. Dans le cas contraire, la compression pèsera excessivement sur le processeur et réduira peut-être à néant les gains d'utilisation de la bande passante. Mais, comme un cache Web sait déjà intelligemment déterminer quel résultat de page dynamique peut être mis en cache (autrement dit, un résultat qui ne change pas pendant au moins un court laps de temps), il est également capable de compresser automatiquement les pages du cache. Ensuite, ces pages mises en cache sont servies à plusieurs reprises aux clients sous forme compressée, ce qui réduit considérablement l'utilisation de la bande passante.
Une compression gzip standard réduit le contenu de près de 80 %, à moins que le contenu ne soit déjà compressé (par exemple, PDF, JPEG, TIFF, etc.). Un bon cache Web doit permettre à l'utilisateur de spécifier les URL à compresser ou à ignorer lors de la compression.

Cluster de cache Web évolutif et dynamique
Un cache Web est un serveur placé devant une batterie Web ASP.NET (presque comme un système). Aujourd'hui, les batteries de serveurs Web ASP.NET peuvent aller de 2 à plus de 100 serveurs avec un équilibreur de charge. Par conséquent, un serveur de cache Web unique est incapable de gérer la charge d'une batterie en pleine expansion. Une règle empirique est que pour cinq serveurs Web dans une batterie de serveurs, il faut un serveur de cache Web.
Disposer de plusieurs serveurs de cache Web améliore non seulement l'évolutivité, mais permet également au cache Web de se répliquer. Ainsi, si un serveur tombe en panne ou est retiré, le cache n'est pas perdu et il n'y a aucune dégradation des performances (voir la figure 4).
Figure 4 Cluster de cache Web dynamique (ajout ou suppression de serveurs en cours d'exécution).
Un bon serveur de cache Web doit pouvoir créer un cluster de serveurs de mise en cache Web afin de garantir la fiabilité grâce aux capacités de réplication et d'évolutivité qu'offre la présence de plusieurs serveurs. Quel que soit le nombre de serveurs de mise en cache Web impliqués, ils restent toujours considérés comme un seul cache Web logique. Même s'il existe plusieurs copies du cache dans le cluster, elles restent toujours synchronisées. En bref, un cluster de serveurs de mise en cache Web permet d'évoluer tout en conservant la précision logique du cache.
Une fois que vous avez un cluster de cache, un bon cache Web doit vous permettre de spécifier différentes options de stockage en cache, également appelées topologies de mise en cache. Les principales topologies sont le cache répliqué, le cache partitionné et le cache client.
Un cache partitionné signifie que le cache entier est copié sur chaque serveur de cache du cluster. Par conséquent, chaque serveur de cache possède le cache entier. Tous les opérations « get » sont toujours locales à chaque serveur et, par conséquent, très rapides. Toutefois, les mises à jour sont effectuées sur plusieurs serveurs de cache, et s'il existe plus de deux serveurs de ce type dans le cluster, le coût des mises à jour augmente.
De son côté, le cache partitionné décompose (ou partitionne) le cache, stockant chaque partition sur un serveur de cache différent. Le nombre de partitions est égal au nombre de serveurs de cache. Ainsi, vous pouvez augmenter la capacité de stockage du cache en ajoutant plusieurs serveurs de cache, ce que vous ne pouvez pas faire avec un cache répliqué. Le cache partitionné vous permet de créer des sauvegardes de chaque partition sur un serveur de cache différent afin de ne pas perdre le cache si l'un de ces serveurs tombe en panne. Le cache partitionné est la topologie de mise en cache la plus évolutive pour le stockage et le nombre de transactions par seconde.
Enfin, le cache client est une topologie qui se combine avec le cache partitionné ou répliqué (surtout si le cache réel est hébergé sur un autre serveur que le serveur de cache Web). Le cache client conserve un petit sous-ensemble du cache dans le processus client de sorte que les données fréquemment utilisées soient toujours disponibles à proximité. Ce qui est conservé dans le cache client dépend de que ce client a récemment extrait. Vous pouvez spécifier une taille maximale pour le cache client afin que lorsqu'il atteint cette taille, il commence à écarter (ou supprimer) les anciens éléments pour libérer de l'espace pour les nouveaux. De cette façon, le cache client ne consomme jamais plus de mémoire que ce que vous avez déterminé comme étant possible.
Si vous utilisez plusieurs serveurs de cache Web sans créer de cluster de cache, vous obtenez plusieurs copies déconnectées du cache. Ce résultat peut être acceptable si votre site Web est relativement statique, mais pour des sites Web dynamiques et des applications ASP.NET, cela peut provoquer des problèmes d'intégrité des données. En outre, vous enverrez finalement la demande de l'utilisateur au serveur Web même si un autre serveur de cache Web possède le résultat de cette page dans le cache, ce qui augmente la charge sur la batterie de serveurs Web ASP.NET.

Distribution géographique du cache
De nombreux sites Web d'applications ASP.NET ont aujourd'hui des utilisateurs dans le monde entier, même si le site Web proprement dit est hébergé à un seul endroit. Il est souvent impossible pour le site Web de se trouver à plusieurs emplacements géographiques en raison de la complexité et du coût de son infrastructure. Par exemple, une batterie de serveurs Web ASP.NET doit également disposer d'un serveur de base de données au même endroit ; les serveurs de bases de données sont en général mal adaptés à une distribution géographique lorsqu'ils impliquent des applications fortement transactionnelles. Par conséquent, les utilisateurs finaux se heurteront à un ralentissement des performances dû à la latence du réseau étendu (WAN).
Une façon de résoudre ce problème consiste à placer les serveurs de cache Web dans chaque emplacement géographique, puis à acheminer le trafic de cette zone via le serveur de cache Web le plus proche (voir la figure 5). Si un serveur de cache Web ne possède pas une page déjà mise en cache, il envoie directement la requête au centre de données principal, où se trouve un autre jeu de serveurs de cache Web.
Figure 5 Serveur de cache Web dans un environnement géographiquement distribué.
Un bon cache Web doit donc pouvoir créer une hiérarchie entre les serveurs pour que chaque cache Web sache où acheminer la demande, même s'il ne possède pas la page mise en cache.

Rester loin de la base de données
Comme je l'écrivais dans mon article de juin 2009, les données ne changent pas à chaque fois ; elles restent constantes. Malheureusement, sans mise en cache distribuée, vous passez par des cycles inutiles pour reproduire maintes et maintes fois ces mêmes données. Mais vous n'avez pas tout le temps à accéder à la base de données. Ce sont les mêmes données, alors pourquoi faire ? Pourquoi ne pas les prendre dans le cache ?
Voici un exemple qui met ce problème en évidence. La page Web principale d'une compagnie aérienne change peu ; elle peut être mise en cache pour une longue période. Un client s'y rend pour rechercher des vols. Les informations changent constamment car comme d'autres utilisateurs réservent des places, les informations changent sur le système back end.
Si le client recherche, par exemple, un vol New York - San Francisco, la disponibilité des places détermine les résultats. Cette disponibilité dépend du nombre de voyageurs déjà enregistrés, des réservations étant prises en permanence. Un vendeur surmené peut compliquer les choses en saisissant des informations incorrectes ou en effectuant plusieurs entrées pour valider une attribution de place.
L'utilisateur reçoit les résultats indiquant qu'un vol particulier est disponible, avec des informations qui sont modifiées dans le cache toutes les cinq minutes. Mais dès que le client souhaite réellement réserver une place, une vérification en temps réel est effectuée dans la base de données. En effet, pour 1 000 personnes qui vérifient la disponibilité d'un vol, il est probable qu'environ 10 seulement effectueront réellement une réservation. C'est très bien d'afficher la disponibilité des vols pour tous ces visiteurs, même si les informations fournies risquent de ne pas être entièrement correctes. Dans ce type de situations, vous pouvez mettre cette page en cache même si elle est hautement dynamique.
Mais vous pouvez la mettre en cache en jugeant qu'il est acceptable de fournir des informations qui risquent de ne pas être complètement exactes. Toutefois, sur la page des réservations de la base de données, il est essentiel de garantir que toutes les informations sont précises et à jour. Ce qui se passe ici, c'est que chaque application possède des informations communes qui peuvent être mises en cache, et qu'il n'est pas nécessaire d'adresser chaque fois un utilisateur du site Web à la base de données de la compagnie aérienne.
L'étape la plus simple a lieu lorsque vous souhaitez mettre en cache toutes les images. Vous ne modifiez pas le logo de votre société ou l'image de votre président, ni les documents standard que vous mettez à la disposition des visiteurs. Mais il y a d'autres parties plus dynamiques. C'est à ce moment que vous pouvez spécifier des règles et dire, par exemple, « je veux mettre cette page en cache pour telle durée".
Pour d'autres pages, vous pouvez, par exemple, dire : « Je ne sais pas combien de temps elle sera mise en cache, donc je veux la relier à la base de données. Si telle ligne de cette table est modifiée, je veux que cette page soit invalidée ". Cela signifie la retirer du cache et la recharger, en créant une nouvelle copie. Chaque catégorie de page est différente. Du moment qu'un cache Web vous permet de déterminer comment vous souhaitez placer les pages en cache, vous créez une situation dans laquelle plus vous mettez en cache et moins vous accédez à la batterie de serveurs Web.

Instructions
Dans la plupart des cas, vous pouvez obtenir des avantages significatifs en déployant un cache Web. Si vous n'avez qu'un seul serveur Web, il est probable que vous n'avez pas assez de trafic pour rencontrer ce type de problèmes. Mais si vous avez 1 000 utilisateurs ou plus, vous avez probablement déjà une batterie avec équilibrage de charge. Dans ce cas, il peut être intéressant pour vous de rechercher des moyens d'optimiser les performances et l'évolutivité.
Planifiez. N'attendez pas que les problèmes surviennent car vous vous trouverez alors en pleine panique. Le meilleur moment est lorsque vous n'êtes confronté à aucun problème majeur. Mais à ce stade, vous devrez être capable de convaincre votre direction de la pertinence de vos raisons pour financer un tel projet. Voici une bonne façon d'y parvenir : demandez à vos dirigeants combien cela que coûterait à l'entreprise si votre site Web avait des temps de réponse affreusement lents aux heures de pointe (au-delà de 30 à 60 secondes par clic). Et ce qui se passerait si votre site Web s'arrêtait pendant 30 à 60 minutes. Poser ces questions peut vous aider à convaincre vos dirigeants de la nécessité de mettre en place un cache Web.
Comme nous l'avons déjà mentionné, il existe des solutions gratuites ou des solutions commerciales de mise en cache Web. Devant la popularité croissance d'ASP.NET parmi les développeurs, des options commerciales de mise en cache Web prenant en charge .NET émergent à présent. Toutefois, à ce jour, la plupart des produits de mise en cache Web prennent en charge Java et PHP. La plupart sont des solutions logicielles, mais certaines options matérielles sont aussi disponibles.
Au moment de choisir, pensez d'abord à votre organisation et à son site Web. À quel point le site est-il dynamique ? Combien d'utilisateurs avez-vous ? À quel point la mise en cache va-t-elle vraiment vous aider ?
Considérez ensuite les fonctionnalités de mise en cache dont vous avez besoin. Comme nous l'avons vu, la mise en cache permet des transactions ultra rapides et évolutives. Mais elle peut parfois fournir aux utilisateurs des informations périmées. Gardez cet équilibre à l'esprit en évaluant les diverses solutions.

Iqbal KHAN est le président et développeur technique de Alachisoft. Alachisoft fournit NWebCache, un cache Web ASP.NET innovant destiné à augmenter les performances et l'évolutivité. Iqbal est titulaire d'une maîtrise d'informatique de l'Université d'Indiana, à Bloomington, obtenue en 1990. Vous pouvez le contacter à l'adresse iqbal@alachisoft.com.

Page view tracker