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

Распространенные стратегии противодавления для служб при постоянной высокой нагрузке

Мне интересно, какие общие стратегии противодавления люди используют для своих веб-сервисов?

Представьте, что ваш сервис работает под большой нагрузкой, и в какой-то момент нагрузка достигает 120% вашей мощности. Как вы с этим справляетесь?

Самая разумная стратегия, которую я могу придумать, - это начать отказываться от связей. Поэтому, если один хост достигает своей максимальной мощности (например, все рабочие Apache заняты), я бы начал отклонять TCP-соединение, пока один из рабочих не освободится. Таким образом, все принятые соединения обрабатываются немедленно без очереди (так что задержка минимальна), а избыточные 20% отклоняются, позволяя балансировщику нагрузки перенаправлять их на другой хост или выполнять любую другую стратегию сброса нагрузки (например, перенаправление на статический / кешированный контент).

Я думаю, что этот безотказный подход намного превосходит любые очереди. Небольшие очереди хороши для поглощения коротких всплесков трафика, но с чрезмерной очередью ваша система может резко выйти из строя при большой нагрузке. Например, при обработке очереди FIFO без какого-либо AQM она может перейти в состояние, когда все обработанные запросы уже истекли на стороне клиента, поэтому система не продвигается вперед.

Я был удивлен, что эту стратегию не так просто реализовать, как кажется. Мой подход заключался в том, чтобы установить небольшое отставание на прослушивание на веб-сервере, ожидая, что все неподходящие соединения будут отклонены. Но из-за изменений в ядре Linux 2.2 эта стратегия разваливается (см. http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html).

Более новое ядро ​​Linux безоговорочно принимает соединения за вас. Ответ SYN-ACK отправляется клиенту без учета размера невыполненного журнала прослушивания. Включение tcp_abort_on_overflow вариант тоже не сильно помогает. Эта опция заставляет ядро ​​отправлять RST, когда соединение не помещается в очередь приема, но на этом этапе клиент уже считает соединение УСТАНОВЛЕННЫМ и, возможно, начал отправку данных.

Это особенно проблематично с HAProxy. Если соединение было успешно установлено, он не будет повторно отправлять запрос на другой сервер, так как этот запрос мог иметь некоторые побочные эффекты на сервере.

Итак, я предполагаю, что мои вопросы:

Заранее спасибо!

Чтобы ответить на ваш первый вопрос: да. Ну, в любом случае, по моему личному мнению, не принимайте это на свой счет. Дело в том, что вы пытаетесь установить ограничения для своего TCP-стека, в то время как перед вами стоит балансировщик нагрузки с множеством счетчиков и опций. Если вы ограничиваете себя в стеке TCP, вы столкнетесь с большим количеством проблем, когда достигнете этих ограничений. Я бы проверил и сохранил ограничения в самом балансировщике нагрузки. Настройте счетчики сеансов или создайте сценарий работоспособности, который будет проверять работоспособность сервера. По достижении пределов вы можете либо отклонить новые входящие запросы, либо перенаправить их на другой сервер, если вы установите бэкэнд как полный. Вы ограничены пределами вашего Apache, а не вашей ОС или haproxy, поэтому старайтесь держаться подальше от системных ограничений, контролируя нагрузку на ваш apache, прежде чем она ее достигнет.

Думаю, это уже ответ на ваш второй вопрос.

Ответ на третий вопрос более сложен, и я не думаю, что вам захочется углубляться в это. Достижение состояния переполнения TCP, на мой взгляд, уже слишком большой шаг в настройке сервера для поддержания высокой нагрузки и трафика.

Это мои два цента, надеюсь, это поможет.