Ответ 1
Плохая новость: вы почти наверняка не сможете решить свою проблему, как вы хотите ее решить. Сигнал FastCGI, отправленный, когда клиент закрывает соединение до получения запроса, FCGI_ABORT_REQUEST
Веб-сервер прерывает запрос FastCGI, когда клиент HTTP закрывает в то время как запрос FastCGI работает от имени этого клиента. Ситуация может показаться маловероятной; большинство запросов FastCGI будет иметь короткое время отклика, с выходом веб-сервера буферизация, если клиент работает медленно. Но приложение FastCGI может быть задержка связи с другой системой или выполнение сервера толчок.
К сожалению, он не выглядит как оригинальная реализация fast-cgi, а PHP-FPM поддерживают сигнал FCGI_ABORT_REQUEST и поэтому не могут быть прерваны.
Хорошая новость заключается в том, что существуют лучшие способы решения этой проблемы. В принципе, у вас никогда не должно быть запросов, требующих много времени для обработки. Вместо этого, если запрос требует много времени для обработки, вы должны:
- Вставьте его в очередь задач, которые необходимо обработать.
- Верните идентификатор задачи клиенту.
- Периодически проводите опрос клиентов, чтобы узнать, завершена ли эта "задача", и когда она будет завершена, покажите результаты.
В дополнение к этим 3 основным вещам - если вы обеспокоены тратой ресурсов системы, когда клиент больше не интересуется результатами запроса, вы должны добавить:
- Разбивайте задачи на небольшие части работы и перемещайте задачи только из одного состояния работы на другое, если клиент все еще запрашивает результат.
Вы не говорите, какова ваша давно работающая задача - пусть притворяется, что она загружает большой файл изображения с другого сервера, манипулирует этим изображением, а затем сохраняет его в S3. Таким образом, состояния для этой задачи будут выглядеть примерно так:
TASK_STATE_QUEUED
TASK_STATE_DOWNLOADING //Moves to next state when finished download
TASK_STATE_DOWNLOADED
TASK_STATE_PROCESSING //Moves to next state when processing finished
TASK_STATE_PROCESSED
TASK_STATE_UPLOADING_TO_S3 //Moves to next state when uploaded
TASK_STATE_FINISHED
Итак, когда клиент отправляет исходный запрос, он возвращает идентификатор taskID, а затем, когда он запрашивает состояние этой задачи, либо:
- Сервер сообщает, что задача все еще обрабатывается
или
- Если он находится в одном из следующих состояний, клиентский запрос удаляет его до следующего состояния.
то есть.
TASK_STATE_QUEUED => TASK_STATE_DOWNLOADING
TASK_STATE_DOWNLOADED => TASK_STATE_PROCESSING
TASK_STATE_PROCESSED => TASK_STATE_UPLOADING_TO_S3
Таким образом, только запросы, которые клиент интересует, продолжают обрабатываться.
btw Я настоятельно рекомендую использовать что-то, предназначенное для работы в качестве очереди для хранения очереди задач (например, Rabbitmq, Redis или Gearman), а не просто используя MySQL или любую базу данных. В принципе, SQL просто не так хорош в том, чтобы действовать как очередь, и вам было бы лучше использовать соответствующую технологию с самого начала, вместо того, чтобы использовать неправильную технологию для запуска, а затем придется ее заменять в чрезвычайной ситуации, когда ваша база данных становится перегружен при попытке сделать сотни вложений, обновлений в секунду для управления задачами.
В качестве побочного преимущества, разбивая долгий процесс работы на задачи, становится очень легко:
- Посмотрите, где тратится время обработки.
- Смотрите и определите колебания во время обработки (например, если CPUS достигнет 100% -ной загрузки, тогда размер изображения будет значительно увеличиваться).
- Выбросьте ресурсы на медленных шагах.
- Вы можете отправлять сообщения о состоянии обновления клиенту, чтобы они могли видеть прогресс в задаче, что дает лучший UX, а не просто сидит там "ничего не делает".