Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Această articol va aborda proiectul nginx-log-collector, care va citi jurnalele nginx și le va trimite în clusterul Clickhouse. De obicei, pentru jurnale se utilizează ElasticSearch. Clickhouse necesită mai puține resurse (spațiu pe disc, RAM, CPU). Clickhouse scrie datele mai repede. Clickhouse comprimă datele, ceea ce face datele pe disc și mai compacte. Avantajele Clickhouse sunt evidente în cele 2 diapozitive din prezentare Cum VK inserează date în ClickHouse de pe zeci de mii de servere.

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Pentru a vizualiza analiticele pentru jurnale, vom crea un tablou de bord pentru Grafana.

Cine este interesat, bun venit sub articol.

Instalăm nginx, grafana în mod standard.

Instalăm clusterul clickhouse folosind ansible-playbook de la Denis Proskurin.

Crearea bbd și tabelelor în Clickhouse

În acest fișier sunt descrise interogările SQL pentru crearea bbd și tabelelor pentru nginx-log-collector în Clickhouse.

Fiecare interogare este realizată pe rând pe fiecare server din clusterul Clickhouse.

Observație importantă. În această linie, logs_cluster trebuie înlocuit cu denumirea dvs. de cluster din fișierul clickhouse_remote_servers.xml între "remote_servers" și "shard".

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

Instalarea și configurarea nginx-log-collector-rpm

Nginx-log-collector nu are rpm. Aici https://github.com/patsevanton/nginx-log-collector-rpm creăm un rpm pentru el. rpm-ul va fi creat cu ajutorul Fedora Copr

Instalăm pachetul 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

Corectăm configurația /etc/nginx-log-collector/config.yaml:

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

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

Configurarea nginx

Configurația generală nginx:

utilizator nginx;
procese lucrător  auto;

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

events {
    conexiuni_lucrător  1024;
}

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

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

    format_log 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  principal;

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

Un singur host virtual:

vhost1.conf:

upstream backend {
    server ip-adresa-server-ului-cu-stub_http_server:8080;
    server ip-adresa-server-ului-cu-stub_http_server:8080;
    server ip-adresa-server-ului-cu-stub_http_server:8080;
    server ip-adresa-server-ului-cu-stub_http_server:8080;
    server ip-adresa-server-ului-cu-stub_http_server:8080;
}

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

Adăugăm în fișierul /etc/hosts gazdele virtuale:

ip-adresa-server-ului-cu-nginx vhost1

Emulator de server HTTP

Ca emulator de server HTTP vom folosi nodejs-stub-server de la Maxim Ignatenko

Nodejs-stub-server nu are rpm. Aici https://github.com/patsevanton/nodejs-stub-server creăm un rpm pentru el. rpm-ul va fi creat cu ajutorul Fedora Copr

Instalăm pe upstream nginx pachetul 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

Testare de încărcare

Testarea se desfășoară folosind Apache benchmark.

Îl instalăm:

yum install -y httpd-tools

Executăm teste folosind Apache benchmark cu 5 servere diferite:

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

Configurarea Grafana

Pe site-ul oficial Grafana nu veți găsi un tablou de bord.

De aceea, îl vom face manual.

Tabloul meu de bord salvat îl puteți găsi aici.

De asemenea, trebuie să creați o variabilă tabelă cu conținutul nginx.access_log.
Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Total Stat pentru Cereri:

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

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Cereri nereușite Singlestat:

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

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Percentaj eșuat în 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

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Timp mediu de răspuns în Singlestat:

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

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Timp maxim de răspuns în Singlestat:

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

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Numără status:

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

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Pentru a afișa datele ca un grafic de tip tort, trebuie să instalați pluginul și să reporniți grafana.

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

Top 5 Status Tort:

SELECT
    1, 
    /* valoare falsă a timestamp-ului */
    status,
    sum(status) AS Reqs
FROM $table
WHERE $timeFilter
GROUP BY status
ORDER BY Reqs desc
LIMIT 5

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

În continuare, voi aduce interogări fără capturi de ecran:

Numără http_user_agent:

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

Rată bună/Rată proastă:

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

Timp de răspuns:

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

Timp de răspuns upstream (timpul de răspuns al primului upstream):

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

Numără status pentru toate vhost:

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

Aspect general al tabloului de bord

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Comparație între avg() și quantile()

avg()
Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse
quantile()
Utilitarul nginx-log-collector de la Avito pentru trimiterea logurilor nginx în Clickhouse

Concluzie:

Sper că comunitatea se va alătura dezvoltării/testării și utilizării nginx-log-collector.
Și cineva care va implementa nginx-log-collector va vorbi despre cât de mult a economisit din spațiul pe disc, RAM, CPU.

Canale Telegram:

Milisecunde:

Celor interesați de milisecunde, vă rog să scrieți sau să votați în acest sens. issue.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster