Nginx-log-collector утиліта від Авіто для відправки логів nginx до Clickhouse

У цій статті розглядатиметься проект nginx-log-collector, який читатиме логі nginx, відправляти їх у кластер Clickhouse. Зазвичай для логів використовують ElasticSearch. Для Clickhouse потрібно менше ресурсів (дискове місце, ОЗУ, ЦПУ). 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 Total Requests:

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

Nginx-log-collector утиліта від Авіто для відправки логів nginx до Clickhouse

Singlestat Failed Requests:

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 Failing Percent:

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 Avg Response Time:

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

Nginx-log-collector утиліта від Авіто для відправки логів nginx до Clickhouse

Singlestat Max Response Time:

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

Nginx-log-collector утиліта від Авіто для відправки логів nginx до Clickhouse

Count Status:

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

Nginx-log-collector утиліта від Авіто для відправки логів nginx до Clickhouse

Для виведення даних як пиріг потрібно встановити плагін і перезавантажити графана.

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

Pie TOP 5 Status:

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

Nginx-log-collector утиліта від Авіто для відправки логів nginx до Clickhouse

Далі наводитиму запити без скріншотів:

Count http_user_agent:

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

GoodRate/BadRate:

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

Response Timing:

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

Upstream response time (час відповіді 1-го upstream):

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

Table Count Status for all 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
квантиль()
Nginx-log-collector утиліта від Авіто для відправки логів nginx до Clickhouse

Висновок:

Сподіваюся, спільнота підключиться до розробки/тестування та використання nginx-log-collector.
І хтось колись запровадить nginx-log-collector розповість скільки заощадив диска, ОЗУ, ЦПУ.

Telegram канали:

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

Кому важливі мілісекунди, напишіть чи проголосуйте, будь ласка, у цьому питання.

Джерело: habr.com

Додати коментар або відгук