Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gzip compression doesn't work in IIS7.5 for classic application pool

I am trying to figure out why one site using classic application pool won't get compressed. This application pool has 32bit enabled. I have the following settings in applicationHost.config.

  <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
        <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"  dynamicCompressionLevel="4" staticCompressionLevel="9"/>
        <scheme name="deflate" dll="%Windir%\system32\inetsrv\gzip.dll"  dynamicCompressionLevel="4" staticCompressionLevel="9"/>

        <staticTypes>
            <add mimeType="text/*" enabled="true" />
            <add mimeType="message/*" enabled="true" />
            <add mimeType="application/x-javascript" enabled="true" />
            <add mimeType="application/atom+xml" enabled="true" />
            <add mimeType="application/xaml+xml" enabled="true" />
            <add mimeType="*/*" enabled="false" />
        </staticTypes>
        <dynamicTypes>
          <add mimeType="text/*" enabled="true" />
          <add mimeType="message/*" enabled="true" />
          <add mimeType="application/javascript" enabled="true" />
          <add mimeType="*/*" enabled="false" />
       </dynamicTypes>
    </httpCompression>

And in global.asax file Sub Application_PreRequestHandlerExecute(ByVal sender As Object, ByVal e As EventArgs)

    Dim app As HttpApplication = TryCast(sender, HttpApplication)
    Dim acceptEncoding As String = app.Request.Headers("Accept-Encoding")
    Dim prevUncompressedStream As Stream = app.Response.Filter

    If app.Context.CurrentHandler Is Nothing Then
        Return
    End If

    If Not (TypeOf app.Context.CurrentHandler Is System.Web.UI.Page) OrElse app.Context.CurrentHandler.[GetType]().Name = "SyncSessionlessHandler" OrElse app.Request("HTTP_X_MICROSOFTAJAX") IsNot Nothing Then
        Return
    End If

    If acceptEncoding Is Nothing OrElse acceptEncoding.Length = 0 Then
        Return
    End If

    acceptEncoding = acceptEncoding.ToLower()

    If acceptEncoding.Contains("gzip") Then
        ' gzip
        app.Response.Filter = New GZipStream(prevUncompressedStream, CompressionMode.Compress)
        app.Response.AppendHeader("Content-Encoding", "gzip")
    ElseIf acceptEncoding.Contains("deflate") OrElse acceptEncoding = "*" Then
        ' deflate
        app.Response.Filter = New DeflateStream(prevUncompressedStream, CompressionMode.Compress)
        app.Response.AppendHeader("Content-Encoding", "deflate")
    End If
End Sub

I doubled checked that I have dynamicCompression feature installed. In the final output Content-Encoding header was removed all the time. What else should I look at? I read that some functions won't work for classic application pool. Is this causing the problem?

like image 879
Luyin Sun Avatar asked Apr 28 '16 17:04

Luyin Sun


People also ask

How do I enable gzip compression in IIS?

Check the httpCompression TypesCheck the httpCompression section in applicationHost. config file, you should find <add mimeType="application/x-javascript" enabled="true" /> . If this is correct, then it should be correctly configured in your IIS. This will start compressing your .

How do I enable gzip on my server?

Gzip on Windows Servers (IIS Manager)Open up IIS Manager. Click on the site you want to enable compression for. Click on Compression (under IIS) Now Enable static compression and you are done!

How to install IIS dynamic content compression?

Select the Internet Information Services (IIS) Manager under Roles > Web Server (IIS). In the IIS Manager, select the desired Site and open the Compression option (Features View). In the Compression window, mark the check box corresponding to the Enable dynamic content compression option.


1 Answers

IIS 7 improves internal compression functionality dramatically making it much easier than previous versions to take advantage of compression that’s built-in to the Web server. IIS 7 also supports dynamic compression which allows automatic compression of content created in your own applications (ASP.NET or otherwise!). The scheme is based on content-type sniffing and so it works with any kind of Web application framework.

