Настройка HTTP/2 на примере Apache 2.4, PHP 7 и Ubuntu 18.04 LTS +12



Я понимаю, что, возможно, Апач на данный момент не является предпочтительным выбором для запуска на нём новых проектов, то тем не менее, он существует, здравствует и проекты на нём таки работают. Выбор на него может пасть по каким-то личным предпочтениям, по требованиям совместимости, или каким-то другим соображениям… не суть. В этой статье я хочу по пунктам описать, как настроить поддержку протокола HTTP/2 на веб-сервере Apache, потому что сам им пользуюсь и в такой статье нуждаюсь нуждался, и надеюсь, что кому-нибудь она тоже пригодится на практике.

Что такое HTTP/2? Как понятно из названия, это — вторая версия протокола HTTP. Подробнее о преимуществах Вы можете прочитать хотя бы на Википедии. От себя лишь скажу, что если Вы хоститесь не на шаред-хостинге, то поддерживать данный протокол — must have, как и, например, HTTPS. Да, для того, чтобы у Вас заработал HTTP/2, Вам потребуется полноценный доступ к консоли машины (пусть и к виртуальной) через ssh или каким-то иным образом, а также уже настроенный HTTPS (TLS/SSL). Ну что же, давайте приступим к делу.

Шаг первый. Обновление Apache


Протокол HTTP/2 поддерживается сервером Apache с версии 2.4.24, поэтому, если у Вас установлена более старая версия, — самое время её обновить. Но сначала проверим:

apache -v

Эта команда выдаст что-то вроде такого:

Server version: Apache/2.4.37 (Ubuntu)
Server built:   2018-10-28T15:27:08

В первой строчке указана версия сервера. Если она больше или равна 2.4.24, — можем смело переходить ко второму шагу. В противном случае, нужно обновить апач, актуальные версии которого Вы сможете найти в PPA известного (если Вам уже приходилось ставить что-то свеженькое на Debian/Ubuntu) разработчика — Ondrej Sury. PPA — это персональные пакеты, не включённые в официальные репозитории дистрибутивов. Поэтому, чтобы воспользоваться ими, сначала нужно научить систему, что и откуда брать:

sudo add-apt-repository ppa:ondrej/apache2

Парень делает хорошее дело, и не против получить небольшой донат, о чём весьма недвусмысленно заявляет при подключении к его репам…

Далее, собственно, обновляем пакеты:

sudo apt update
sudo apt upgrade

И снова проверяем версию Apache. Если всё прошло хорошо — на Вашем сервере будет стоять Apache, на котором можно настроить HTTP/2. Если всё пошло плохо — боюсь, это уже не тема данной статьи. А теперь переходим ко второму шагу.

Шаг второй. Использование FastCGI


Что такое FastCGI — лучше почитать, как я уже говорил, хотя бы в Википедии, потому что коротко не расскажешь. Вам нужно перейти на PHP, работающем в режиме FastCGI (php-fpm). Как это работает — дан хороший ответ на Тостере. Здесь же я в такие нюансы вдаваться не буду, а перейду сразу к установке:

sudo apt install php-fpm

После установки нам будет сказано буквально следующее: чтобы включить PHP 7.2 FPM в Apache2,  сделайте:

sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php7.2-fpm

Делаем. После этого нужно отключить mod_php, потому что вместо него у Вас теперь php-fpm.

sudo a2dismod php7.2

Вообще говоря, версия PHP у Вас до этого могла стоять другая. Глянуть, что за модули у Вас установлены в системе можно в директории /etc/apache2/mods-available/, а какие активны в /etc/apache2/mods-enabled

Далее перезапускаем Apache

sudo service apache2 restart

и переходим к третьему шагу.

Шаг третий. Переход с модуля Prefork на Event


Что такое MPM и в чём разница между prefork, event, worker — можно почитать вот в этой замечательной статье… но сейчас на самом деле важно знать только одно: «стандартный» prefork не очень совместим с HTTP/2, поэтому Вам нужно использовать более подходящий. Выключаем один, включаем другой, перезагружаем Apache.

sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
service apache2 restart

Шаг четвёртый. Включаем HTTP/2


Либо в конфигурационный файл хоста, найти который можно в директории /etc/apache2/sites-enabled/, либо в конфиге самого сервера /etc/apache2/apache2.conf говорим, что нам нужна поддержка нового протокола:
Protocols h2 h2c http/1.1

