Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

In diesem Artikel wird das Projekt nginx-log-collectorbehandelt, das die nginx-Logs liest und sie an einen Clickhouse-Cluster sendet. Üblicherweise werden für Logs ElasticSearch verwendet. Clickhouse benötigt weniger Ressourcen (Speicherplatz, RAM, CPU). Clickhouse schreibt Daten schneller. Clickhouse komprimiert Daten, was den Speicherplatz auf der Festplatte noch effizienter macht. Die Vorteile von Clickhouse sind in 2 Folien der Präsentation sichtbar. Wie VK Daten aus Zehntausenden von Servern in ClickHouse einfügt.

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Um Analysen zu den Logs anzuzeigen, erstellen wir ein Dashboard für Grafana.

Wer interessiert ist, ist unter dem Schnitt willkommen.

Wir installieren nginx und grafana auf die übliche Weise.

Wir installieren den Clickhouse-Cluster mit dem Ansible-Playbook von Denis Proskurin.

Erstellung der DB und Tabellen in Clickhouse

In dieser Datei sind die SQL-Abfragen zur Erstellung der DB und Tabellen für den nginx-log-collector in Clickhouse beschrieben.

Jede Abfrage führen wir nacheinander auf jedem Server des Clickhouse-Clusters aus.

Wichtiger Hinweis: In dieser Zeile muss logs_cluster durch den Namen Ihres Clusters aus der Datei clickhouse_remote_servers.xml zwischen "remote_servers" und "shard" ersetzt werden.

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

Installation und Konfiguration des nginx-log-collector-rpm

Nginx-log-collector hat kein rpm. Hier https://github.com/patsevanton/nginx-log-collector-rpm erstellen wir ein rpm. Das rpm wird mit Hilfe von Fedora Copr

Wir installieren das rpm-Paket 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

Wir bearbeiten die Konfiguration /etc/nginx-log-collector/config.yaml:

  .......
  upload:
    table: nginx.access_log
    dsn: http://ip-adresse-des-clickhouse-clusters:8123/

- tag: "nginx_error:"
  format: error  # access | error
  buffer_size: 1048576
  upload:
    table: nginx.error_log
    dsn: http://ip-adresse-des-clickhouse-clusters:8123/

Konfiguration von nginx

Allgemeine nginx-Konfiguration:

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

Virtueller Host eins:

vhost1.conf:

upstream backend {
    server ip-adresse-des-servers-mit-stub_http_server:8080;
    server ip-adresse-des-servers-mit-stub_http_server:8080;
    server ip-adresse-des-servers-mit-stub_http_server:8080;
    server ip-adresse-des-servers-mit-stub_http_server:8080;
    server ip-adresse-des-servers-mit-stub_http_server:8080;
}

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

Fügen Sie virtuelle Hosts in die Datei /etc/hosts ein:

ip-adresse-des-servers-mit-nginx vhost1

HTTP-Server-Emulator

Als HTTP-Server-Emulator verwenden wir nodejs-stub-server ab Maxim Ignatenko

Nodejs-stub-server hat kein rpm. Hier https://github.com/patsevanton/nodejs-stub-server erstellen wir ein rpm. Das rpm wird mit Hilfe von Fedora Copr

Installieren Sie das rpm-Paket nodejs-stub-server auf dem upstream nginx

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

Lasttest

Wir führen den Test mit Apache Benchmark durch.

Wir installieren es:

yum install -y httpd-tools

Wir starten den Test mit Apache Benchmark von 5 verschiedenen Servern:

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 einrichten

Auf der offiziellen Website von Grafana finden Sie kein Dashboard.

Deshalb werden wir es manuell machen.

Ihr gespeichertes Dashboard finden Sie hier.

Sie müssen auch eine Variable table mit dem Inhalt erstellen nginx.access_log.
Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Singlestat Gesamtanforderungen:

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

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Singlestat Fehlgeschlagene Anforderungen:

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

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Singlestat Fehlerrate:

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 ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Singlestat Durchschnittliche Reaktionszeit:

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

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Singlestat Maximale Reaktionszeit:

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

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Zählstatus:

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

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Um die Daten als Tortendiagramm anzuzeigen, müssen Sie ein Plugin installieren und Grafana neu starten.

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

Torte TOP 5 Status:

SELECT
    1, 
    /* gefälschter Zeitstempelwert */
    status,
    sum(status) AS Reqs
FROM $table
WHERE $timeFilter
GROUP BY status
ORDER BY Reqs desc
LIMIT 5

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Ich werde die Abfragen weiter ohne Screenshots bereitstellen:

Zähl 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

Reaktionszeiten:

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

Upstream-Antwortzeit (Antwortzeit des ersten Upstreams):

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

Tabelle Zählstatus für alle vhosts:

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

Gesamtansicht des Dashboards

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Vergleich von avg() und quantile()

avg()
Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse
quantile()
Nginx-Log-Collector ist ein Werkzeug von Avito zum Senden von nginx-Logs an Clickhouse

Ausgabe:

Ich hoffe, die Community wird sich an der Entwicklung, dem Testen und der Nutzung des nginx-log-collectors beteiligen.
Und jemand, der den nginx-log-collector implementiert, wird sagen, wie viel Speicherplatz, RAM und CPU gespart wurde.

Telegram-Kanäle:

Millisekunden:

Wer Millisekunden wichtig ist, schreibt bitte oder stimmt in diesem issue.

Quelle: habr.com

60GB SSD 8Gb DDR4