Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I'm using nginx reverse proxy cache with gzip enabled. However, I got some problems from Android applications HTTP-requests to my Rails JSON web service. It seems when I turn off reverse proxy cache, it works ok because the response header comes without gzip. Therefore, I think the problem is caused by gzip. What is the most appropriate level of gzip compression?

gzip               on;
gzip_http_version  1.0;
gzip_vary          on;
gzip_comp_level    6;
gzip_proxied       any;
gzip_types         text/plain text/css text/javascript application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss;
share|improve this question
add comment

2 Answers

up vote 5 down vote accepted

The level of gzip compression simply determines how compressed the data is on a scale from 1-9, where 9 is the most compressed. The trade-off is that the most compressed data usually requires the most work to compress/decompress, so if you have it set fairly high on a high-volume website, you may feel its effect.

It sounds like your issues are more related to the HTTP headers on the requests. Usually gzip-compressed HTTP traffic is accompanied by the Content-Encoding: gzip header. If this is being dropped somewhere, then the client might not know to have to decompress the response.

share|improve this answer
    
How to disable gzip response using http request header from the client? I try Accept-Encoding: '', but it doesn't work. –  Chamnap Mar 30 '11 at 4:01
    
From RFC2616 (w3.org/Protocols/rfc2616/rfc2616-sec14.html) I think you want just 'Accept-Encoding: ' with nothing following. –  growse Mar 30 '11 at 8:28
    
Yeah, I added the header Accept-Encoding with empty string with poster addon on mozilla, and the response back without Content-Encoding: 'gzip'. However, on the android app, it always returns back in gzip. I checked what has been cached in the proxy cache directories, nginx caches the gzip content, so it's probably responses back in gzip. How to solve this? –  Chamnap Mar 30 '11 at 9:03
add comment

I tested this under nginx 1.3.9 with two files, and these were the results I got for the various levels:


text/html - phpinfo():

0    55.38 KiB (100.00% of original size)
1    11.22 KiB ( 20.26% of original size)
2    10.89 KiB ( 19.66% of original size)
3    10.60 KiB ( 19.14% of original size)
4    10.17 KiB ( 18.36% of original size)
5     9.79 KiB ( 17.68% of original size)
6     9.62 KiB ( 17.37% of original size)
7     9.50 KiB ( 17.15% of original size)
8     9.45 KiB ( 17.06% of original size)
9     9.44 KiB ( 17.05% of original size)

application/x-javascript - jQuery 1.8.3 (Uncompressed):

0    261.46 KiB (100.00% of original size)
1     95.01 KiB ( 36.34% of original size)
2     90.60 KiB ( 34.65% of original size)
3     87.16 KiB ( 33.36% of original size)
4     81.89 KiB ( 31.32% of original size)
5     79.33 KiB ( 30.34% of original size)
6     78.04 KiB ( 29.85% of original size)
7     77.85 KiB ( 29.78% of original size)
8     77.74 KiB ( 29.73% of original size)
9     77.75 KiB ( 29.74% of original size)

I'm not sure how representative this is but it should serve as an example. Also, I haven't taken the CPU usage into account but from these results the ideal compression level seems to be between 4 and 6.


Additionally, if you use the gzip_static module, you may want to pre-compress your files (in PHP):

function gzip_static($path)
{
    if ((extension_loaded('zlib') === true) && (is_file($path) === true))
    {
        $levels = array();
        $content = file_get_contents($path);

        foreach (range(1, 9) as $level)
        {
            $levels[$level] = strlen(gzencode($content, $level));
        }

        if ((count($levels = array_filter($levels)) > 0) && (min($levels) < strlen($content)))
        {
            if (file_put_contents($path . '.gz', gzencode($content, array_search(min($levels), $levels)), LOCK_EX) !== false)
            {
                return touch($path . '.gz', filemtime($path), fileatime($path));
            }
        }
    }

    return false;
}

This allows you to get the best possible compression without sacrificing the CPU on every request.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.