PHP, работающий как приложение FastCGI (php-cgi) - как выдавать параллельные запросы?


ИЗМЕНИТЬ: Обновить - прокрутите вниз
ПРАВКА 2: Обновление - проблема решена


Некоторая справочная информация:

Я пишу свой собственный веб-сервер на Java, и пару дней назад я спросил, как именно Apache взаимодействует с PHP, чтобы я мог реализовать поддержку PHP. Я узнал, что FastCGI - лучший подход (поскольку mod_php - это не вариант). Итак, я просмотрел спецификацию протокола FastCGI и сумел написать рабочий Оболочка FastCGI для моего сервера. Я протестировал phpinfo(), и он работает, на самом деле все функции PHP, похоже, работают просто отлично (публикация данных, сеансы, дата/время и т. Д. и т. Д.).

Мой веб-сервер может одновременно обслуживать запросы (т.Е. пользователь1 может извлекать file1.html в то же время, когда пользователь2 запрашивает some_large_binary_file.zip ), он делает это, создавая новый поток Java для каждого запроса пользователя (завершается при завершении или отмене соединения пользователя с клиентом).

Однако это не может разберитесь с 2 (или более) Запросы FastCGI одновременно. Что он делает, так это ставит их в очередь, поэтому, когда запрос 1 будет выполнен сразу после этого, он начнет обрабатывать запрос 2. Я протестировал это с помощью 2 PHP-страниц, одна из которых содержит sleep(10), а другая phpinfo().

Как бы я справился с несколькими запросами, как я знаю, это можно сделать (PHP в IIS работает как FastCGI, и он отлично справляется с несколькими запросами).

Еще немного информации:

Я кодирую под windows и мой пакетный файл, используемый для выполнения php-cgi.exe содержит:

set PHP_FCGI_CHILDREN=8
set PHP_FCGI_MAX_REQUESTS=500
php-cgi.exe -b 9000

Но это не порождает 8 детей, служба просто завершается после 500 запросов.

Я провел исследование и из Википедии:

Обработка нескольких запросов одновременно достигается либо с помощью одного соединения с внутренним мультиплексированием (т. е. множественный запросы по одному соединению) и/или с помощью нескольких соединений

Теперь очевидно, что несколько подключений не работают для меня, так как каждый раз, когда клиент запрашивает что-то, связанное с FastCGI, он создает новый сокет для приложения FastCGI, но он не работает одновременно (вместо этого он ставит их в очередь).

Я знаю, что внутреннее мультиплексирование запросов FastCGI при одном и том же соединении выполняется путем выдачи каждого уникального запроса FastCGI с другим идентификатором запроса . (также смотрите последние 3 абзаца заголовка "Протокол связи" в эта статья).

Я не тестировал это, но как бы я это реализовал? Я так понимаю, мне нужен какой-то поток Java FastCGI, который содержит какую-то карту и статическую функцию, которую я могу использовать для добавления запросов. Затем в функции run() потока у него будет цикл while, и для каждого цикла он будет проверять, содержит ли Карта новые запросы, если это так, он назначит им идентификатор запроса и запишет их в поток FastCGI. А затем дождитесь ввода и т. Д. И т. Д., Как вы можете видеть, это становится слишком сложным.

Кто-нибудь знает правильный способ сделать это? Или вообще какие-нибудь мысли? Большое спасибо.

Обратите внимание, что при необходимости я могу предоставить код для моей оболочки FastCGI.


Обновление:

В принципе, я скачал nginx и настроил его на использование PHP в качестве приложения FastCGI, и он тоже страдал от той же проблемы, что и мой сервер. Он не мог обрабатывать одновременные запросы PHP. Это заставляет меня поверить в мой код на самом деле это правильно. Значит, что-то не так с PHP, или я неправильно его настраиваю. Может быть, это потому, что я использую Windows, потому что некоторые пользователи lighttpd утверждают, что Windows не может правильно обрабатывать FastCGI (это не имеет особого смысла). Я скоро установлю Linux и сообщу о любом прогрессе в этом.

Author: Jeff Atwood, 2010-05-08

3 answers

Хорошо, мне удалось найти причину проблемы. Это был совсем не мой код. Это PHP, он не может создавать дополнительные php-cgi под Windows при запуске в режиме FastCGI, в Linux он работает отлично, я просто указал свой сервер на свой IP-адрес linux, и у него не было проблем с одновременными запросами FCGI. Отстой, но я думаю, что так оно и есть...

После этого я углубился в исходный код PHP и обнаружил, что раздел кода, который отвечает на PHP_FCGI_CHILDREN, был инкапсулирован #ifndef WIN32, поэтому разработчики должны знать об этой проблеме

 7
Author: Waleed Amjad, 2011-05-22 10:56:15

Привет, это немного запоздало, я написал спавнер для php-cgi.exe в Windows не идеально, но это может быть то, что вам нужно. Проверьте это по адресу здесь.

 2
Author: nosam, 2011-05-22 02:25:10

Re: spawn - скрипт php на python...

Спасибо @nosam, что действительно помогло.
Для тех, кто хочет быстро заставить его работать, вам понадобится следующее (если 64-битная система)

ActivePython-2.7.2.5-win64-x64.msi
ActivePython-2.7.2.5-win64-x64.msi
pywin32-217.win-amd64-py2.7.exe

У ActivePython нет более старых версий на их www, поэтому вам нужно будет немного погуглить, чтобы найти рабочее зеркало (их там много)

Как только вы загрузите src из bitbucket, возможно, вам потребуется отредактировать spawn-php.py (чтобы исправить интервал между вкладками), так как бит-ведро, казалось, испортило вкладку в файле, не позволяя ей работать.

В целом, это спасло мой день для загруженного маленького веб-сайта Windows с использованием nginx +fast-cgi.

Спасибо, приятель!

 2
Author: David, 2012-06-23 12:31:46