Jaki jest najlepszy poziom gzip kompresji nginx?

44

Używam odwrotnej pamięci podręcznej proxy nginx z włączonym gzip. Mam jednak problemy z żądaniami HTTP aplikacji Android do mojej usługi internetowej Rails JSON. Wygląda na to, że kiedy wyłączę bufor buforowania odwrotnego proxy, działa to dobrze, ponieważ nagłówek odpowiedzi przychodzi bez gzip. Dlatego myślę, że problem jest spowodowany przez gzip. Jaki jest najbardziej odpowiedni poziom kompresji gzip?

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;
Chamnap
źródło

Odpowiedzi:

18

Poziom kompresji gzip po prostu określa stopień kompresji danych w skali od 1 do 9, gdzie 9 jest najbardziej skompresowany. Kompromis polega na tym, że najbardziej skompresowane dane zwykle wymagają najwięcej pracy przy kompresji / dekompresji, więc jeśli ustawisz je dość wysoko na stronie o dużej objętości, możesz poczuć jego efekt.

Wygląda na to, że Twoje problemy są bardziej związane z nagłówkami HTTP żądań. Zazwyczaj ruchowi HTTP skompresowanemu przez gzip towarzyszy Content-Encoding: gzipnagłówek. Jeśli zostanie to gdzieś upuszczone, klient może nie wiedzieć, że musi rozpakować odpowiedź.

rosnąć
źródło
Jak wyłączyć odpowiedź gzip za pomocą nagłówka żądania HTTP od klienta? Próbuję Accept-Encoding: '', ale to nie działa.
Chamnap
Z RFC2616 ( w3.org/Protocols/rfc2616/rfc2616-sec14.html ) Myślę, że chcesz po prostu „Accept-Encoding:” bez niczego.
growse 30.03.11
Tak, dodałem nagłówek Accept-Encoding z pustym ciągiem z addonem posteru na Mozilli i odpowiedź z powrotem bez Content-Encoding: „gzip”. Jednak w aplikacji na Androida zawsze wraca z powrotem w gzip. Sprawdziłem, co zostało buforowane w katalogach pamięci podręcznej proxy, nginx buforuje zawartość gzip, więc prawdopodobnie jest to odpowiedź z powrotem w gzip. Jak to rozwiązać?
Chamnap
Niektóre źródła sugerują, że zasoby dekompresyjne nie zwiększają się wraz ze wzrostem poziomu kompresji. W niektórych przypadkach zasoby faktycznie zmniejszają się wraz ze wzrostem poziomu kompresji. stackoverflow.com/questions/28452429/…
user2208096
90

Przetestowałem to pod nginx 1.3.9 z dwoma plikami, i takie były wyniki dla różnych poziomów:


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 (nieskompresowany):

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)

Nie jestem pewien, czy jest to reprezentatywne, ale powinno to służyć jako przykład. Ponadto nie wziąłem pod uwagę użycia procesora, ale z tych wyników wydaje się, że idealny poziom kompresji jest pomiędzy 4i 6.


Dodatkowo, jeśli używasz gzip_staticmodułu, możesz chcieć wstępnie skompresować swoje pliki (w 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;
}

Pozwala to uzyskać najlepszą możliwą kompresję bez poświęcania procesora na każde żądanie.

Alix Axel
źródło
jibes z wynikami na weblogs.asp.net/owscott/iis-7-compression-good-bad-how-much, które pokazują duży spadek poziomów kompresji po poziomach 5 i 6.
Jeff Atwood
6

Jeśli naprawdę możesz oszczędzić zasoby procesora, możesz użyć 9, ale dla większości witryn wystarczająca jest wartość 2, ponieważ gzip nie zmniejsza pliku znacznie po poziomie 1.

Edycja: Patrzyłem na Amazon CloudFront i wydaje się, że używa poziomu 6, prawdopodobnie dlatego, że ten poziom uruchamia dekompresję szybciej, co poprawia wydajność renderowania strony.

DiegoG
źródło
To nie jest poprawne
calumbrodie
2
Czy wyjaśnisz, co jest w tym złego? W każdym razie zaktualizowałem odpowiedź, przestudiowałem trochę więcej i widzę, że strony takie jak Amazon CloudFront używają poziomu kompresji 6, prawdopodobnie dlatego, że najlepiej chodzi o szybkość dekompresji (dlatego strony ładują się szybciej).
DiegoG
1) Różnica między 2 a 6 nie jest trywialna, może do 10-15%, przejrzeć dane lub spróbować samodzielnie. 2) poziom kompresji nie wpływa na trudność w dekompresji (patrz stackoverflow.com/questions/28452429/… )
calumbrodie
0

Jeśli masz dużą witrynę i nadal chcesz mieć pełny poziom kompresji (9), najlepszym pomysłem byłoby umieszczenie zawartości statycznej na Amazon S3 lub podobnych obiektowych usługach przechowywania i przesłanie skompresowanych plików.

Nadal będziesz chciał używać nginx do kompresji HTML, więc lepiej utrzymać tę wartość na normalnym poziomie, używam tam 5.

Aftab Naveed
źródło
Chciałbym skorzystać z twojej sugestii, ale obecnie nie mam comp_levelw konfiguracji, więc nie mogę powiedzieć, na jakim poziomie jestem obecnie. Czy wiesz jakie są wartości domyślne? Źródło?
Hassan Baig