http-server with two pools of threads (one for easy to handle requests, and one for hard to handle), forked from Begun's lizard
C++ CMake
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
blzmod_example
debian
src/blizzard
CMakeLists.txt
CMakeMacro.cmake
README
blizzard.spec

README

ОПИСАНИЕ

blizzard - многопоточный HTTP-сервер

Используется приложениями, нуждающимися в HTTP-общении с окружающим миром -
такое приложение реализуются как .so-плагин к blizzard-у. От плагина
требуется реализация интерфейса blizzard-плагина - конструктор/деструктор,
load(), easy() хендлер, hard() хендлер. Опционально - idle() и другие, не
полностью виртуальные функции класса blz_plugin.

blizzard поддерживает следующие ключи командной строки:

  -c, --config-file=   - конфиг-файл
  -p, --pid-file=      - pid-файл
  -d, --daemon         - демонизироваться при запуске
  -D, --no-daemon      - не демонизироваться при запуске

Общая работа сервера проста:

Cервер стартует, парсит свой конфиг, создаёт объект плагина, вызывает его
метод load(), передавая ему необходимые параметры, инициализирует сетевые
соединения

* сетевой поток - следит за сокетом, привешенным к "входящему" порту; когда
  получает соединение, добавляет сокет в список готовых сокетов; обрабатывает
  сетевые события; парсит HTTP-запросы; готовые запросы кладёт в easy-очередь;
  проверяет done-очередь на предмет ответов; отдаёт сформированные ответы.
  Если установлен лимит на количество элементов в easy/hard-очереди, на все
  излишки сервер отвечает 503 ошибкой.

* easy-потоки (число задаётся конфигом). Спят, ожидая данные в easy-очереди.
  Если в очереди появляются запросы, easy-потоки оживают, конкурентно вызывая
  easy-хендлер плагина на каждый элемент очереди. После этого варианта три:

  1 хендлер обработал конект - blizzard кладёт запрос в done-очередь.
  2 хендлер не осилил запрос - blizzard кладёт запрос в hard-очередь.
  3 хендлер обнаружил ошибку - blizzard пишет в соединение код 503, кладя запрос в done-очередь.

* hard-потоки (число задаётся конфигом). Спят, ожидая данные в hard-очереди.
  Если в очереди появляются запросы, hard-потоки оживают, радостно разгребая 
  очередь и вызывая hard-хендлер на каждый элемент. Тут у хэндлера уже два
  варианта:

  1 хендлер обработал конект - blizzard кладёт запрос в done-очередь.
  2 хендлер обнаружил ошибку - blizzard пишет в соединение код 503, кладя запрос в done-очередь.

* idle-поток. Если в конфиге есть ключ <idle_timeout>, этот поток вызывает
  idle-функцию у плагина с заданной ключом периодичностью. Иначе он вызывает
  idle ровно один раз.

КОНФИГУРАЦИОННЫЙ ФАЙЛ

Параметры:

  <pid_file_name>        - имя pid-файла
  <log_file_name>        - имя log-файла
  <log_level>            - уровень логгирования, варианты: alert crit error warn notice info debug - в порядке убывания важности

  <stats>
    <uri>                - по этому URI можно получить статистику
  </stats>

  <plugin>
    <ip>                 - айпи входного сокета
    <port>               - порт входного сокета
    <connection_timeout> - таймаут на каждый коннекшн
    <idle_timeout>       - период между вызовами idle у плагина в мс
    <library>            - путь к .so-плагину
    <params>             - строка, передаваемая в set_param для инициализации плагина
    <easy_threads>       - число easy-потоков
    <hard_threads>       - число hard-потоков
    <easy_queue_limit>   - если указан, ограничивает число запросов в easy-очереди
    <hard_queue_limit>   - если указан, ограничивает число запросов в hard-очереди.
  </plugin>

СТАТИСТИКА

Статистика отдаётся при запросе к uri, указанному в директиве uri секции stats
в следующем формате:

  <blizzard_stats>                                           
      <blizzard_version>0.3.2</blizzard_version>
      <uptime>287</uptime>                     # в секундах
      <rps>1105.250</rps>                      # запросов в секунду
      <queues>                                 # размеры очередей
          <easy>2</easy>                       # мгновенный размер
          <max_easy>1</max_easy>               # максимальный размер за предыдущие 4 секунды
          <hard>0</hard>
          <max_hard>0</max_hard>
          <done>0</done>
          <max_done>1</max_done>
      </queues>
      <response_time>                          # времена обработки запросов (в секундах)
          <min>0.127500</min>                  # минимальное за предыдущие 4 секунды
          <avg>1.342132</avg>                  # среднее за предыдущие 4 секунды
          <max>8.674405</max>                  # максимальное за предыдущие 4 секунды
      </response_time>
      <mem_allocator>                          # данные аллокатора памяти
          <pages>1</pages>                     # кол-во выделенных страниц в http-пуле
          <objects>8</objects>                 # кол-во выделенных объектов в http-пуле
      </mem_allocator>
      <rusage>                                 # данные rusage для blizzard-а
          <utime>2</utime>                     # время в userspace
          <stime>4</stime>                     # время в system
      </rusage>
  </blizzard_stats>

ИЗВЕСТНЫЕ ПРОБЛЕМЫ

* если максимальное число файловых дескрипторов не очень велико (ulimit -n
  выдаёт например 1024), при большой интенсивности запросов этот запас может
  исчерпаться, вызывая таймауты по соответствующим коннектам. Потому при
  таймаутах как минимум нужно выставить ulimit -n достаточно большим, например,
  16384

* сервер отличается агрессивным поведением в отношении коннектов, с которыми у
  него есть проблемы - он просто закрывает соединение, если ошибка в
  http-запросе, если суммарный размер HTTP-хэдеров больше 8кб, если наступил
  таймаут итд.