In chapter 4, we examined and implemented HTTP Expires headers in an ASP.NET application. These HTTP headers tell the browser it can store certain components in its cache for a set amount of time, thereby reducing page load times because the browser doesn’t need to retrieve these components from the server. In order to ensure the components are still valid, the browser makes a small validation request. In this chapter, you’re going to investigate the ways the browser validates its cache components and what you can do to eliminate unnecessary HTTP requests.
ETags, also known as Entity Tags, are a protocol used for HTTP caching. They’re unique strings that are sent back in the HTTP response that help the browser identify and validate the browser cache. If used incorrectly they can be inefficient, so in this chapter you’re going to learn how to tweak your application so it performs at its best.
Every time you make an HTTP request for a resource on a web server, an ETag is attached in the HTTP response data. These unique strings are used to identify the cache and validate whether the cache in the user’s browser matches the one on the server. The browser cache can be much more efficient, and it saves bandwidth, because the web server doesn’t need to send a full response if the content hasn’t changed. In chapter 4, in the discussion of HTTP caching and the Expires header, you learned that when you tell a browser to cache a resource in a web page, it stores it along with an expiration date. The browser uses both the ETag and the Expires date when validating the freshness of a resource.
Figure 8.1 shows an ETag in the Response header of a resource. The ETag shows a simple string that looks similar to a GUID, a unique reference number often used in software development. This unique string provides another way to validate cached entries other than the last-modified date. It’s stored against the resource in the browser, and anytime you make an HTTP request for the same resource, it will be sent in the HTTP headers of the request. ETags are similar to fingerprints because they can be quickly compared to determine if two versions of a resource are the same.
If you revisit a web page or refresh the page, the browser validates the resource before reusing it by making a small HTTP request and sending up the ETag it’s stored against that resource, as illustrated in figure 8.2.
Figure 8.2 is a typical HTTP request header that contains an ETag. It’s sent up in the If-None-Match field and if the component hasn’t expired in cache and it matches what’s on the server, the server returns an HTTP status code of 304 Not Modified. This small check must be performed each time but it’s much more efficient than downloading the file with each HTTP request and receiving a 200 HTTP status code.
If you open your developer tools and analyze the network traffic, you might see something similar to figure 8.3. It shows a typical set of cached responses that return a 304 Not Modified HTTP code.
This unique string is sent back and forth between the server and browser, making ETags a flexible and efficient method of validating a cached component.
ETags aren’t without their limitations. They rely on a hash algorithm to generate a unique string, and the outcome of this algorithm will differ depending upon which server you land. If you run your website across multiple servers with a load balancer (figure 8.4), you’ll receive a different ETag on each server. The more servers you have in a cluster, the lower the odds are that you’ll share the same ETag across the servers. If each server uses a different ETag, the ETag won’t validate against the component and it will need to perform a full HTTP request in order to update the component.
Figure 8.4 shows what happens when a user moves between servers in a multiweb server environment. The ETags returned by each server are different, even though the component is identical and should validate correctly. These extra requests are wasteful because you’ve done all the hard work and added HTTP Expires headers, but it won’t validate if the ETag is different and a full HTTP request will have to be made.
What does this mean for you as a developer, and how can you make sure this doesn’t happen? If you run your website in a web farm or load-balanced environment, it’s best to remove the ETags altogether.
If you’re hosting your website on one server, it isn’t necessary to remove ETags. The same ETag will be used every time and the validation check will take place efficiently and correctly. The rest of this chapter will have no bearing on your development and you should skip this step completely.
If you run your website through the Yahoo! YSlow performance tool, you may notice a recommendation similar to the one in figure 8.5.
This YSlow rule suggests you remove ETags if your websites are running in a web farm environment.
There has been a big debate surrounding ETags for a number of years. Some in the developer community say it’s better to leave ETags in place because they’re there for a reason. In 2006, Steve Souders wrote the original 14 rules for faster loading websites (table 2.2). It’s not surprising that one of these original rules was the removal of ETags.
If you run your website in an environment with multiple servers, you’ll come across the scenario where your users are served different ETags for the same component. It’s even more prevalent today when many organizations run their websites in the cloud with multiple instances. Your users will notice slower page loads and your bandwidth will be wasted. You’re looking to be as efficient as possible and avoid invalidating all of the work you’ve done on the HTTP Expires headers thus far.
If ETags are a method of validating a cache component and you remove it, how does the server know if the component is still valid? Even if the ETag is removed, the Last-Modified header will still validate the component based on its timestamp. By removing the ETag you’re also effectively reducing the size of the header in the HTTP request and HTTP response. That’s one less piece of data being passed back and forth from the server. In the remainder of this chapter, you’re going to learn how to remove ETags in both ASP.NET Web Forms and ASP.NET MVC.
Unfortunately there is no simple way to remove ETags in an ASP.NET application. Most of the IIS configuration work you’ve done thus far has been done inside an easy-to-use interface, but in order to make this change you’ll need to create a custom module to remove the ETags. You’ll practice this ETag removal technique on the Surf Store application you’ve been working on throughout this book.
The code for this chapter can be downloaded from the Github repository at https://github.com/deanhume/FastASPNetWebsites. Once you’ve downloaded the code, navigate to the chapter 8 folder and open the solution under your preferred development approach (Web Forms or MVC). The sample code you’re about to run through can be applied to both ASP.NET Web Forms applications and ASP.NET MVC.
Start by adding a new class to the Utils folder, called ETagUtils.cs (figure 8.6).
Next, add the code in this listing to the class file.
First, the class is implementing the IHTTPModule interface. You need to do this in order to create a custom HTTP module. Next, an eventhandler is added for the PostReleaseRequestState. Once this event is fired, remove the ETag from the HTTP response header. The code will get fired across all requests and will occur every time a component is requested.
As a last step, you need to add the custom module to the Web.config file. Figure 8.7 shows the configuration and where to place this file in your Web.config file.
If you fire up the application and observe the HTTP requests, you might notice something a little different.
Figure 8.8 shows the HTTP response headers for an image file the Surf Store application is requesting. There are no more ETags! You now send only one header instead of two and this prevents the cache from being invalidated.
Using the code in this chapter, you configured and removed ETags from the Surf Store application. You did this with a custom HTTP module that removes the ETags from all HTTP header responses. In previous chapters, the Yahoo! YSlow tool issued a grade F for ETags, meaning the ETags weren’t configured correctly and required some attention. The Yahoo! YSlow tool has a rule recommending ETag removal in an environment where a single web application is served across multiple servers. Before making these changes to the Surf Store application, the performance score on the Yahoo! YSlow tool came in at 94 out of 100 (figure 8.9).
If you run the sample application against the updated code in this chapter, the Yahoo! YSlow tool now reports an improved performance score (figure 8.10).
The result in figure 8.10 shows a grade A for configuring ETags, and the overall performance score has jumped to 95 out of 100. Although this only gave you a one-point increase in your performance score, it’s a step in the right direction. Because you’ve made such major leaps in performance on the application thus far, further gains in performance are going to be a lot harder to obtain.
The performance cycle, discussed in chapters 1 and 6, plays an important role when you’re optimizing a website. You should choose only the optimizations that are right for your situation and your development environment. In each chapter you’ve learned about the performance scores that both Yahoo! YSlow and Google PageSpeed offer. These tools are fantastic resources for analyzing your website’s performance, but you should also allow them to help you improve your site’s performance. Implementing performance improvements to your site requires analysis, so don’t make changes only because these tools tell you to do so!
This is especially applicable to ETags. Although removing them altogether from your application may enhance its performance on a web farm, this may not be applicable to your server environment. The key here is to use the Identification step in the performance cycle. Use the technique that best suits your situation.
ETags offer a flexible and efficient way of validating components in a browser’s cache. In certain circumstances, however, it’s better to remove ETags if extra HTTP requests are required to validate the component. If your website is run in a web farm environment or if you load balance your website across multiple servers, each server might return a different ETag. In this chapter you learned how to remove ETags to prevent unnecessary HTTP requests from being made.
You learned how to remove ETags from both ASP.NET Web Forms and MVC applications with a custom HTTP module. This custom module was fired on each request and ensured that ETags were removed for each HTTP request that was made. By removing the ETags you improved the overall performance score of the Surf Store application and also ensured that your application made full use of the HTTP Expires headers.
3.14.142.131