Могу ли я определить, когда клиент отключился от CGI?
У меня достаточно ресурсоемкий CGI, который довольно долго занимает отправку данных. Мы видели довольно много случаев, когда нетерпеливые люди перезагружались пару раз, что затем запускало дополнительные запуски CGI для загрузки, или случаи, когда клиент прерывал работу и сбрасывал соединение, но CGI продолжал работать.
Есть ли хороший способ определить, когда это произошло? Он даже не должен находиться внутри самого CGI (и, вероятно, лучше, если это не так - он передает другую программу, которую я не контролирую), но может быть работой cron, которая запускается время от времени искать мертвые соединения, чтобы пожинать.
В настоящее время я использую Apache, но это такая проблема, что я хотел бы запустить какой-нибудь другой веб-сервер, если у него есть условия для его решения (или способ позволить мне отслеживать проблему).
3 ответа
Обычно вы не можете обнаружить разорванное соединение, пока не начнете писать обратно пользователю. В противном случае ваш процесс продолжит выполнять свою работу, не заметив прерывания соединения со стороны пользователя. Этот пост связан, даже если он говорит о PHP. Концепция должна быть такой же.
Есть возможные вещи, которые вы можете попробовать:
- Делайте трудоемкую работу в фоновом режиме. Когда пользователь запрашивает CGI, не выполняйте задачу как обычный блокирующий вызов. Просто верните что-нибудь пользователю, чтобы сообщить, что запрос обрабатывается. Конечно, вам нужно найти способ обновить представление или предоставить другую страницу для проверки статуса работы, используя какой-либо идентификатор запроса или IP-адрес.
- Отправьте данные обратно клиенту как можно скорее и выйдите, если не удалось отправить (указание на разорванное соединение). Например, вы можете отправлять информацию о ходе работы каждые несколько секунд или минут.
Если вы сохраняете текущие задания в базе данных, вы можете сохранить идентификатор запроса и / или IP-адрес клиента. Таким образом, вы можете обнаруживать и игнорировать повторяющиеся запросы к одному и тому же ресурсу, говоря пользователю "ваш запрос обрабатывается".
Старый вопрос, но у меня возникла та же проблема, и я решил проверить, установилось ли соединение:
В моем случае я запускаю один сценарий 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
Предупреждение: эта информация может быть устаревшей. Смотрите последний абзац.
Я помню, что у меня была такая же проблема, и я решил ее с помощью сценария CGI nph (без заголовка разбора).
Обычно 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 была удалена в то же время - но потом, может быть, нет, я признаю, я выглядел не очень сложно.