Что действительно важно — это h2. Два других пункта — на Ваше усмотрение. h2c — это поддержка HTTP/2 через TCP (а не TLS). http/1.1 — поддержка старой версии HTTP.

Включаем модуль http2 и перезагружаем сервер:

sudo a2enmod http2
service apache2 restart

Приехали


С настоящего момента всё. Ваш ресурс должен начать работать по протоколу HTTP/2. Если вы пользуетесь Хромом, зайдя на ресурс, Вы увидете, как засветилась синим цветом пиктограмма молнии в правом верхнем углу браузера. Наведя на неё курсор, вы увидите подсказку HTTP/2-enabled(h2). В Firefox войдите в панель разработчика и на вкладке Network включите столбец Protocol — для ресурсов с вашего сайта должен значиться HTTP/2.0. Также, можно проверить, поддерживает ли ваш ресурс этот протокол на одном из множества сайтов в Сети. Но не стоит расслабляться, потому что уже на пятки наступает HTTP/3 :)

Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (26):

  1. AEP
    /#19383268 / +3

    В статье отсутствует одно важное «почему» (а именно, почему нужно переходить на php-fpm), поэтому дополняю.

    Обычный способ развертывания PHP вместе с Apache — это mod_php. Однако, PHP использует слишком много непотокобезопасных библиотек, и поэтому mod_php совместим только с MPM'ами, которые не используют потоки. Т.е. по факту только с mpm_prefork. Однако, как указано в статье, mpm_prefork несовместим с HTTP/2. Поэтому от корня зла (mod_php) надо избавиться, и заменить на отдельный процесс php-fpm, который работает независимо от Apache.

    • KevlarBeaver
      /#19383290

      Спасибо за дополнение. А Вы не можете также просвятить на тему того, чем отличается PHP FastCGI от FPM, который расшифровывается примерно в то же: FastCGI Process Manager? Вернее, даже, интересует, не чем они отличаются (на сайте php.net это описано), а зачем понадобилось это разбиение и почему нельзя было реализовать фишки FPM в рамках PHP FastCGI?

      • AEP
        /#19383438 / +2

        Основное отличие — кто отвечает за запуск FastCGI-процесса. Спецификация FastCGI допускает как запуск веб-сервером, так и внешний запуск.

        Раньше, до появления PHP-FPM и Apache 2.4, за запуск процесса отвечал Apache (а точнее, модуль mod_fastcgi или его более современный аналог — mod_fcgid). Запускал, давал сокет на stdin, и посылал туда запросы. Т.е. делал все, как предусмотрено спецификацией FastCGI, а именно разделом "Initial Process State". Другие веб-серверы так не умели, они хотели, чтобы процесс FastCGI запускал кто-то еще, а им оставалось только соединяться с сокетом и посылать туда запросы. Начиная с версии 2.4, к армии таких серверов присоединился и Apache с модулем mod_proxy_fasctgi.

        Соответственно, получилась несостыковка интерфейсов: PHP из коробки (а именно, в виде /usr/bin/php-cgi или /usr/lib/cgi-bin/php) не умел запускаться так, как ожидает Nginx или mod_proxy_fasctgi. Разработчики Lighttpd в свое время решили проблему путем написания утилиты spawn-fcgi. Эта утилита запускается как обычный демон, создает слушающий сокет, запускает традиционный FastCGI-процесс и передает этот сокет ему на stdin.

        «Почему нельзя было реализовать фишки FPM в рамках PHP FastCGI» — опять-таки, не поделили ответственность. Фишки FPM имеют смысл только в рамках концепции внешней запускалки для FastCGI-процессов. Т.е. в рамках PHP-FPM или mod_fcgid (который все равно бы не воспользовался дополнительными процессами, запущенными самим PHP, см. раздел «Special PHP considerations» тут), но не в рамках самого PHP. Исключение: использование через spawn-fcgi, как это делали пользователи lighttpd.

    • gecube
      /#19384356 / +1

      Спасибо за комментарий. Но это фактически означает, что раз уж мы начали использовать php-fpm, то нет ни одной причины, которая может нас остановить от перехода на nginx. .htaccess — может быть аргументом, но его можно корректно конвертировать в директивы nginx.

      • AEP
        /#19384518

        Причины оставаться на Apache, к сожалению, есть, и вылезают практически на каждом из проводимых мной учебных курсов по Nginx. Навскидку (не только про PHP):

        1. Софт динамически переписывает .htaccess, и по какой-то причине нельзя «заморозить» результат.
        2. Используется авторизация через CAS или Shibboleth, что в Debian или Ubuntu для Apache означает установку mod_auth_cas или mod_shib2 из репозитория, или компиляцию соответствующего модуля Nginx из исходников, а компиляция запрещена начальством.
        3. Требуется «липкая» балансировка на несколько бекендов (в Apache есть из коробки), и нет ни денег на Nginx Plus, ни желания собирать nginx-sticky-module-ng из исходников.

        • gecube
          /#19384680

          AEP спасибо, что пояснили.
          По пунктам — ничего удивительного, но что-то нужно менять в этом мире.
          1. Это кривой софт. Лучше, если софт реализован в виде отдельного бекенд-приложения, которое инкапсулирует в себе эту историю с реврайтами. Ну, например, uwsgi + python + flask или django.
          2. Пахнет самодурством начальства. Я бы понял, если там речь шла бы про ИБ и про сложность взаимодействия с ops. Но если рациональнее использовать перекомпилированный и собранный в пакет nginx, то стоит рассмотреть предложение об улучшении. Понимаю, что ситуации бывают разные, но я бы от работодателя-самодура бежал сломя голову, благо предложений (нормальных) хватает.
          3. Я так понимаю, что на самом деле это вытекает из п.2. Пересобрать nginx это не страшно )

          • AEP
            /#19384844

            По пункту 2 объяснение от начальства той фирмы на самом деле получено. «Мы пытались что-то раньше собирать из исходников, а потом никого из команды не удавалось элементарно заставить следить за обновлениями безопасности и за совместимостью. А если ставить из пакета, то этим занимается за нас сопровождающий из Debian. И в данном конкретном случае, Apache работает и сам обновляется через unattended-upgrades, не трогай.»

  2. KevlarBeaver
    /#19383560

    На ЛОРе подсказали, HTTP/2-индикатор для Firefox в виде аддона.

  3. blind_oracle
    /#19383578 / +1

    У меня один вопрос: зачем Apache?

    • KevlarBeaver
      /#19383610

      Ну хотя бы потому что про апач такой статьи ещё нет. И не смотря на то, что апач нынче не на коне, он всё ещё используется, на нём крутятся проекты, и HTTP/2 там не помешает. Так почему бы статье не быть?

      • blind_oracle
        /#19383652 / +1

        Во всех тех случаях когда мне нужен по каким-либо причинам Апач — я ставлю перед ним Nginx, который обеспечит HTTP/2 и все остальные плюшки.

        • kolu4iy
          /#19383894

          Напомните, nginx научился сквозную kerberos-авторизацию? Мне, например, это надо внутри конторы для внутреннего же RT. Безусловно, любой средне- и выше нагруженный общедоступный веб-сервис у меня тоже на nginx.

          • gecube
            /#19384682

            Я думаю, что все это можно прикрутить. Другой вопрос, что не зная Вашей конкретной задачи, ничего полезного посоветовать не смогу.

          • blind_oracle
            /#19385114 / +1

            Есть модуль: github.com/stnoonan/spnego-http-auth-nginx-module

            А вообще я, конечно же, имел в виду сервисы торчащие голой попой в интернет и имеющие какую-никакую нагрузку. Внутри энтерпрайзов, возможно, действительно проще поставить Апач сразу с нужными модулями и не заморачиваться со сборкой.

            • KevlarBeaver
              /#19385226

              Вы считаете, что апач, торчащий наружу — это «голой попой»? Если да, то почему? Не придираюсь, мне действительно интересно.

              • blind_oracle
                /#19385266 / +1

                До 2.4 версии Апач был не юзабелен просто по той причине что его можно было уложить открыв ну там, допустим, 300-500-1000 коннектов (смотря какой лимит стоит и сколько памяти) и забив весь PreFork пул. Это сейчас может случиться даже не со злого умысла кулхацкера, а просто потому что браузеры любят KeepAlive коннекты — открывают их много и не закрывают. Аналогично и с MPM Worker.

                Сейчас туда прикрутили epoll/kqueue поверх Worker и назвали это MPM Event, который пытается делать то же самое что и Nginx — держать сотни тысяч коннектов открытыми. На деле это просто костыль, работающий медленнее в 2-3 раза.

                Бенчмарки можно глянуть, например, тут: www.eschrade.com/page/performance-of-apache-2-4-with-the-event-mpm-compared-to-nginx

                • gecube
                  /#19385630

                  Для справедливости: я когда работал в хостинг-компании, то у нас была проблема, что медленные клиенты (например, мобильники) забивали пул соединений nginx… Полагаю, что с правки ситуация попросту была бы хуже и проблемы наступили раньше

                  • blind_oracle
                    /#19385720

                    Конечно, любой пул можно забить:
                    1) Файловые дескрипторы
                    2) Память под открытые сокеты
                    3) Собственно упереться в потолок выставленного worker_connections (но это скорее вопрос конфигурации)

                    Вот только в случае стандартных Prefork/Thread моделей обработки запросов число открытых коннектов на некоем сферическом сервере не сможет превысить единицы тысяч (чаще — гораздо меньше). Ибо даже шедулить 1к тредов\процессов ядру *очень* тяжело — будет большой оверхед.

                    В epoll-like моделях без проблем можно иметь 1 миллион и более коннектов на сервер. Для примера можно взять github.com/valyala/fasthttp:

                    Currently fasthttp is successfully used by VertaMedia in a production serving up to 200K rps from more than 1.5M concurrent keep-alive connections per physical server.

                    (модель работы Golang очень похожа на epoll)

    • ntfs1984
      /#19384374

      Затем что очень много продуктов до сих пор используют рерайты и патчи в .htaccess, к примеру Prestashop.

      Забегая вперед и вангуя ваш ответ, скажу, что ЦА Prestashop'а не будет никогда заморачиваться с какими-то конвертациями .htaccess в nginx (она даже с VPS не будет заморачиваться), ей просто нужно продавать свои банки краски.

      Да и сами по себе апачевские рерайты более читабельны нежели откровенно мудацкий язык описания нджинкса. Недаром конвертеров апач-нжинкс навалом, а вот нжинкс-апач…

      Кроме всего, почти все shared-хостинги используют apache, особливо в контексте ГУЕвых панелек. Он более гибче, и позволяет юзерам играться с некоторыми настройками сервера, не боясь при этом положить всю систему. За границей шареды очень популярны, поскольку дядька продающий котиков или банки краски, в гробу видал этот ваш ssh и apt-get. Он заливает файлы через плагин для Вордпресса, и его нельзя в этом винить, cuique suum.

      В общем все PRO апача — только лишь в его удобстве для клиентов, которые не слишком сильны в серверных работах. Когда нужна скорость или экономия ресурсов — конечно lighttpd впереди планеты всей.

      • gecube
        /#19384384

        К сожалению, на шареде никто не даст крутить пхп-фпм и сильно менять конфигурацию апача (если это вообще возможно). Поэтому — да, htaccess там живёт, и нет — статья клиентам такого хостинга не поможет

        • Mladolaborant
          /#19386944

          На любом уважающем себя шареде сейчас будет стоять сpanel, а она вполне себе позволяет работать и с PHP-FPM и с http/2 — так что с этим проблем не должно быть. Что не меняет, конечно, того что статья клиентам такого, например, хостинга не поможет.

  4. achekalin
    /#19383990

    Судя по заголовку, цель просто странная: http/2 поднимается на веб-сервере, остальные компоненты уравнения (ОС, бекэнд, ЯП) точно не при чем.


    Пишите либо правильные заголовки, либо правильные статьи. А поднять на nginx поддержку http/2 — это одно слово, если https настроен, правда же?

    • KevlarBeaver
      /#19384134 / +1

      Статья о том, как это сделать на Apache. При чём тут nginx?

      • achekalin
        /#19384748

        Да, спросонок не то написал. Ну так и в apache включить http/2 несложно, при чем тут php?

        • KevlarBeaver
          /#19384840

          PHP к настройке HTTP/2 на праве? Не при чём. Вот тут Вы, видимо, правы, нужно было отделить мух от котлет и написать две статьи: о том, как настроить апач и как прикрутить к этой конфигурации — пхп. Но я не отделил.