HTTP Proxy/FastCGI/SCGI не закрывает соединение, когда клиент отключен - ошибка или функция?

Я работаю над поддержкой Comet для CppCMS framework через длинные опросы XMLHttpRequest. Во многих случаях такой запрос закрывается клиентом до того, как был получен какой-либо ответ от сервера - например, страница закрыта, пользователь переходит на другую страницу или просто обновляется.

На стороне сервера я ожидаю, что получу уведомление о том, что соединение разорвано. Я тестировал приложение через 3 разъема: FastCGI, SCGI и простой HTTP Proxy.

Из 3 основных веб-серверов UNIX, Apache2, lighttpd и Nginx, только последний имел закрытое соединение, как и ожидалось, что позволило моему приложению удалить запрос из очереди ожидания - это работало как для коннекторов FastCGI, так и для HTTP-прокси. (Nginx по умолчанию не имеет модуля scgi).

Другие, Apache и Lighttpd, не закрывают соединение и не сообщают бэкэнду об отключенных клиентах, как если бы клиент все еще был в сети. Это происходит для всех 3 поддерживаемых API: FastCGI, SCGI и HTTP Proxy.

Я открыл проблему для Lighttpd, но меня больше всего удивляет тот факт, что Apache - зрелый и хорошо поддерживаемый веб-сервер, такой как lighttpd, и не раскрывает серверную часть сервера, которую ушел клиент.

Вопросы:

  1. Это ошибка или это особенность? Есть ли причина не закрывать соединение между веб-сервером и серверной частью приложения?
  2. Существуют ли реальные приложения Comet, работающие за этими серверами через бэкэнды FastCGI/SCGI/HTTP-Proxy?
  3. Если вышеизложенное верно, как они справляются с этой проблемой? Я понимаю, что могу тайм-аутить все соединения каждые 10 секунд, но я бы хотел, чтобы они простаивали до тех пор, пока клиент их слушает - потому что это позволяет легче масштабировать - каждое соединение очень дешевое - стоимость составляет только открытый сокет.

Спасибо!

2 ответа

Решение

(1) Особенность. Или, более конкретно, выпадение из деталей реализации.

Соединение TCP/IP не требует постоянного потока трафика туда и обратно. Таким образом, невозможно узнать, что клиент ушел, если (а) клиент не сообщит вам, что закрывает соединение, или (б) тайм-аут.

(2) Я не особенно знаком с Comet или CppCMS. Но, да, за упомянутыми веб-серверами работают все виды серверов CMS, и все они должны иметь дело с этой проблемой (и, да, это боль).

(3) Тайм-ауты - единственный способ, но вы можете, так сказать, смягчить боль. Попросите клиента пропинговать сервер через соединение каждые N секунд, если в противном случае нет активности. Не нужно ничего делать, и вы можете прикрепить материал к ответу; уведомления о одновременных изменениях или что вам нужно.

Вы правы в том, что удивительно, что mod_fastcgi не поддерживает сообщение бэкэнду о том, что Apache обнаружил разъединение или истекло время ожидания соединения. И ты не первый, кто встревожен.

Второй патч на этой странице должен исправить эту проблему:

http://osdir.com/ml/web.fastcgi.devel/2006-02/msg00015.html

http://ncannasse.fr/blog/tora_comet

У меня нет конкретной информации для вас, но в этой статье упоминается, что они могут определить, когда клиент отключился от Apache. Увидеть tora.Queue, И похоже, что источник доступен в CVS neko, так что вы можете найти некоторые подсказки там. Удачи.

Другие вопросы по тегам