W artykule omówimy projekt , który będzie odczytywał logi nginx i wysyłał je do klastra Clickhouse. Zwykle do logów używa się ElasticSearch. Clickhouse wymaga mniej zasobów (przestrzeni dyskowej, RAM, CPU). Clickhouse szybciej zapisuje dane. Clickhouse kompresuje dane, co czyni je jeszcze bardziej kompaktowymi na dysku. Zalety Clickhouse są widoczne na dwóch slajdach z prezentacji.


Aby przeglądać analitykę logów, stworzymy dashboard dla Grafany.
Zainteresowanych zapraszam pod kat.
Instalujemy nginx, grafanę w standardowy sposób.
Instalujemy klaster Clickhouse za pomocą ansible-playbook od .
Tworzenie bazy danych i tabel w Clickhouse
W tym opisano zapytania SQL do tworzenia bazy danych i tabel dla nginx-log-collector w Clickhouse.
Każde zapytanie wykonujemy kolejno na każdym serwerze klastra Clickhouse.
Ważna uwaga. W tym wierszu logs_cluster należy zastąpić nazwą twojego klastra z pliku clickhouse_remote_servers.xml pomiędzy "remote_servers" a "shard".
ENGINE = Distributed('logs_cluster', 'nginx', 'access_log_shard', rand())Instalacja i konfiguracja nginx-log-collector-rpm
Nginx-log-collector nie ma rpm. Tutaj tworzymy dla niego rpm. Kompilujemy rpm za pomocą
Instalujemy 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-collectorPoprawiamy konfigurację /etc/nginx-log-collector/config.yaml:
.......
upload:
table: nginx.access_log
dsn: http://adres-ip-klastra-clickhouse:8123/
- tag: "nginx_error:"
format: error # access | error
buffer_size: 1048576
upload:
table: nginx.error_log
dsn: http://adres-ip-klastra-clickhouse:8123/Konfiguracja nginx
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-adres-serwera-z-stub_http_server:8080;
server ip-adres-serwera-z-stub_http_server:8080;
server ip-adres-serwera-z-stub_http_server:8080;
server ip-adres-serwera-z-stub_http_server:8080;
server ip-adres-serwera-z-stub_http_server:8080;
}
server {
listen 80;
server_name vhost1;
location / {
proxy_pass http://backend;
}
}Dodajemy do pliku /etc/hosts wirtualne hosty:
ip-adres-serwera-z-nginx vhost1Emulator serwera HTTP
Jako emulator serwera HTTP użyjemy od
Nodejs-stub-server nie posiada rpm. Tutaj tworzymy dla niego rpm. Kompilujemy rpm za pomocą
Instalujemy pakiet rpm nodejs-stub-server na 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_serverTestowanie obciążenia
Testowanie przeprowadzamy za pomocą Apache benchmark.
Instalujemy go:
yum install -y httpd-toolsUruchamiamy testowanie za pomocą Apache benchmark 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; doneKonfiguracja Grafana
Na oficjalnej stronie Grafana nie znajdziesz dashboardu.
Dlatego zrobimy go ręcznie.
Moje zapisane pulpit można znaleźć .
Musisz również utworzyć zmienną table z zawartością nginx.access_log.

Singlestat Łączne Żądania:
SELECT
1 as t,
count(*) as c
FROM $table
WHERE $timeFilter GROUP BY t
Singlestat Nieudane Żądania:
SELECT
1 as t,
count(*) as c
FROM $table
WHERE $timeFilter AND status NOT IN (200, 201, 401) GROUP BY t
Singlestat Procent Niepowodzeń:
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 Średni Czas Odpowiedzi:
SELECT
1, avg(request_time) FROM $table
WHERE $timeFilter GROUP BY 1
Singlestat Maksymalny Czas Odpowiedzi:
SELECT
1 as t, max(request_time) as c
FROM $table
WHERE $timeFilter GROUP BY t
Liczba Statusów:
$columns(status, count(*) as c) FROM $table
Aby wyświetlić dane jako wykres kołowy, należy zainstalować wtyczkę i zrestartować grafanę.
grafana-cli plugins install grafana-piechart-panel
service grafana-server restartWykres Kołowy TOP 5 Statusów:
SELECT
1,
status,
sum(status) AS Reqs
FROM $table
WHERE $timeFilter
GROUP BY status
ORDER BY Reqs desc
LIMIT 5
Kolejne zapytania podam bez zrzutów ekranu:
Liczba http_user_agent:
$columns(http_user_agent, count(*) c) FROM $tableDobra Stawka/Zła Stawka:
$rate(countIf(status = 200) AS good, countIf(status != 200) AS bad) FROM $tableCzas Odpowiedzi:
$rate(avg(request_time) as request_time) FROM $tableCzas odpowiedzi upstream (czasu odpowiedzi 1. upstream):
$rate(avg(arrayElement(upstream_response_time,1)) as upstream_response_time) FROM $tableTabela Liczba Statusów dla wszystkich vhost:
$columns(status, count(*) as c) FROM $tableOgólny widok pulpitu



Porównanie avg() i quantile()
avg()

quantile()

Wynik:
Mam nadzieję, że społeczność dołączy do rozwoju/testowania i używania nginx-log-collector.
I ktoś, kto wdroży nginx-log-collector, opowie, ile zaoszczędził miejsca na dysku, RAM-u, CPU.
Kanały Telegram:
Milisekundy:
Kto potrzebuje milisekund, niech napisze lub zagłosuje, proszę, w tym .
Źródło: habr.com
