Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

In diesem Artikel wird das Projekt besprochen Nginx-Log-Collector, das Nginx-Protokolle liest und sie an den Clickhouse-Cluster sendet. Normalerweise wird ElasticSearch für Protokolle verwendet. Clickhouse benötigt weniger Ressourcen (Speicherplatz, RAM, CPU). Clickhouse schreibt Daten schneller. Clickhouse komprimiert die Daten, wodurch die Daten auf der Festplatte noch kompakter werden. Die Vorteile von Clickhouse sind auf zwei Folien des Berichts zu sehen Wie VK Daten von Zehntausenden Servern in ClickHouse einfügt.

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Um Analysen nach Protokollen anzuzeigen, erstellen wir ein Dashboard für Grafana.

Wen kümmert's, willkommen unter Katze.

Installieren Sie Nginx und Grafana auf die Standardmethode.

Installieren Sie den Clickhouse-Cluster mit Ansible-Playbook von Denis Proskurin.

Erstellen einer Datenbank und Tabellen in Clickhouse

Hierin Datei Es werden SQL-Abfragen zum Erstellen von Datenbanken und Tabellen für nginx-log-collector in Clickhouse beschrieben.

Wir stellen jede Anfrage der Reihe nach auf jedem Server des Clickhouse-Clusters.

Wichtiger Hinweis. In dieser Zeile sollte logs_cluster durch Ihren Clusternamen aus der Datei clickhouse_remote_servers.xml zwischen „remote_servers“ und „shard“ ersetzt werden.

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

Nginx-log-collector-rpm installieren und konfigurieren

Nginx-Log-Collector hat kein RPM. Hier https://github.com/patsevanton/nginx-log-collector-rpm Erstellen Sie rpm dafür. rpm wird mit erstellt Fedora Copr

Installieren Sie 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

Bearbeiten Sie die Konfiguration /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 einrichten

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-адрес-сервера-с-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;
    }
}

Fügen Sie virtuelle Hosts zur Datei /etc/hosts hinzu:

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

HTTP-Server-Emulator

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

nodejs-stub-server hat kein rpm. Hier https://github.com/patsevanton/nodejs-stub-server Erstellen Sie rpm dafür. rpm wird mit erstellt Fedora Copr

Installieren Sie das Paket „nodejs-stub-server“ auf dem 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

Belastbarkeitstest

Die Tests werden mit dem Apache-Benchmark durchgeführt.

Es installieren:

yum install -y httpd-tools

Wir beginnen mit dem Testen mithilfe des Apache-Benchmarks 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 Grafana-Website finden Sie kein Dashboard.

Deshalb werden wir es von Hand machen.

Sie finden mein gespeichertes Dashboard hier.

Sie müssen außerdem eine Tabellenvariable mit dem Inhalt erstellen nginx.access_log.
Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Gesamtanzahl der Singlestat-Anfragen:

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

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Fehlgeschlagene Singlestat-Anfragen:

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

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Singlestat-Ausfallprozentsatz:

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-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Durchschnittliche Antwortzeit von Singlestat:

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

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Maximale Singlestat-Reaktionszeit:

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

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Zählstatus:

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

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Um Daten wie einen Kuchen auszugeben, müssen Sie das Plugin installieren und Grafana neu laden.

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

Kuchen 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-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Weiter werde ich Anfragen ohne Screenshots stellen:

Zählen Sie 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

Reaktionszeitpunkt:

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

Upstream-Reaktionszeit (Reaktionszeit des 1. Upstreams):

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

Tabellenzählstatus für alle Vhosts:

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

Gesamtansicht des Dashboards

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Vergleich von avg() und quantile()

avg()
Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse
Quantil()
Nginx-Log-Collector-Dienstprogramm von Avito zum Senden von Nginx-Protokollen an Clickhouse

Fazit:

Hoffentlich wird sich die Community an der Entwicklung/Testung und Verwendung von nginx-log-collector beteiligen.
Und wenn jemand Nginx-Log-Collector implementiert, wird er Ihnen sagen, wie viel er Festplatte, RAM und CPU gespart hat.

Telegram-Kanäle:

Millisekunden:

Wen interessieren Millisekunden? Bitte schreiben oder stimmen Sie hier ab Problem.

Source: habr.com

Kommentar hinzufügen