Tomcat, HTTP Keep-Alive и Java HttpsUrlConnection - PullRequest
17 голосов
/ 22 декабря 2011

У меня есть два сервера Tomcat, которым необходимо поддерживать постоянное соединение для сокращения SSL-квитирования. Один сервер (прокси-сервер) находится в демилитаризованной зоне, а другой находится в безопасности за другим брандмауэром. Прокси-сервер в основном просто запускает простой сервлет, который выполняет некоторую проверку работоспособности перед отправкой запросов на защищенную машину. По первому требованию машины обмениваются сертификатами перед выполнением реальной работы. Поэтому я хотел бы поддерживать постоянное соединение с таймаутом в несколько минут.

Для связи с защищенным сервером сервлет прокси-сервера использует HttpsUrlConnection. Я настроил WireShark и заметил, что независимо от значения keepAliveTimeout, которое я установил для соединителя на защищенной машине, соединение TCP закрывается примерно через 5 или 10 секунд. Похоже, это число совпадает с тем, что я прочитал, по умолчанию, и как Java обрабатывает HTTP Keep-Alive. Эта ссылка объясняет, что Java соблюдает время ожидания Keep-Alive, если оно отправлено сервером, в противном случае для закрытия соединения используется 5 секунд (прямые подключения) или 10 секунд (прокси-подключения).

Я пытаюсь понять, как заставить Tomcat отправить заголовок Keep-Alive. Не Connection: Keep-Alive, а Keep-Alive: timeout=x.

Я экспериментировал с HTTP-сервером Apache, и изменение keepAliveTimeout в httpd.conf приводит к тому, что заголовок Keep-Alive меняет свое значение тайм-аута. Кроме того, Java соблюдает это время ожидания.

ОБНОВЛЕНИЕ (23.12.11): После нескольких экспериментов я попытался создать быстрый и грязный код, используя Apache HttpClient (3.1) вместо HttpsUrlConnection. Похоже, что HttpClient, когда он настроен на использование Keep-Alive, просто ждет, пока сервер закроет соединение. Я не знаю, как долго это будет ждать. Я снимаю, чтобы поддерживать HTTP-соединение живым в течение 3-5 минут.

Ответы [ 3 ]

8 голосов
/ 17 марта 2012

Я смог использовать HttpClient 3.1, чтобы держать HTTP-соединение открытым в течение 5 минут, установив keepAliveTimeout в коннекторе Tomcat на 300000. Я проверил с помощью WireShark, что сервер прервет соединение, в то время как HttpClient просто подождет. Последующие запросы через HttpClient повторно используют существующее TCP-соединение (избегая дальнейшего установления SSL-квитирования). Ключевым моментом здесь является наличие единственного экземпляра HttpClient (то есть, не создавая его каждый раз). Это может быть очевидно для большинства, но я не был уверен, какой будет механика API для HTTPClient. Короче говоря, создайте один экземпляр HttpClient и для каждого запроса (POST, GET и т. Д.) Создайте новый PostMethod, GetMethod и т. Д. Это приведет к повторному использованию TCP-соединения.

5 голосов
/ 24 января 2013

В Tomcat мне удалось установить заголовки в моем HttpServelet, используя HttpServletResponse.addHeader (), например так:

  response.addHeader("Connection", "Keep-Alive");
  response.addHeader("Keep-Alive", "timeout=60000");

Я подтвердил с WireShark, что это работает с HttpUrlConnection на стороне клиента. Он не работает, если вы не установили заголовок «Соединение», поэтому вам нужно установить оба.

2 голосов
/ 26 января 2012

Java API Http(s)UrlConnection легко обрабатывает информацию Keep-Alive и управляет пулом соединений для каждого хоста сервера в соответствии с , следуя подробному объяснению (читайте внимательно - каждая деталь важна).

В этом случае ваш код должен полностью прочитать буферы, закрыть потоки и ошибку чтения в случае IOException.

Конечно, у HttpClient меньше ограничений, но лучший способ справиться с вашей ситуацией - это использовать MultiThreadedHttpConnectionManager благодаря , следуя указаниям .

...