Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

W tym artykule omówimy projekt kolektor-logów nginx, który odczyta logi nginx, wyślij je do klastra Clickhouse. Zwykle ElasticSearch jest używany do dzienników. Clickhouse wymaga mniej zasobów (miejsca na dysku, pamięci RAM, procesora). Clickhouse zapisuje dane szybciej. Clickhouse kompresuje dane, dzięki czemu dane na dysku są jeszcze bardziej kompaktowe. Korzyści z Clickhouse można zobaczyć na 2 slajdach z raportu Jak VK wstawia dane do ClickHouse z dziesiątek tysięcy serwerów.

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Aby przeglądać analizy według dzienników, utwórzmy pulpit nawigacyjny dla Grafany.

Kogo to obchodzi, witamy pod kotem.

Zainstaluj nginx, grafana w standardowy sposób.

Zainstaluj klaster Clickhouse z ansible-playbook z Denis Proskurin.

Tworzenie bazy danych i tabel w Clickhouse

W tym plik Opisano zapytania SQL do tworzenia baz danych i tabel dla nginx-log-collector w Clickhouse.

Każde żądanie wykonujemy po kolei na każdym serwerze klastra Clickhouse.

Ważna uwaga. W tym wierszu logs_cluster należy zastąpić nazwą klastra z pliku clickhouse_remote_servers.xml między „remote_servers” a „shard”.

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

Instalowanie i konfigurowanie nginx-log-collector-rpm

Nginx-log-collector nie ma rpm. Tutaj https://github.com/patsevanton/nginx-log-collector-rpm utwórz dla niego rpm. rpm zostanie zbudowany przy użyciu Fedora Copr

Zainstaluj pakiet 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

Edytuj konfigurację /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/

Konfiguracja nginxa

Ogólna konfiguracja 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;
}

Wirtualny host jeden:

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;
    }
}

Dodaj wirtualne hosty do pliku /etc/hosts:

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

Emulator serwera HTTP

Jako emulatora serwera HTTP użyjemy nodejs-stub-server od Maksym Ignatenko

nodejs-stub-server nie ma rpm. Tutaj https://github.com/patsevanton/nodejs-stub-server utwórz dla niego rpm. rpm zostanie zbudowany przy użyciu Fedora Copr

Zainstaluj pakiet nodejs-stub-server na upstream nginx rpm

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

Test naprężeń

Testy przeprowadzane są przy użyciu benchmarku Apache.

Zainstaluj to:

yum install -y httpd-tools

Rozpoczynamy testowanie za pomocą testu porównawczego Apache z 5 różnych serwerów:

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

Konfigurowanie Grafany

Na oficjalnej stronie Grafany nie znajdziesz pulpitu nawigacyjnego.

Dlatego zrobimy to ręcznie.

Możesz znaleźć mój zapisany pulpit nawigacyjny tutaj.

Musisz także utworzyć zmienną tabeli z zawartością nginx.access_log.
Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Łączna liczba żądań Singlestat:

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

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Nieudane żądania Singlestat:

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

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Procent nieudanych testów 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

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Średni czas odpowiedzi singlestat:

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

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Maksymalny czas odpowiedzi singlestat:

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

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

stan licznika:

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

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Aby wyprowadzać dane jak ciasto, musisz zainstalować wtyczkę i ponownie załadować grafana.

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

Ciasto TOP 5 Stan:

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

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Dalej podam prośby bez zrzutów ekranu:

Policz http_user_agent:

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

Dobra ocena/Zła ocena:

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

czas odpowiedzi:

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

Czas odpowiedzi upstream (czas odpowiedzi 1. upstream):

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

Stan liczby stołów dla wszystkich vhostów:

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

Widok ogólny deski rozdzielczej

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Porównanie avg() i kwantylu()

średnia()
Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse
kwantyl()
Narzędzie Nginx-log-collector firmy Avito do wysyłania logów nginx do Clickhouse

Wnioski:

Miejmy nadzieję, że społeczność zaangażuje się w tworzenie/testowanie i używanie nginx-log-collector.
A kiedy ktoś wdroży nginx-log-collector, powie ci, ile zaoszczędził dysku, pamięci RAM, procesora.

Kanały telegramów:

milisekundy:

Kogo obchodzi milisekunda, napisz lub zagłosuj, proszę, w tym problem.

Źródło: www.habr.com

Dodaj komentarz