Статьи

Интеграция системного журнала с Kinesis: предвидение использования пожарного шланга

Вслед за  объявлением Kinesis Firehose все больше людей будут стремиться интегрировать Kinesis с системами регистрации (чтобы ускорить / упростить загрузку журналов в S3 и Redshift). Вот один из способов решения этой проблемы, который объединяет syslog-ng с Kinesis.

Во-первых, давайте посмотрим на конфигурацию syslog-ng. В конфигурации syslog-ng вы связываете источники с местами назначения:

source s_sys {
    udp(ip(127.0.0.1) port(514));
};

destination d_test { file("/var/log/monetate/test.log"
    perm(0644)
    template("$MSGONLY\n")
    template_escape(no)
); };

destination d_fact_kinesis { tcp("localhost"
   port(4242)
   template("$MSGONLY\n")
   template_escape(no)
); };
log { source(s_sys); destination(d_test); destination(d_kinesis); };

В этом примере у нас есть один источник событий: UDP, и у нас есть два назначения: один файл и один TCP. Мы соединяем их вместе в последнем  log утверждении. При такой конфигурации любые пакеты syslog-ng, полученные через UDP, записываются в порт TCP и в файл. Файл — это наша стратегия резервного копирования, на случай, если что-то случится с Kinesis, мы также сохраним события локально.  TCP — это наш путь к Kinesis .

Что касается TCP, мы можем легко реализовать простой сервер TCP на Java, который получает сообщения от syslog-ng и отправляет их через KPL. В Monetate мы сделали именно это. (и я посмотрю, сможем ли мы открыть решение с открытым исходным кодом). Тем не менее , очень важно понимать  управление потоком syslog-ng и, более конкретно, как мы будем справляться с обратным давлением, если / когда Kinesis начнет выполнять резервное копирование.

Давайте рассмотрим, как мы поддерживаем это.

Вот изображение, которое показывает весь поток:

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

Например, если наш маленький TCP-сервер («мост») слепо принимает пакеты из потока TCP, мы быстро получим виртуальную машину Java, если / когда замедлится Kinesis. Таким образом, в «мосту» нам нужно применить противодавление вверх по течению, чтобы этого не произошло. Точнее говоря, нам нужно прекратить использование потока TCP и надеяться, что syslog-ng отреагирует соответствующим образом.

К счастью, syslog-ng объяснил этот случай своим «выходным буфером», показанным выше. Выходной буфер используется для хранения сообщений для доставки в пункты назначения. Если в этом буфере достигнут максимальный размер, то адресат «отключается», чтобы не вывести системный журнал. Вы управляете максимальным размером буфера через  log_fifo_size настройку в syslog-ng.

В этом сценарии разные типы описания имеют разное поведение, и мы протестировали некоторые из них. Сначала мы рассмотрели прямую трубу между syslog и нашим процессом моста, используя назначение «program» в syslog-ng. Это работало хорошо, но в случае резервной очереди syslog-ng убивает программу и запускает новый процесс. Это было не идеально. Мы также рассмотрели использование UDP. Это также сработало и, по сути, исключило сценарий противодействия давлению, потому что UDP «запускай и забывай». Однако при большой нагрузке мы заметили отбрасывание пакетов, что означало, что мы теряли события.

В итоге мы решили перейти с TCP. С TCP мы не будем молча терять сообщения, а syslog-ng не будет постоянно перезапускать наш процесс. С этим решением нам нужно было подтвердить поведение syslog-ng. И для этого нам нужно было контролировать syslog-ng. Эта удобная командная строка денди делает именно это:

syslog-ng -Fevd >& syslog.log

Во время мониторинга системного журнала мы протестировали два сценария сбоя. Первый протестировал мертвый мост (без прослушивателя TCP). В этой ситуации syslog-ng не сможет подключиться. Нам нужно было убедиться, что syslog-ng хорошо себя ведет в этом случае. Чтобы проверить это, мы пропустили 100K сообщений через систему в течение 40 секунд (> 2K / сек). При мониторинге syslog-ng мы увидели, что он пытается восстановить соединение:

$grep 4242 syslog.log | grep failed
Connection failed; server='AF_INET(127.0.0.1:4242)', error='Connection refused (111)', time_reopen='10'
...
Connection failed; server='AF_INET(127.0.0.1:4242)', error='Connection refused (111)', time_reopen='10'

Все сообщения поступили в наш файл журнала (аллилуйя!), Что означает, что сбитое TCP-соединение не оказало влияния на назначение файла журнала. Более того, syslog-ng постоянно пытался установить TCP-соединение, поэтому, когда процесс возобновил работу, он снова подключился! отлично! Из вышеприведенного вывода следует отметить одну очень важную вещь — time_reopen. Оказывается, это  глобальная опция конфигурации , которая сообщает syslog-ng, как долго ждать повторной попытки установить соединение. Таким образом, поведение было стабильным — и мы можем на самом деле настроить, как шумные вещи получаются, если / когда мы теряем процесс моста.

Для финального теста нам нужно было увидеть, что происходит, когда мы применяем обратное давление от самого процесса Java. В этом случае syslog-ng может подключиться, но процесс Java отказывается считывать поток / сокет. Для этого мы запустили тот же 100K-тест, но в процессе java приостановили потребление для имитации замедления Kinesis. И снова мы увидели хорошие вещи … Все сообщения поступили в файл журнала, и на этот раз мы увидели сообщения из syslog-ng, указывающие, что буфер вывода (очередь fifo) был заполнен:

syslog.log:Destination queue full, dropping message; queue_len='1000', mem_fifo_size='1000'
...
syslog.log:Destination queue full, dropping message; queue_len='1000', mem_fifo_size='1000'

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

Итак, у вас есть это … для подключения системного журнала к Kinesis, я бы рекомендовал использовать назначение вывода TCP с некоторым связующим кодом между ним и библиотекой Kinesis Producer (KPL). (и снова я посмотрю, сможем ли мы открыть часть этого). Просто будьте осторожны и примените обратное давление к syslog-ng. 

Согласно нашим экспериментам, syslog-ng может  поддержать это !