While static compression on IIS 7 is super easy to set up and turned on by default for most text content (text/*, which includes HTML and CSS, as well as for JavaScript, Atom, XAML, XML), setting up dynamic compression is a bit more involved, mostly because the various default compression settings are set in multiple places down the IIS –> ASP.NET hierarchy.

Let’s take a look at each of the two approaches available:

  • Static Compression
    Compresses static content from the hard disk. IIS can cache this content by compressing the file once and storing the compressed file on disk and serving the compressed alias whenever static content is requested and it hasn’t changed. The overhead for this is minimal and should be aggressively enabled.
  • Dynamic Compression
    Works against application generated output from applications like your ASP.NET apps. Unlike static content, dynamic content must be compressed every time a page that requests it regenerates its content. As such dynamic compression has a much bigger impact than static caching.

How Compression is configured

Compression in IIS 7.x is configured with two .config file elements in the <system.WebServer> space. The elements can be set anywhere in the IIS/ASP.NET configuration pipeline all the way from ApplicationHost.config down to the local web.config file. The following is from the the default setting in ApplicationHost.config (in the %windir%\System32\inetsrv\config folder) on IIS 7.5 with a couple of small adjustments (added json output and enabled dynamic compression):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    
    <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
      <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" staticCompressionLevel="9" />
      <dynamicTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="*/*" enabled="false" />
      </dynamicTypes>
      <staticTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="application/atom+xml" enabled="true" />
        <add mimeType="application/xaml+xml" enabled="true" />
        <add mimeType="*/*" enabled="false" />
      </staticTypes>
    </httpCompression>
    
    <urlCompression doStaticCompression="true" doDynamicCompression="true" />
    
  </system.webServer>
</configuration>

You can find documentation on the keys here respectively:

  • httpCompression
  • urlCompression

The httpCompression Element – What and How to compress

Basically httpCompression configures what types to compress and how to compress them. It specifies the DLL that handles gzip encoding and the types of documents that are to be compressed. Types are set up based on mime-types which looks at returned Content-Type headers in HTTP responses. For example, I added the application/json to mime type to my dynamic compression types above to allow that content to be compressed as well since I have quite a bit of AJAX content that gets sent to the client.

The urlCompression Element – Enables and Disables Compression

The urlCompression element is a quick way to turn compression on and off. By default static compression is enabled server wide, and dynamic compression is disabled server wide. This might be a bit confusing because the httpCompression element also has a doDynamicCompression attribute which is set to true by default, but the urlCompression attribute by the same name actually overrides it.

The urlCompression element only has three attributes: doStaticCompression, doDynamicCompression, and dynamicCompressionBeforeCache. The doCompression attributes are the final determining factor whether compression is enabled, so it’s a good idea to be explcit! The default for doDynamicCompression='false”, but doStaticCompression="true"! Static Compression is enabled by Default, Dynamic Compression is not

Because static compression is very efficient in IIS 7 it’s enabled by default server wide and there probably is no reason to ever change that setting. Dynamic compression however, since it’s more resource intensive, is turned off by default. If you want to enable dynamic compression there are a few quirks you have to deal with, namely that enabling it in ApplicationHost.config doesn’t work. Setting:

<urlCompression doDynamicCompression="true" />

in applicationhost.config appears to have no effect and I had to move this element into my local web.config to make dynamic compression work. This is actually a smart choice because you’re not likely to want dynamic compression in every application on a server. Rather dynamic compression should be applied selectively where it makes sense. However, nowhere is it documented that the setting in applicationhost.config doesn’t work (or more likely is overridden somewhere and disabled lower in the configuration hierarchy).

So: Remember to set doDynamicCompression=”true” in web.config!!!

How Static Compression works

Static compression works against static content loaded from files on disk. Because this content is static and not bound to change frequently – such as .js, .css and static HTML content – it’s fairly easy for IIS to compress and then cache the compressed content. The way this works is that IIS compresses the files into a special folder on the server’s hard disk and then reads the content from this location if already compressed content is requested and the underlying file resource has not changed. The semantics of serving an already compressed file are very efficient – IIS still checks for file changes, but otherwise just serves the already compressed file from the compression folder.

The compression folder is located at:
%windir%\inetpub\temp\IIS Temporary Compressed Files\ApplicationPool\

If you look into the subfolders you’ll find compressed files:

CompressedFileFolder

These files are pre-compressed and IIS serves them directly to the client until the underlying files are changed.

As I mentioned before – static compression is on by default and there’s very little reason to turn that functionality off as it is efficient and just works out of the box. The one tweak you might want to do is to set the compression level to maximum. Since IIS only compresses content very infrequently it would make sense to apply maximum compression. You can do this with the staticCompressionLevel setting on the scheme element:

<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" staticCompressionLevel="9" />

Other than that the default settings are probably just fine.

Dynamic Compression – not so fast!

By default dynamic compression is disabled and that’s actually quite sensible – you should use dynamic compression very carefully and think about what content you want to compress. In most applications it wouldn’t make sense to compress all generated content as it would generate a significant amount of overhead. Scott Fortsyth has a great post that details some of the performance numbers and how much impact dynamic compression has. Depending on how busy your server is you can play around with compression and see what impact it has on your server’s performance.

There are also a few settings you can tweak to minimize the overhead of dynamic compression. Specifically the httpCompression key has a couple of CPU related keys that can help minimize the impact of Dynamic Compression on a busy server:

  • dynamicCompressionDisableCpuUsage
  • dynamicCompressionEnableCpuUsage

By default these are set to 90 and 50 which means that when the CPU hits 90% compression will be disabled until CPU utilization drops back down to 50%. Again this is actually quite sensible as it utilizes CPU power from compression when available and falling off when the threshold has been hit. It’s a good way some of that extra CPU power on your big servers to use when utilization is low. Again these settings are something you likely have to play with. I would probably set the upper limit a little lower than 90% maybe around 70% to make this a feature that kicks in only if there’s lots of power to spare. I’m not really sure how accurate these CPU readings that IIS uses are as Cpu usage on Web Servers can spike drastically even during low loads. Don’t trust settings – do some load testing or monitor your server in a live environment to see what values make sense for your environment.

Finally for dynamic compression I tend to add one Mime type for JSON data, since a lot of my applications send large chunks of JSON data over the wire. You can do that with the application/json content type:

<add mimeType="application/json" enabled="true" />

What about Deflate Compression?

The default compression is GZip. The documentation hints that you can use a different compression scheme and mentions Deflate compression. And sure enough you can change the compression settings to:

<scheme name="deflate" dll="%Windir%\system32\inetsrv\gzip.dll" staticCompressionLevel="9" />

to get deflate style compression. The deflate algorithm produces slightly more compact output so I tend to prefer it over GZip but more HTTP clients (other than browsers) support GZip than Deflate so be careful with this option if you build Web APIs.

I also had some issues with the above value actually being applied right away. Changing the scheme in applicationhost.config didn’t show up on the site right away. It required me to do a full IISReset to get that change to show up before I saw the change over to deflate compressed content. Content was slightly more compressed with deflate – not sure if it’s worth the slightly less common compression type, but the option at least is available.

IIS 7 finally makes GZip Easy

In summary IIS 7 makes GZip easy finally, even if the configuration settings are a bit obtuse and the documentation is seriously lacking. But once you know the basic settings I’ve described here and the fact that you can override all of this in your local web.config it’s pretty straight forward to configure GZip support and tweak it exactly to your needs.

Static compression is a total no brainer as it adds very little overhead compared to direct static file serving and provides solid compression. Dynamic Compression is a little more tricky as it does add some overhead to servers, so it probably will require some tweaking to get the right balance of CPU load vs. compression ratios. Looking at large sites like Amazon, Yahoo, NewEgg etc. – they all use


Reference :

http://weblog.west-wind.com/posts/2011/May/05/Builtin-GZipDeflate-Compression-on-IIS-7x

like image 163
Ali Gh Avatar answered Nov 14 '22 23:11

Ali Gh