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

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

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

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

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

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

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

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

Если вы сохраняете текущие выполняемые задания в базе данных, вы можете сохранить идентификатор запроса и / или 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

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

Я помню, что у меня была такая же проблема, и я решил ее с помощью nph (без синтаксического заголовка) 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, и поискал в Google apache cgi nph ничего полезного не принес. Так что, возможно, функция nph тем временем была удалена - но тогда, может быть, и нет, признаю, я не очень сильно смотрел.