Назад | Перейти на главную страницу

Странные ответы Apache PHP-FPM с Proxy enablereuse = on

При включении <Proxy ... enablereuse=on max=10> Я начинаю получать странные ответы. При обновлении текущей страницы основной запрос загружает разные ответы; например, пустая страница, ответы, предназначенные для отдельного клиента, или ответ 404 из файла CSS на запрошенной странице.

Удаление enablereuse, исправляет странные ответы, но предотвращает одновременные запросы от одного и того же пользователя, то есть каждый запрос обслуживается индивидуально.

Например: открытие двух вкладок браузера для двух разных URL-адресов в одном домене vhost, если загрузка первой запрошенной страницы занимает 5 секунд, она не загрузит вторую вкладку, пока первая не будет завершена.

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

Серверная среда

CentOS 6.10 x64
php 5.6.37 Remi
Apache 2.4.33 IUS

Конфигурация события MPM

<IfModule mpm_event_module>
    ServerLimit              100
    StartServers             4
    ThreadLimit              64
    MaxRequestWorkers        100
    MinSpareThreads          25
    MaxSpareThreads          75
    ThreadsPerChild          25
    MaxConnectionsPerChild   1000
    ListenBacklog       511
</IfModule>

Конфигурация виртуального хоста (1 из 4 - все идентично, кроме IP-адреса, UDS и ServerName)

<VirtualHost 192.168.1.71:443>
    ServerName example.com:443
    DocumentRoot /home/example/example.com
    <IfModule mod_ssl.c>
        SSLEngine on
        SSLCertificateFile /etc/httpd/ssl/certs/example.crt
        SSLCertificateKeyFile /etc/httpd/ssl/private/example.key
        SSLCertificateChainfile /etc/httpd/ssl/certs/example.ca-bundle
        <IfModule mod_setenvif.c>
            SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
        </IfModule>
        <IfModule mod_headers.c>
            Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
        </IfModule>
    </IfModule>
    <Directory "/home/example/example.com">
        AllowOverride All
        Require all granted
    </Directory>
    <IfModule mod_proxy_fcgi.c>
        <FilesMatch \.php$>
            <If "-f %{REQUEST_FILENAME}">
                SetHandler "proxy:unix:/var/run/example.sock|fcgi://127.0.0.1/"
            </If>
        </FilesMatch>
        <Proxy "fcgi://127.0.0.1" enablereuse=on max=10>
            ProxySet timeout=7200
        </Proxy>
    </IfModule>
</VirtualHost>

Конфигурация пула PHP-FPM (1 из 4 все идентичные, кроме UDS)

[example_com]
user = example
group = example
listen = /var/run/example.sock
listen.owner = example
listen.group = apache
listen.mode = 0660

pm = dynamic
pm.max_children = 20
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 20
pm.max_requests = 1000

security.limit_extensions = .php

Я пробовал использовать TCP-прокси вместо UDS из-за того, что другие сообщения комментируют проблемы с UDS, которые не поддерживаются, но проблема сохраняется:

<IfModule mod_proxy_fcgi.c>
    <FilesMatch \.php$>
        <If "-f %{REQUEST_FILENAME}">
            SetHandler "proxy:fcgi://127.0.0.1:9000/"
        </If>
    </FilesMatch>
    <Proxy "fcgi://127.0.0.1:9000" enablereuse=on max=10>
        ProxySet timeout=7200
    </Proxy>
</IfModule>

Также попытался изменить конфигурацию PHP-FPM, установив pm на dynamic, ondemand и static с соответствующими изменениями процесса.


Я определил, что ограничение одновременных запросов связано с сеансами PHP и блокировкой, налагаемой на сеансы на основе файловой системы. Однако проблема не соответствует полученным мной странным ответам.

Из документации Apache 2.4: включить повторное использование подключения к бэкэнду FCGI, например PHP-FPM

Имейте в виду, что PHP-FPM (на момент написания, февраль 2018 г.) использует модель prefork, а именно, каждый из его рабочих процессов может обрабатывать одно соединение за раз. По умолчанию mod_proxy (настроенный с помощью enablereuse = on) разрешает пул соединений ThreadsPerChild подключений к бэкэнду для каждого процесса httpd при использовании многопоточного mpm (например, worker или event), поэтому следует учитывать следующие варианты использования:

Under HTTP/1.1 load it will likely cause the creation of up to MaxRequestWorkers connections to the FCGI backend.
Under HTTP/2 load, due to how mod_http2 is implemented, there are additional h2 worker threads that may force the creation of other backend connections. The overall count of connections in the pools may raise to more than MaxRequestWorkers.

Максимальное количество рабочих процессов PHP-FPM должно быть настроено с умом, так как есть вероятность, что все они в конечном итоге будут «заняты» обработкой простаивающих постоянных подключений, без каких-либо мест для установки новых, и взаимодействие с конечным пользователем будет быть грудой таймаутов HTTP-запросов.

Поэтому я упоминаю не использовать enablereuse с mod_proxy_fcgi + php-fpm.