Могу ли я определить, когда клиент отключился от CGI?

Могу ли я определить, когда клиент отключился от CGI?

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

Есть ли хороший способ обнаружить, когда это произошло? Это даже не обязательно должно быть в пределах самого CGI (и, вероятно, лучше, если это не так — он передаст управление другой программе, которую я не контролирую), но это может быть задание cron, которое запускается время от времени для поиска мертвых соединений для сбора данных.

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

решение1

Обычно вы не можете обнаружить разорванное соединение, пока не начнете писать обратно пользователю. В противном случае ваш процесс продолжит выполнять свою работу, не заметив разрыв соединения со стороны пользователя.Эта почтасвязано, даже если оно говорит о PHP. Концепция должна быть той же.

Вот что вы можете попробовать:

  1. Выполняйте трудоемкую работу в фоновом режиме. Когда пользователь запрашивает CGI, не выполняйте задачу как обычный блокирующий вызов. Просто верните что-нибудь пользователю, чтобы сообщить, что запрос находится в обработке. Конечно, вам нужно найти способ обновить представление или предоставить другую страницу для проверки статуса задания с использованием некоторого идентификатора запроса или IP.
  2. Отправьте данные обратно клиенту как можно скорее и выйдите, если отправка не удалась (индикация разрыва соединения). Например, вы можете отправлять ход выполнения задания каждые несколько секунд или минут.

Если вы сохраните текущие запущенные задания в базе данных, вы можете сохранить идентификатор запроса и/или IP-адрес клиента. Таким образом, вы можете обнаружить и игнорировать дублирующиеся запросы к одному и тому же ресурсу, сообщая пользователю «ваш запрос находится в обработке».

решение2

Предупреждение: эта информация может быть устаревшей. См. последний абзац.

Я помню, что у меня была такая же проблема, и я решил ее с помощьюнф(без заголовка анализа) CGI-скрипт.

Обычно apache собирает все заголовки из вашего скрипта, и когда заканчивает чтение заголовков, дополняет их некоторыми стандартными заголовками, которые вы не предоставили. Это также означает, что пока вы не закончите заголовки, apache вообще ничего не отправляет клиенту.

С помощью скрипта nph вам придется предоставить все заголовки, но Apache немедленно отправит их клиенту и отправит вашему скрипту CGI сигнал SIGPIPE, как только клиент отключится. Таким образом, вы можете отправлять некоторые X-Slowly-Counting-Part-nnn: yesзаголовки каждые несколько секунд, чтобы предотвратить тайм-ауты на клиенте, и вы получите уведомление, если клиент разорвет соединение.

Это все еще оставляет проблему: вам придется сначала отправить HTTP-статус, но если вы отправите «Content-Length: 0» или, может быть, «Content-Length: 1» и закроете соединение, не отправив никакого контента, ваш загрузчик файловдолженпредположить наличие ошибки в сети и действовать соответствующим образом.

Вероятно, вам придется передать вывод другой программы через свой процесс, но это не должно сильно повлиять на производительность, по крайней мере, если вы работаете в Linux и используете системный sendfile(2)вызов.

Проблема со всем этим в том, что я использовал его по крайней мере 10 лет назад, возможно, на Apache 1.3, и гугление apache cgi nphне дало ничего полезного. Так что, возможно, функция nph была удалена в то время - но, может быть, и нет, признаю, я не очень внимательно искал.

решение3

Старый вопрос, но у меня была та же проблема, и я решил ее, проверив, установлено ли соединение:

В моем случае я запускаю один bash-скрипт на сервере. Переменные env экспортируются mod_cgi. Я считаю, что это решение будет работать для любой программы/скрипта, работающего на CGI.

ss -nt state established "( sport = :$SERVER_PORT and dport = $REMOTE_ADDR:$REMOTE_PORT )" 2>/dev/null | grep -q "$REMOTE_ADDR:$REMOTE_PORT"
if [ "$?" -ne '0' ]; then
     # Client closed browser/connection
fi

Связанный контент