Kompresja
OxPHP domyślnie kompresuje odpowiedzi HTTP za pomocą kodowania Brotli. Kompresja stosowana jest automatycznie do tekstowych typów zawartości, gdy tylko klient je obsługuje, dzięki czemu rozmiar transferu spada bez żadnych zmian w kodzie aplikacji.
Jak to działa
Każda odpowiedź przechodzi przez ten sam zestaw kontroli, w podanej kolejności, zanim OxPHP zdecyduje, czy ją skompresować:
- Kontrola Accept-Encoding. Nagłówek
Accept-Encodingklienta jest analizowany pod kątem obsługibr(Brotli). Żądania bezbrw tym nagłówku nigdy nie są kompresowane. - Kontrola typu zawartości. Typ MIME odpowiedzi jest weryfikowany względem listy kompresowalnych typów.
- Kontrola istniejącego kodowania. Odpowiedzi z istniejącym nagłówkiem
Content-Encodingsą pomijane, aby uniknąć podwójnej kompresji. - Kontrola zakresu rozmiaru. Kompresowane są tylko odpowiedzi mieszczące się między 256 bajtami a 3 MB. Mniejsze odpowiedzi przynoszą niewielką korzyść; większe są strumieniowane bez buforowania.
- Kompresja. Stosowane jest kodowanie Brotli. Jeśli skompresowany wynik nie jest mniejszy od oryginału, wysyłana jest odpowiedź nieskompresowana.
Kompresja odbywa się po wykonaniu kodu PHP i po obsłużeniu plików statycznych. Całe skompresowane ciało odpowiedzi jest przez chwilę przechowywane w pamięci, dlatego właśnie odpowiedzi powyżej 3 MB są wykluczone.
Konfiguracja
| Zmienna | Wartość domyślna | Opis |
|---|---|---|
COMPRESSION_LEVEL |
4 |
Poziom jakości Brotli (0–11). Wyższe wartości dają mniejszy wynik kosztem większego zużycia CPU. Ustaw na 0, aby całkowicie wyłączyć kompresję |
Domyślny poziom 4 równoważy współczynnik kompresji względem zużycia CPU przy serwowaniu treści webowych. Poziomy 9–11 lepiej nadają się do kompresji offline lub w czasie budowania.
Kompresowalne typy zawartości
Kompresja stosowana jest do następujących typów MIME:
Typy tekstowe:
text/htmltext/csstext/plaintext/xmltext/javascript
Typy application:
application/javascriptapplication/jsonapplication/xmlapplication/xhtml+xmlapplication/rss+xmlapplication/atom+xmlapplication/manifest+jsonapplication/ld+jsonapplication/wasm
Inne typy:
image/svg+xmlfont/ttffont/otfapplication/x-font-ttfapplication/x-font-opentypeapplication/vnd.ms-fontobject
Bez kompresji
Odpowiedzi są wysyłane bez kompresji, gdy spełniony jest którykolwiek z poniższych warunków:
- Klient nie deklaruje
brw nagłówkuAccept-Encoding - Odpowiedź ma już nagłówek
Content-Encoding(np. treść wstępnie skompresowana) - Ciało odpowiedzi jest mniejsze niż 256 bajtów lub większe niż 3 MB
- Typ zawartości nie znajduje się na liście kompresowalnych (np.
image/png,image/jpeg,font/woff2,application/zip— formaty te korzystają już z wewnętrznej kompresji) - Odpowiedź jest strumieniowana — jej długość nie jest znana w momencie wysyłania nagłówków (skrypty PHP używające
oxphp_stream_flush(), Server-Sent Events). Kompresja strumienia wymagałaby zbuforowania go w całości w pamięci, niszcząc czas do pierwszego bajtu, dlatego strumieniowane odpowiedzi zawsze przechodzą bez kompresji
Nagłówki odpowiedzi
Gdy kompresja jest stosowana, OxPHP ustawia następujące nagłówki:
| Nagłówek | Wartość |
|---|---|
Content-Encoding |
br |
Content-Length |
Zaktualizowany do rozmiaru skompresowanego ciała odpowiedzi |
Vary |
Dopisywane jest Accept-Encoding, co gwarantuje, że pamięci podręczne HTTP przechowują osobne wersje dla klientów z obsługą Brotli i bez niej |
Rozwiązywanie problemów
Odpowiedzi nie są kompresowane
Sprawdź, czy klient wysyła Accept-Encoding: br. Większość nowoczesnych przeglądarek to robi, ale niektóre narzędzia do testowania HTTP nie dołączają tego nagłówka domyślnie.
Sprawdź za pomocą curl:
curl -H "Accept-Encoding: br" -I http://localhost/Poszukaj Content-Encoding: br w nagłówkach odpowiedzi. Jeśli go brakuje, sprawdź, czy:
COMPRESSION_LEVELnie jest ustawiony na0- Ciało odpowiedzi ma co najmniej 256 bajtów
Content-Typeodpowiedzi znajduje się na liście kompresowalnych powyżej
Kompresja powiększa odpowiedzi
W przypadku bardzo małych odpowiedzi (poniżej kilkuset bajtów) narzut Brotli sporadycznie daje wynik większy od oryginału. OxPHP wykrywa to i automatycznie wysyła odpowiedź nieskompresowaną — nie jest potrzebna żadna zmiana konfiguracji.
Wysokie zużycie CPU przez kompresję
Wyższe poziomy jakości (8–11) kompresują znacznie lepiej, ale zużywają znacznie więcej CPU. Jeśli zaobserwujesz wysokie zużycie CPU przez kompresję:
Rozwiązanie: Obniż COMPRESSION_LEVEL do 4 lub 5. Poziomy te zapewniają 80–90% redukcji rozmiaru maksymalnej jakości przy ułamku kosztu CPU.
Wstępnie skompresowane zasoby są kompresowane ponownie
Jeśli Twój potok budowania generuje pliki .br i ustawia na nich nagłówek Content-Encoding: br, OxPHP automatycznie pomija ponowną kompresję. Jeśli Twoja wstępnie skompresowana treść jest kompresowana ponownie, sprawdź, czy nagłówek Content-Encoding jest obecny w oryginalnej odpowiedzi, zanim uruchomi się kompresja.
Przykład Docker
services:
app:
image: ghcr.io/oxphp/oxphp:0.10.0
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
environment:
- DOCUMENT_ROOT=/var/www/html/public
- ENTRY_FILE=index.php
- COMPRESSION_LEVEL=6Zobacz także
- Pliki statyczne — serwowanie plików, wykrywanie MIME i buforowanie HTTP
- Dokumentacja konfiguracji — pełna lista zmiennych środowiskowych