Сжатие

OxPHP по умолчанию сжимает HTTP-ответы кодировкой Brotli. Сжатие применяется автоматически к текстовым типам контента, когда клиент его поддерживает, поэтому объём передаваемых данных снижается без каких-либо изменений в коде вашего приложения.

Как это работает

Каждый ответ проходит через одни и те же проверки, в указанном порядке, прежде чем OxPHP решит, сжимать его или нет:

  1. Проверка Accept-Encoding. Заголовок клиента Accept-Encoding разбирается на предмет поддержки br (Brotli). Запросы без br в этом заголовке никогда не сжимаются.
  2. Проверка типа контента. MIME-тип ответа сверяется со списком сжимаемых типов.
  3. Проверка уже применённой кодировки. Ответы с уже присутствующим заголовком Content-Encoding пропускаются, чтобы избежать двойного сжатия.
  4. Проверка диапазона размера. Сжимаются только ответы размером от 256 байт до 3 МБ. Ответы меньшего размера дают мало выгоды; ответы большего размера передаются потоком без буферизации.
  5. Сжатие. Применяется кодировка Brotli. Если сжатый результат не меньше оригинала, вместо него отправляется несжатый ответ.
Note

Сжатие происходит после выполнения PHP и после отдачи статических файлов. Всё сжатое тело кратковременно удерживается в памяти — именно поэтому ответы размером больше 3 МБ исключаются.

Конфигурация

Переменная По умолчанию Описание
COMPRESSION_LEVEL 4 Уровень качества Brotli (0–11). Более высокие значения дают меньший результат ценой большего процессорного времени. Установите 0, чтобы полностью отключить сжатие

Уровень по умолчанию 4 балансирует степень сжатия и нагрузку на CPU для веб-отдачи. Уровни 9–11 лучше подходят для оффлайн-сжатия или сжатия на этапе сборки.

Сжимаемые типы контента

Сжатие применяется к следующим MIME-типам:

Текстовые типы:

  • text/html
  • text/css
  • text/plain
  • text/xml
  • text/javascript

Типы application:

  • application/javascript
  • application/json
  • application/xml
  • application/xhtml+xml
  • application/rss+xml
  • application/atom+xml
  • application/manifest+json
  • application/ld+json
  • application/wasm

Прочие типы:

  • image/svg+xml
  • font/ttf
  • font/otf
  • application/x-font-ttf
  • application/x-font-opentype
  • application/vnd.ms-fontobject

Не сжимается

Ответы отправляются без сжатия при выполнении любого из следующих условий:

  • Клиент не заявляет br в заголовке Accept-Encoding
  • Ответ уже содержит заголовок Content-Encoding (например, предварительно сжатый контент)
  • Тело ответа меньше 256 байт или больше 3 МБ
  • Тип контента отсутствует в списке сжимаемых (например, image/png, image/jpeg, font/woff2, application/zip — эти форматы уже используют внутреннее сжатие)
  • Ответ передаётся потоком — его длина неизвестна на момент отправки заголовков (PHP-скрипты, использующие oxphp_stream_flush(), Server-Sent Events). Сжатие потока потребовало бы полной буферизации его в памяти, что разрушило бы time-to-first-byte, поэтому потоковые ответы всегда проходят без сжатия

Заголовки ответа

Когда сжатие применяется, OxPHP устанавливает следующие заголовки:

Заголовок Значение
Content-Encoding br
Content-Length Обновляется до размера сжатого тела
Vary Добавляется Accept-Encoding, благодаря чему HTTP-кеши хранят отдельные версии для клиентов с поддержкой Brotli и без неё

Устранение неполадок

Ответы не сжимаются

Убедитесь, что клиент отправляет Accept-Encoding: br. Большинство современных браузеров это делают, но некоторые инструменты для тестирования HTTP по умолчанию его не включают.

Проверьте с помощью curl:

bash
curl -H "Accept-Encoding: br" -I http://localhost/

Ищите Content-Encoding: br в заголовках ответа. Если он отсутствует, проверьте, что:

  1. COMPRESSION_LEVEL не установлен в 0
  2. Тело ответа не меньше 256 байт
  3. Content-Type ответа есть в списке сжимаемых выше
Сжатие увеличивает размер ответов

Для очень маленьких ответов (менее нескольких сотен байт) накладные расходы Brotli иногда дают результат больше оригинала. OxPHP обнаруживает это и автоматически отправляет несжатый ответ — никаких изменений в конфигурации не требуется.

Высокая нагрузка на CPU из-за сжатия

Более высокие уровни качества (8–11) сжимают значительно лучше, но используют гораздо больше CPU. Если вы наблюдаете высокое потребление CPU из-за сжатия:

Решение: Понизьте COMPRESSION_LEVEL до 4 или 5. Эти уровни обеспечивают 80–90% уменьшения размера, достигаемого при максимальном качестве, при малой доле затрат CPU.

Предварительно сжатые ресурсы сжимаются повторно

Если ваш пайплайн сборки генерирует .br-файлы и устанавливает заголовок Content-Encoding: br для этих файлов, OxPHP автоматически пропускает повторное сжатие. Если ваш предварительно сжатый контент сжимается повторно, убедитесь, что заголовок Content-Encoding присутствует в исходном ответе до того, как запускается сжатие.

Пример с Docker

compose.yaml
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=6

Смотрите также