Назад | Перейти на главную страницу

Проблемы Apache при тестировании производительности с mod_reqtimeout

У нас есть 2 веб-сервера Apache за балансировщиком нагрузки, которые подключены к 2 (JBoss) серверам приложений через мод ajp.

К этим веб-серверам мобильные устройства подключаются через REST API.

В нашем тесте производительности мы довольно быстро столкнулись с множеством ошибок NonHttpResponse:, которые, как мы определили, происходят из mod_reqtimeout:

[Mon Mar 16 14:42:49.324705 2015] [reqtimeout:info] [pid 27914:tid 140628428449536] [client 1.2.3.4:48280] AH01382: Request header read timeout

... который настроен следующим образом:

<IfModule reqtimeout_module>
    RequestReadTimeout header=10-20,minrate=500
    RequestReadTimeout body=10,minrate=500
</IfModule>

Я смог избавиться от этих ошибок, увеличив эти значения до

RequestReadTimeout header=20-60,minrate=100

Но это не может быть решением, так как с несколькими одновременными пользователями проблема снова возникла (требуется возможность обслуживать 300 одновременных пользователей - 100 работали нормально, с 300 у нас было более 10000 из этих таймаутов чтения заголовка запроса ошибки). Я подозреваю, что взаимодействие apache KeepAlive, нашей конфигурации mod_ajp и mod_reqtimeout приводит mod_reqtimeout к выводу о продолжающейся атаке slowloris (ко многим открытым соединениям, которые ничего не делают), и я любезно прошу вашей помощи в настройке этих параметров.

Дополнительная проблема - это брандмауэр между веб-сервером и сервером приложений, который, как я подозреваю, убивает открытые неактивные соединения. Я читал о полной деактивации KeepAlive, чтобы решить эту проблему, но, как я уже сказал, все наши клиенты - мобильные устройства, так что это, вероятно, не вариант (?).

Вот другие конфиги (части):

worker.properties:

worker.list=server
worker.maintain=60

worker.server.type=ajp13
worker.server.host=server
worker.server.port=15869
worker.server.socket_keepalive=True
worker.server.connection_pool_timeout=600
worker.server.ping_mode=A
worker.server.connection_ping_interval=60

mod_prefork:

<IfModule prefork.c>
    StartServers         5
    MinSpareServers      5
    MaxSpareServers     10
    #MaxClients         256
    MaxClients         300
    MaxRequestsPerChild  0
</IfModule>

mainserver.conf:

Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15

ssl.conf (мобильные устройства подключаются через ssl):

Timeout 1200
KeepAlive On
MaxKeepAliveRequests 0
KeepAliveTimeout 10

Необычно то, что вы используете «prefork» MPM в том, что кажется по сути обратным прокси, гибридный «рабочий» MPM имеет лучшую масштабируемость, но это не проблема.

Снижение DoS-атак обычно лучше всего выполняется (если не вашим интернет-провайдером) на внешний интерфейс устройство, которое завершает клиентские запросы, из вашего описания это балансировщик нагрузки, а не Apache. Любой компетентный балансировщик нагрузки будет знать HTTP (то есть «Уровень 7»), это, скорее всего, приведет к буферизации HTTP-запросов. Это также применимо, если балансировщик нагрузки завершает HTTPS, но в меньшей степени, если балансировщик нагрузки просто ретранслирует HTTPS-соединения (поскольку он не может видеть HTTP-запросы для их буферизации). Это также не применимо, если ваш балансировщик нагрузки представляет собой простой балансировщик нагрузки типа NAT "Layer 3/4".

Что касается возможной причины тайм-аутов:

  • ваш экземпляр SSL KeepAliveTimeout такой же, как RequestReadTimeout таймаут чтения заголовка, возможно, есть гонка, когда тайм-аут поддержки активности достигается в середине входящего клиентского запроса / заголовков. Если я попытаюсь воспроизвести это, в дополнение к ошибкам AH01382 я также получу AH01991 (ошибка чтения входного фильтра SSL) и AH00567 (сбой запроса: ошибка чтения заголовков). Однако это не может объяснить всех проблем.
  • некорректно сформированные клиентские запросы, которые нередки в прошлом (например, лишний CR / LF после POST, неполные запросы при повторной попытке после ошибки). Я не знаю ничего актуального, это зависит от вашей клиентской базы и, что более важно, от их связи.
  • может быть ошибка, похожая на этот недавний что вызвало ложные таймауты с "событийным" MPM.

Чтобы воспроизвести тайм-ауты:

 $ openssl s_client -connect myhost:443
 GET / HTTP/1.1
 Host: myhost.whatever.com 

 [server reply goes here]
 GET / HTTP/1.1
 Host:

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

Может помочь уменьшение KeepAliveTimeout (по умолчанию 5 секунд). Обратите внимание, что KeepAliveTimeout - это время для получения полного запроса. Я думаю, что следующим шагом может быть mod_log_forensic.

Что касается соединений с серверной частью через AJP, вы используете "ping" на Apache Balancer конфигурация? Если я правильно понимаю вашу систему, предоставленная вами конфигурация Tomcat не будет применяться к соединениям от Apache httpd к Tomcat. Видеть варианты здесь.

                          /-> apache httpd + ajp -\            /-> tomcat/jboss
client -> load-balancer  <                         > firewall <
                          \-> apache httpd + ajp -/            \-> tomcat/jboss