In diesem Artikel wird das Projekt behandelt, 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.


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 .
Erstellung der DB und Tabellen in Clickhouse
In dieser 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 erstellen wir ein rpm. Das rpm wird mit Hilfe von
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-collectorWir 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 vhost1HTTP-Server-Emulator
Als HTTP-Server-Emulator verwenden wir ab
Nodejs-stub-server hat kein rpm. Hier erstellen wir ein rpm. Das rpm wird mit Hilfe von
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_serverLasttest
Wir fĂŒhren den Test mit Apache Benchmark durch.
Wir installieren es:
yum install -y httpd-toolsWir 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; doneGrafana einrichten
Auf der offiziellen Website von Grafana finden Sie kein Dashboard.
Deshalb werden wir es manuell machen.
Ihr gespeichertes Dashboard finden Sie .
Sie mĂŒssen auch eine Variable table mit dem Inhalt erstellen nginx.access_log.

Singlestat Gesamtanforderungen:
SELECT
1 as t,
count(*) as c
FROM $table
WHERE $timeFilter GROUP BY t
Singlestat Fehlgeschlagene Anforderungen:
SELECT
1 as t,
count(*) as c
FROM $table
WHERE $timeFilter AND status NOT IN (200, 201, 401) GROUP BY t
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
Singlestat Durchschnittliche Reaktionszeit:
SELECT
1, avg(request_time) FROM $table
WHERE $timeFilter GROUP BY 1
Singlestat Maximale Reaktionszeit:
SELECT
1 as t, max(request_time) as c
FROM $table
WHERE $timeFilter GROUP BY t
ZĂ€hlstatus:
$columns(status, count(*) as c) from $table
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 restartTorte 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
Ich werde die Abfragen weiter ohne Screenshots bereitstellen:
ZĂ€hl http_user_agent:
$columns(http_user_agent, count(*) c) FROM $tableGoodRate/BadRate:
$rate(countIf(status = 200) AS good, countIf(status != 200) AS bad) FROM $tableReaktionszeiten:
$rate(avg(request_time) as request_time) FROM $tableUpstream-Antwortzeit (Antwortzeit des ersten Upstreams):
$rate(avg(arrayElement(upstream_response_time,1)) as upstream_response_time) FROM $tableTabelle ZĂ€hlstatus fĂŒr alle vhosts:
$columns(status, count(*) as c) from $tableGesamtansicht des Dashboards



Vergleich von avg() und quantile()
avg()

quantile()

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 .
Quelle: habr.com
