Сбор метрик из Nginx’a в Clickhouse

admin

Запись данных в Clickhouse (и другие векторные базы) может достигать производительности в миллионы строк в секунду. Для этого важно писать данные крупными пакетами (сотни тысяч…миллионы строк в пакете).

Однако аналитические данные часто генерируются прямо на лету. Например, сбор данных о поведении пользователя на сайте. В [https://iotechnologies.com IO] – это один из ключевых источников данных, метрики приходят от миллиардов устройств. И тут крайне важно иметь минимальный путь от Web сервера до базы данных.

Идеальная схема будет включать только Web сервер и базу данных:

Событие -> Nginx -> Логи -> Clickhouse

## Событие будет логироваться Nginx’ом

Упростим нашу задачу до сбора и записи простых наборов метрик во времени:

  • У метрики есть название и значение.
  • Метрика приходит в определенный момент времени.
  • По метрикам можно делать различные выборки – фильтровать по времени и имени.

Подготовка таблицы

В нашем случае таблица будет такой структуры:

CREATE TABLE metrics

( time DateTime, name String, value Int64)

ENGINE = MergeTree

PARTITION BY name

ORDER BY time

SETTINGS index_granularity = 8192

## Создание таблицы в Clickhouse

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

Настройка логирования

Самая сложная задача – научить Nginx писать данные в нужном нам формате. Хотя с Nginx’ом она оказывается довольно простой. Собирать метрики будем обычным запросом в формате:

http://tracking.server/?n=metric_name&v=metric_value

## Два аргумента – для названия (n) и значения (v) метрики

Для того, чтобы вставлять данные в Clickhouse мы постараемся получить лог-файл в CSV-формате:

date_time,metric_name,metric_value

## Такой CSV формат можно сразу зафидить в Clickhouse

Например, при отправке пары запросов по адресу http://tracking.server/?n=pageviews&v=1, мы увидим:

2019-04-07 14:26:47,pageviews,1
2019-04-07 14:26:49,pageviews,1

Получить такой формат лога в Nginx’e оказалось довольно просто, но пришлось использовать [https://www.nginx.com/resources/wiki/modules/lua/ Lua] для получения времени в нужном формате:

map $host **$time** { # Определяем переменную $time

default ”;

}

log_format track ‘**$time,$arg_n,$arg_v**’; # Определяем нужный формат лога

server {

location / {

access_log /var/log/nginx/track.log track;

default_type text/plain;

content_by_lua ”

ngx.say(‘thanks’)

**ngx.var.time = os.date(‘!%Y-%m-%d %H:%M:%S’)** # Наполняем $time временем

“;

}

}

## Такая конфигурация позволит записать данные в /var/log/nginx/track.log в нужном формате

Запись в Clickhouse

Чтобы записать данные из лога в Clickhouse, необходимо сначала сменить активный лог-файл (сделать rotate):

mv /var/log/nginx/track.log /tmp/db.log

kill -USR1 `cat /var/run/nginx.pid`

## Ротейтим лог перед записью в БД

Тепер можно записывать данные в Clickhouse:
cat /tmp/db.log | clickhouse-client --query "INSERT INTO metrics FORMAT CSV" && rm /tmp/db.log
## Обычный метод записи, ведь формат и данные уже готовы

Ну и объединить это в цикл с желаемым окном:

while :

do

mv /var/log/nginx/track.log /tmp/db.log

kill -USR1 `cat /var/run/nginx.pid`

cat /tmp/db.log | clickhouse-client –query “INSERT INTO metrics FORMAT CSV” && rm /tmp/db.log

**sleep 10**

done

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

Буферизация

Дополнительной оптимизацией может стать использование [https://clickhouse.yandex/docs/en/operations/table_engines/buffer/ буфера]. Если нагрузка на запись будет неравномерная (скажем, то 10 записей, то 10 тысяч записей), это имеет смысл. Работает все, как всегда, просто – достаточно создать специальную таблицу:

CREATE TABLE metrics_buffer

AS metrics

ENGINE = **Buffer**(default, metrics, 16, 10, 100, 1000, 10000, 10000, 100000)

## Создаем буфер для таблицы с метриками

Так Clickhouse создаст специальную таблицу, данные которой будут находиться только в памяти. Она будет повторять структуру нашей главной таблицы, и будет периодически сбрасывать в нее данные на основе указанных ограничений. Это повышает производительность вставки данных в основную таблицу, т.к. небольшие пакеты буферизируются и объединяются в более крупные.

Внимание, буферы чистятся при перезагрузке базы или сервера. Убедитесь, что у нее есть fail-over, если используете ее на продакшне.

Чтение данных также нужно делать из буфера вместо основной таблицы. Clickhouse сам замерджит данные из двух таблиц и выдаст правильный результат:

SELECT time, name, value FROM **metrics_buffer**
## Читать данные необходимо также из буфера

Производительность решения

Мы тестировали решение на самом мелком [https://www.digitalocean.com/pricing/ дроплете на DigitalOcean]:

Если не учитывать задержки Интернета, то такое решение способно обслужить около 6…7 тыс. запросов в секунду (что и понятно, это же простой Nginx без оверхеда):

ab -n 100000 -c 16 "http://127.0.0.1/track?n=test&v=1"
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

...

Concurrency Level:      16
Time taken for tests:   15.553 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      19000000 bytes
HTML transferred:       700000 bytes
**Requests per second:    6429.44 [#/sec] (mean)**
Time per request:       2.489 [ms] (mean)
Time per request:       0.156 [ms] (mean, across all concurrent requests)
Transfer rate:          1192.96 [Kbytes/sec] received

## Тестирование пропускной способности

Собранный пример на этом же дроплете, который считает просмотры и количество пикселей, которые проехали мышки наших читателей можно [https://rt.onthe.io/?metric=5caa00c8e8260-distance&period=1%20hour найти тут]. Там же можно потестировать трекинг:

curl “rt.onthe.io/track?n=5caa00c8e8261-**[имя_метрики]**&v=1”

## Для трекинга

После отправки данных достаточно будет зайти по адресу:
https://rt.onthe.io/?metric=5caa00c8e8261-[имя_метрики]
## Для просмотра

Самое главное

Использование связки Nginx log + Clickhouse позволяет получить высокопроизводительное решение для сбора, хранения и аналитики временных рядов.

Останні статті

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

Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…

21.11.2024

Что такое PWA приложение? Зачем необходимо прогрессивное веб-приложение

Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…

19.11.2024

Как создать игру на телефоне: программирование с помощью конструктора

Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…

17.11.2024

Google Bard: эффективный аналог ChatGPT

В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…

14.11.2024

Скрипт и программирование: что это такое простыми словами

Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…

12.11.2024

Дедлайн в разработке: что это такое простыми словами

Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…

11.11.2024