Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

В тази статия ще бъде разгледан проектът nginx-log-collector, който ще чете логовете от nginx и ще ги изпраща в кластера Clickhouse. Обикновено за логовете се използва ElasticSearch. За Clickhouse се изискват по-малко ресурси (дисково пространство, RAM, CPU). Clickhouse записва данни по-бързо. Clickhouse компресира данните, което прави данните на диска още по-компактни. Предимствата на Clickhouse са видими при 2 слайда от доклада Как VK вмъква данни в ClickHouse от десетки хиляди сървъри.

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

За преглед на аналитиката по логовете ще създадем дашборд за Grafana.

Който се интересува, заповядайте под кат.

Инсталираме nginx и grafana по стандартния начин.

Инсталираме кластер Clickhouse с помощта на ansible-playbook от Денис Проскурин.

Създаване на база данни и таблици в Clickhouse

В този файл са описани SQL запитвания за създаване на база данни и таблици за nginx-log-collector в Clickhouse.

Всеки запитване изпълняваме последователно на всеки сървер от кластера Clickhouse.

Важно забележка. В този ред logs_cluster трябва да бъде сменен с името на вашия кластер от файла clickhouse_remote_servers.xml между "remote_servers" и "shard".

ENGINE = Distributed('logs_cluster', 'nginx', 'access_log_shard', rand())

Инсталация и настройка на nginx-log-collector-rpm

Nginx-log-collector няма rpm. Тук https://github.com/patsevanton/nginx-log-collector-rpm създаваме rpm за него. RPM ще бъде компилиран с помощта на Fedora Copr

Инсталираме rpm пакета nginx-log-collector-rpm

yum -y install yum-plugin-copr
yum copr enable antonpatsev/nginx-log-collector-rpm
yum -y install nginx-log-collector
systemctl start nginx-log-collector

Коригираме конфигурацията /etc/nginx-log-collector/config.yaml:

  .......
  upload:
    table: nginx.access_log
    dsn: http://ip-адрес-кластера-clickhouse:8123/

- tag: "nginx_error:"
  format: error  # access | error
  buffer_size: 1048576
  upload:
    table: nginx.error_log
    dsn: http://ip-адрес-кластера-clickhouse:8123/

Настройка на nginx

Обща конфигурация на nginx:

user  nginx;
worker_processes  auto;

#error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    log_format avito_json escape=json
                     '{'
                     '"event_datetime": "$time_iso8601", '
                     '"server_name": "$server_name", '
                     '"remote_addr": "$remote_addr", '
                     '"remote_user": "$remote_user", '
                     '"http_x_real_ip": "$http_x_real_ip", '
                     '"status": "$status", '
                     '"scheme": "$scheme", '
                     '"request_method": "$request_method", '
                     '"request_uri": "$request_uri", '
                     '"server_protocol": "$server_protocol", '
                     '"body_bytes_sent": $body_bytes_sent, '
                     '"http_referer": "$http_referer", '
                     '"http_user_agent": "$http_user_agent", '
                     '"request_bytes": "$request_length", '
                     '"request_time": "$request_time", '
                     '"upstream_addr": "$upstream_addr", '
                     '"upstream_response_time": "$upstream_response_time", '
                     '"hostname": "$hostname", '
                     '"host": "$host"'
                     '}';

    access_log     syslog_server=unix:/var/run/nginx_log.sock,nohostname,tag=nginx avito_json; #ClickHouse
    error_log      syslog_server=unix:/var/run/nginx_log.sock,nohostname,tag=nginx_error; #ClickHouse

    #access_log  /var/log/nginx/access.log  main;

    proxy_ignore_client_abort on;
    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
}

Виртуален хост един:

vhost1.conf:

upstream backend {
    server ip-адрес-сервера-с-stub_http_server:8080;
    server ip-адрес-сервера-с-stub_http_server:8080;
    server ip-адрес-сервера-с-stub_http_server:8080;
    server ip-адрес-сервера-с-stub_http_server:8080;
    server ip-адрес-сервера-с-stub_http_server:8080;
}

server {
    listen   80;
    server_name vhost1;
    location / {
        proxy_pass http://backend;
    }
}

Добавяме в файла /etc/hosts виртуалните хостове:

