Обнаружение прерванных запросов в HttpServlet

Есть ли способ узнать, прерван ли HttpServletRequest?

Я пишу мгновенное браузерное приложение (какой-то чат): клиенты запрашивают новые события в цикле, используя AJAX-HTTP-запросы. Сервер (Tomcat) обрабатывает запросы в HttpServlet. Если для этого клиента нет новых событий, сервер задерживает ответ до тех пор, пока не поступит новое событие или не истечет время ожидания (30 секунд).

Теперь я хочу определить клиентов, которые больше не опрашиваются. Поэтому я запускаю кик-таймер в конце запроса, который останавливается при поступлении нового запроса. Если клиент закрывает окно браузера, TCP-соединение закрывается, и HTTP-запрос прерывается.

Проблема: Клиент не сталкивается с тайм-аутом удара, потому что сервлет все еще обрабатывает запрос на событие - бездействует и ожидает события или тайм-аута.

Было бы здорово, если бы я мог каким-то образом прослушивать события прерывания соединения, а затем уведомлять об ожидающем запросе, чтобы остановить его. Но я не смог найти ничего подобного в HttpServletRequest или HttpServletResponse...


person Escudo    schedule 06.12.2010    source источник
comment
Какой API/фреймворк вы используете для обработки асинхронных запросов и/или отправки HTTP-запросов? Ваш вопрос звучит/читается очень странно, потому что это не то, как обычно работает стандартный API Servlet, поэтому я предположил, что вы используете какой-то API/фреймворк поверх этого (например, Comet, Atmosphere, Servlet 3.0 async и т. д.) . Либо так, либо вы делаете что-то совершенно неправильно.   -  person BalusC    schedule 07.12.2010
comment
Я не использую никаких фреймворков. Это так просто: ::::::: UpdateServlet doGet-Method (1) получает updateClient из сеанса (2) получает List‹Event› из updateClient (3) Печатает закодированные события. ::::::: UpdateClient метод getEvents (1) ожидает, если нет ожидающих событий (2) возвращает события ::::::: UpdateClient метод addEvent (1) добавляет событие в список (2) уведомляет ожидающие потоки Запросы обрабатываются одновременно в разных потоках.   -  person Escudo    schedule 07.12.2010
comment
Это работает довольно хорошо и мгновенно. :-)   -  person Escudo    schedule 07.12.2010
comment
Несмотря на это, терминология в вашем вопросе определенно сбивает с толку.   -  person BalusC    schedule 07.12.2010


Ответы (3)


Это, вероятно, больше не поможет OP, но может помочь другим, пытающимся обнаружить прерванные HTTP-соединения в HttpServlet в целом, поскольку у меня была аналогичная проблема, и я наконец нашел ответ.

Ключевым моментом является то, что когда клиент отменяет запрос, обычно единственный способ для сервера узнать об этом — отправить некоторые данные обратно клиенту, что в этом случае не удастся. Я хотел определить, когда клиент перестает ждать долгих вычислений на сервере, поэтому в итоге я периодически записывал один символ в тело ответа через средство записи HttpServletResponse. Чтобы принудительно отправить данные клиенту, вы должны вызвать HttpServletResponse.flushBuffer(), который выдает ClientAbortException, если соединение прервано.

person andysh    schedule 12.07.2018

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

Я не знаю, есть ли надежные способы опросить «живучесть» соединения (например, resp.getOutputStream, не вызывающий исключение), и если да, то какой способ лучше (наиболее надежный, наименее загруженный ЦП).

person Markus A.    schedule 20.02.2012

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

person Jon Onstott    schedule 06.12.2010
comment
Спасибо за ваш ответ. Я знаю об этом недостатке открытых соединений. Проблема в том, что я хочу, чтобы клиенты были очень быстро проинформированы о событиях. Если бы я не использовал подход ожидания, интервал опроса должен был бы быть небольшим. Это снова приведет к большому трафику... - person Escudo; 07.12.2010
comment
Ах я вижу. Может быть есть способ проверить прерывания (извините, я точно не знаю). Технология push, такая как Comet, или что-то, что обертывает Comet, кажется идеальной. - person Jon Onstott; 07.12.2010
comment
Да, я в основном пытаюсь реализовать эту концепцию самостоятельно, чтобы иметь больше гибкости. Мгновенный аспект работает нормально, но оповещение о включении/выключении отстает от оповещения о прерывании. Спасибо за ваши комментарии. :-) - person Escudo; 07.12.2010