
На самом деле, в настоящее время я исследую долго работающие соединения веб-приложения на базе Java/Tomcat. После исключения любых внутренних или прикладных причин я перехожу к сетевому уровню. Причина, по которой я исследую эту проблему, заключается в том, что у нас есть, по-видимому, случайные всплески в нашем мониторинге времени отклика. Во время исследования я обнаружил, что это поведение вовсе не такое уж случайное, а вызвано определенными клиентскими HTTP-запросами. Особенность этих соединений в том, что все они исходят с одного и того же IP-адреса и, похоже, используют Bluecoat Proxy, потому что я вижу HTTP-заголовок x-bluecoat-via.
Как я уже сказал, само приложение работает нормально, только конец соединения (с точки зрения Tomcat) кажется каким-то образом задержанным. Сервер не общается напрямую с клиентом, а находится за F5 Loadbalancer, который должен кэшировать ответы (чего может не произойти из-за заголовка идентификации accept-encoding и фактического ответа, который слишком велик для буфера).
Я получил дамп TCP, но из-за досадной ошибки в настоящее время я вижу только пакеты из LB на сервер приложений, а не фактические пакеты, отправляемые с сервера приложений.
Дамп содержит несколько запросов на одном и том же соединении TCP/IP, что связано с пулом соединений, выполненным F5. Последний HTTP-запрос на этом соединении — это фактическое соединение, которое было отмечено как долго работающее (925836.442 мс) в нашем журнале. Я вижу пакеты запросов, серию ACK, что наводит меня на мысль, что сервер приложений пишет свой ответ, а затем, наконец, два пакета FIN, ACK, за которыми следует RST, ACK, который является последним пакетом, отправленным F5.
С точки зрения времени все это происходит в течение 250 мс, последний пакет отправляется за 15 минут и 13 секунд до того, как я вижу журнал ответа на сервере приложений, который записывается после того, как Tomcat предположительно завершил ответ.
У меня сейчас немного идей, и есть пара открытых вопросов:
Есть ли причина, по которой Linux будет оставлять открытым соединение, получившее RST, и не сообщать об этом прикладному уровню?
Есть ли другой тайм-аут, который может привести к такому поведению? Если бы это был тайм-аут повторной передачи TCP, я бы увидел больше RST от LB.
Есть ли еще идеи, почему закрытое соединение на проводе может привести к тому, что на прикладном уровне соединение останется открытым?
Как может что-то, происходящее на прикладном уровне (специальный HTTP-запрос), привести к воспроизводимому поведению на транспортном уровне?
Может быть, я на совершенно неверном пути и это проблема с поддержанием соединения внутри Tomcat?
решение1
Я не могу помочь с сетевым уровнем, но на Tomcat есть несколько мест, где это можно настроить.http://tomcat.apache.org/connectors-doc/reference/workers.html. Вы можете попробовать переписать тайм-аут и настроить его на закрытие соединения по истечении определенного времени.
По ссылке вы также найдете конфигурации балансировщика нагрузки, которые могут быть полезны в вашем сценарии.