ip-адрес-сервера-с-nginx vhost1

Емулятор на HTTP сървър

Ще използваме като емулатор на HTTP сървър nodejs-stub-server от Maxim Ignatenko

Nodejs-stub-server няма rpm. Тук https://github.com/patsevanton/nodejs-stub-server създаваме rpm за него. RPM ще бъде компилиран с помощта на Fedora Copr

Инсталираме на upstream nginx rpm пакета nodejs-stub-server

yum -y install yum-plugin-copr
yum copr enable antonpatsev/nodejs-stub-server
yum -y install stub_http_server
systemctl start stub_http_server

Натоварващо тестване

Тестовете се провеждат с помощта на Apache benchmark.

Инсталираме го:

yum install -y httpd-tools

Стартираме тестването с помощта на Apache benchmark с 5 различни сървъра:

while true; do ab -H "User-Agent: 1server" -c 10 -n 10 -t 10 http://vhost1/; sleep 1; done
while true; do ab -H "User-Agent: 2server" -c 10 -n 10 -t 10 http://vhost1/; sleep 1; done
while true; do ab -H "User-Agent: 3server" -c 10 -n 10 -t 10 http://vhost1/; sleep 1; done
while true; do ab -H "User-Agent: 4server" -c 10 -n 10 -t 10 http://vhost1/; sleep 1; done
while true; do ab -H "User-Agent: 5server" -c 10 -n 10 -t 10 http://vhost1/; sleep 1; done

Настройка на Grafana

На официалния сайт на Grafana няма да намерите дашборд.

Затова ще го направим ръчно.

Моята запазена таблета може да бъде намерена тук.

Също така трябва да създадете променливата table със съдържанието nginx.access_log.
Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Singlestat Общо заявки:

SELECT
 1 as t,
 count(*) as c
 FROM $table
 WHERE $timeFilter GROUP BY t

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Singlestat Неправилни заявки:

SELECT
 1 as t,
 count(*) as c
 FROM $table
 WHERE $timeFilter AND status NOT IN (200, 201, 401) GROUP BY t

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Singlestat Процент на грешки:

SELECT
 1 as t, (sum(status = 500 or status = 499)/sum(status = 200 or status = 201 or status = 401))*100 FROM $table
 WHERE $timeFilter GROUP BY t

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Singlestat Средно време за отговор:

SELECT
 1, avg(request_time) FROM $table
 WHERE $timeFilter GROUP BY 1

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Singlestat Максимално време за отговор:

SELECT
 1 as t, max(request_time) as c
 FROM $table
 WHERE $timeFilter GROUP BY t

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Брой статус:

$columns(status, count(*) as c) from $table

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

За да извеждате данни като пай, трябва да инсталирате плъгин и да рестартирате grafana.

grafana-cli plugins install grafana-piechart-panel
service grafana-server restart

Пай ТОП 5 статус:

SELECT
    1, 
    status,
    sum(status) AS Reqs
FROM $table
WHERE $timeFilter
GROUP BY status
ORDER BY Reqs desc
LIMIT 5

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Следващата част ще съдържа запитвания без скрийншотове:

Брой http_user_agent:

$columns(http_user_agent, count(*) c) FROM $table

Добра/Лоша ставка:

$rate(countIf(status = 200) AS good, countIf(status != 200) AS bad) FROM $table

Време за отговор:

$rate(avg(request_time) as request_time) FROM $table

Време за отговор от upstream (време за отговор на 1-ви upstream):

$rate(avg(arrayElement(upstream_response_time,1)) as upstream_response_time) FROM $table

Таблица Брой статус за всички vhost:

$columns(status, count(*) as c) from $table

Общ изглед на таблета

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Сравнение avg() и quantile()

avg()
Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse
quantile()
Утилита nginx-log-collector от Авито за изпращане на логове от nginx в Clickhouse

Извод:

Надявам се общността да се включи в разработката/тестването и използването на nginx-log-collector.
И някой, когато внедри nginx-log-collector, ще разкаже колко е спестил от диск, RAM, CPU.

Telegram канали:

Милисекунди:

На тези, на които им трябва време в милисекунди, моля, пишете или гласувайте в това issue.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster