Tomcat иногда возвращает ответ без заголовков HTTP - PullRequest
0 голосов
/ 27 ноября 2018

Я исследую проблему, когда Tomcat ( 7.0.90 7.0.92) очень редко возвращает ответ без заголовков HTTP.

В соответствии с перехваченными пакетами Wireshark послеTomcat получает запрос, он просто возвращает только тело ответа.Он не возвращает ни строку состояния, ни заголовки ответа HTTP.

Он заставляет нижестоящий экземпляр Nginx выдавать ошибку «восходящий не отправил недопустимый заголовок HTTP / 1.0 при чтении заголовка ответа из восходящего потока», возвращает ошибку 502 клиенту изакройте соответствующее соединение http между Nginx и Tomcat.

Что может быть причиной такого поведения?Есть ли возможность, которая заставляет Tomcat вести себя таким образом?Или может быть что-то, что лишает HTTP-заголовки при некоторых условиях?Или Wireshark не удалось захватить кадры, которые содержат заголовки HTTP?Любой совет, чтобы сузить, где проблема, также высоко ценится.

Это скриншот Wireshark "Follow HTTP Stream", который показывает проблемный ответ:

enter image description here

РЕДАКТИРОВАТЬ:

Это снимок экрана «TCP Stream» соответствующей части (только ответ).Кажется, что фрагменты во втором ответе от последнего выглядят хорошо:

enter image description here

EDIT2:

Я переправил этот вопрос в список рассылки пользователей Tomcat и получил несколько предложений от разработчиков:

http://tomcat.10.x6.nabble.com/Tomcat-occasionally-returns-a-response-without-HTTP-headers-td5080623.html

Но я пока не нашел правильного решения.Я все еще ищу идеи для решения этой проблемы ..

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

Проблемы, с которыми вы сталкиваетесь, связаны с конвейерной обработкой нескольких запросов по одному соединению с восходящим потоком, что объясняется вчерашним ответом здесь Eugène Adell .

Является ли это ошибкой в ​​nginx,Tomcat, ваше приложение или взаимодействие любой из вышеперечисленных комбинаций, вероятно, будет обсуждением для другого форума, но сейчас давайте рассмотрим, какое решение будет наилучшим:

МожетВы публикуете свою конфигурацию nginx?В частности, если вы используете keepalive и значение по умолчанию proxy_http_version в nginx?- cnst 1 час назад

@ cnst Я использую proxy_http_version 1.1 и keepalive 100 - Кохей Нозаки 1 час назад

Согласно более раннему ответуна несвязанный вопрос здесь на SO , но при этом разделяя параметры конфигурации, как указано выше, вы можете пересмотреть причины использования функции keepalive между внешним балансировщиком нагрузки (например, nginx) и внутренним приложениемсервер (например, tomcat).

Согласно объяснению * keepalive ServerFault в контексте nginx , функция поддержки активности в контексте upstream nginx даже не поддерживалась до самого- совсем недавно, в годы разработки nginx.Зачем?Это потому, что существует очень мало допустимых сценариев использования keepalive, когда в основном быстрее установить новое соединение, чем ждать, пока существующее станет доступным:

  • Когда задержка между клиентом исервер составляет порядка 50 мс +, keepalive позволяет повторно использовать учетные данные TCP и SSL, что приводит к очень значительному ускорению, поскольку для подготовки соединения для обслуживания HTTP-запросов не требуется никаких дополнительных обратных соединений.

    Вот почему вы никогда не должны отключать keepalive между клиентом и nginx (управляется через http://nginx.org/r/keepalive_timeout в http, server и location контекстах).

  • Но когда задержка между внешним прокси-сервером и внутренним сервером приложений составляет порядка 1 мс (0,001 с), использование keepalive - это рецепт погони за гейзенгами без каких-либо преимуществ, как дополнительная задержка в 1 мс, чтобы установитьСоединение также может быть меньше, чем 100 мс ожидания ожидания существующегоподключение станет доступным.(Это чрезмерное упрощение обработки соединений, но оно просто показывает, насколько незначительными могут быть любые возможные преимущества keepalive между интерфейсным балансировщиком нагрузки и сервером приложений, если они оба находятся в одном регионе..)

    Вот почему использование http://nginx.org/r/keepalive в контексте upstream редко является хорошей идеей, если вам это действительно не нужно, и вы специально проверили, что он дает желаемые результаты, учитываяпункты, как указано выше.

    (И, просто чтобы прояснить, эти пункты не зависят от того, какое реальное программное обеспечение вы используете, поэтому, даже если вы не испытывали проблем, с которыми вы сталкиваетесь при вашей комбинацииnginx и tomcat, я все равно рекомендую вам не использовать keepalive между балансировщиком нагрузки и сервером приложений, даже если вы решите переключиться с nginx и tomcat на одно или оба.)


Мое предложение?

  • Проблема не может быть воспроизведена при использовании va по умолчаниюзначения http://nginx.org/r/proxy_http_version и http://nginx.org/r/keepalive.

  • Если ваш бэкэнд находится в пределах 5 мс от внешнего интерфейса, вы наверняка даже не получите никаких преимуществ от изменения этих директив в первую очередьТаким образом, если вы не преследуете Heisenbugs, вы можете использовать эти конкретные настройки с наиболее разумными значениями по умолчанию.

0 голосов
/ 16 декабря 2018

Оказалось, что библиотека "sjsxp", которую использует JAX-WS RI v2.1.3, заставляет Tomcat вести себя таким образом.Я попробовал другую версию JAX-WS RI (v2.1.7), которая больше не использует библиотеку "sjsxp", и это решило проблему.

Очень похожая проблема, опубликованная в списке рассылки Metro: http://metro.1045641.n5.nabble.com/JAX-WS-RI-2-1-5-returning-malformed-response-tp1063518.html

0 голосов
/ 28 ноября 2018

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

после того, как Tomcat получает запрос, он просто возвращает только тело ответа.

Не совсем.Он начинается с 5d , который, вероятно, является размером чанка , и это означает, что последний "полный" ответ (с строка состояния и заголовки ) полученное из этого соединения содержало заголовок « Transfer-Encoding: chunked ».По какой-то причине ваш сервер по-прежнему считает, что предыдущий ответ не завершен к тому времени, когда он начинает отправлять этот новый ответ на ваш последний запрос.

Отсутствующий фрагмент выглядит подтвержденным, поскольку на снимке экрана не отображается last-chunk (значение = 0), заканчивающий предыдущий запрос.Обратите внимание, что последний ответ заканчивается последним блоком (последний показанный байт равен 0).

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

Не пропущены ли какие-либо байты, если вы сравниваете размеры чанков с тем, что фактически отправляется клиенту?Все буферы очищены?Остерегайтесь также конца строк (только CRLF и LF).

Еще одна причина, о которой я думаю, если ваш ответ содержит какой-то ввод пользователя, полученный из запроса, вы можете столкнуться с Разделение HTTP .

Возможные решения.

Стоит попробовать отключить кодирование по частям на уровне вашей библиотеки, например, с помощью Axis2 проверьте Транспорт HTTP .

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

Дополнительная литература

RFC 2616 3.6.1 Кодирование передачи по частям

...