Pull to refresh

sasl:overload. Или — «не кладите в тарелку больше, чем она может вместить»

Reading time 2 min
Views 1.5K
Эрланг отличная платформа для построения серверов, и в его стандартной библиотеке предусмотрены многие средства заметно облегчающие жизнь разработчика.

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

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

Как это делается?


Одним из средств контроля загрузки в эрланг программах является модуль overload в приложении sasl. Его идея очень проста — при новом запросе от клиента мы проверяем текущую загрузку, если она больше чем N в секунду, отправляем клиенту вежливый отказ. Если загрузка меньше этого порога, то передаем этот запрос на основную обработку.

Идея проста — но реализация достаточно неприятная, надо помнить время, когда пришли несколько последних запросов, иметь в виду, что могут быть локальные «пики» интенсивности запросов и т.д.

На наше счастье все это делает модуль overload. В настройках программы можно указать требуемый порог (грубо говоря в sys.config), и затем, когда приходит запрос от клиента, просто выполняем overload:request() и смотрим результат — accept — продолжаем работу, reject — отказываем в обслуживании.

То есть что то типа
handle_call(SomeRequest,State) ->
  case overload:request() of
     reject -> {reply, overloaded, State}
     accept -> {Result,NewState}= do_something(SomeRequest,State),
                    {reply,Result,NewState}
   end.


За кулисами — sasl считает когда и сколько раз вызывался overload:request(), и на основании этого по сложной формуле (можно посмотреть в документации) считает загрузку, и по результатам принимает решение — достоен ли текущий запрос того, чтобы его обработали

Как это выглядит на практике:

Настраиваем sasl, прмерно такой sys.config:

[
{sasl,[{overload_max_intensity, 300.0},{sasl_error_logger,{file,"/var/log/rcvr.log"}},{utc_log,false}]}
].


Здесь мы устанавливаем максимальную интенсивность 300 запросов в секунду. Запускаем, для примера

erl +K true -sname rcvr -setcookie 123 -config sys.config

И следим за загрузкой. Через неделю munin нам показывает такое:



Здесь видно, что сервер принимает и обрабатывает только 300 запросов в секунду, что нам и требовалось.

Недостатки overload

  • Поскольку sasl считает интенсивность вызовов overload:request() для определения текущей загрузки — overload:request() можно использовать только в одном месте в программе. У вас не плоучится для сервера, который принимает (к примеру) http и rpc запросы настроить overload отдельно для rpc и отдельно для http.
  • Настройки задаются в sys.config (ну или в .app файле) и не могут быть изменены, пока работает программа. то есть чтобы перенастроить sasl:overload придется перезагружать сервер.


Мораль


Модуль overload удобен, но не везде применим из за своих ограничений. но в любом случае — знать и помнить о нем — нужно.
Tags:
Hubs:
+35
Comments 20
Comments Comments 20

Articles