Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

In questo articolo verrà esaminato il progetto nginx-log-collector, che leggerà i log di nginx e li invierà al cluster Clickhouse. Di solito, per i log si utilizza ElasticSearch. Clickhouse richiede meno risorse (spazio su disco, RAM, CPU). Clickhouse scrive i dati più rapidamente. Clickhouse comprime i dati, rendendo i dati sul disco ancora più compatti. I vantaggi di Clickhouse sono evidenti in 2 diapositive della presentazione Come VK inserisce i dati in ClickHouse da decine di migliaia di server.

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Per visualizzare l'analisi dei log, creeremo un dashboard per Grafana.

Chi è interessato, è benvenuto sotto il tag.

Installiamo nginx e grafana nel modo standard.

Installiamo un cluster Clickhouse utilizzando l'ansible-playbook di Denis Proskurin.

Creazione del db e delle tabelle in Clickhouse

In questo file sono descritti i comandi SQL per creare db e tabelle per nginx-log-collector in Clickhouse.

Eseguiamo ogni comando in sequenza su ciascun server del cluster Clickhouse.

Nota importante. In questa riga, è necessario sostituire logs_cluster con il nome del tuo cluster dal file clickhouse_remote_servers.xml tra "remote_servers" e "shard".

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

Installazione e configurazione di nginx-log-collector-rpm

Nginx-log-collector non ha un rpm. Qui https://github.com/patsevanton/nginx-log-collector-rpm creiamo un rpm. Il rpm verrà creato utilizzando Fedora Copr

Installa il pacchetto 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

Modifichiamo la configurazione /etc/nginx-log-collector/config.yaml:

  .......
  upload:
    table: nginx.access_log
    dsn: http://ip-indirizzo-cluster-clickhouse:8123/

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

Configurazione di nginx

Configurazione generale di 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;
}

Host virtuale uno:

vhost1.conf:

upstream backend {
    server ip-indirizzo-del-server-con-stub_http_server:8080;
    server ip-indirizzo-del-server-con-stub_http_server:8080;
    server ip-indirizzo-del-server-con-stub_http_server:8080;
    server ip-indirizzo-del-server-con-stub_http_server:8080;
    server ip-indirizzo-del-server-con-stub_http_server:8080;
}

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

Aggiungiamo nel file /etc/hosts gli host virtuali:

ip-indirizzo-del-server-con-nginx vhost1

Emulatore di server HTTP

Utilizzeremo come emulatore di server HTTP nodejs-stub-server di Maxim Ignatenko

Nodejs-stub-server non ha rpm. Qui https://github.com/patsevanton/nodejs-stub-server creiamo un rpm. Il rpm verrà creato utilizzando Fedora Copr

Installiamo il pacchetto rpm di nodejs-stub-server su 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

Test di carico

Effettueremo il test utilizzando Apache benchmark.

Lo installiamo:

yum install -y httpd-tools

Avviamo il test utilizzando Apache benchmark da 5 diversi server:

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

Configurazione di Grafana

Sul sito ufficiale di Grafana non troverete un dashboard.

Perciò lo faremo manualmente.

Il mio dashboard salvato può essere trovato qui.

Devi anche creare una variabile table con il contenuto nginx.access_log.
Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Singlestat Totale Richieste:

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

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Singlestat Richieste Fallite:

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

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Singlestat Percentuale di Fallimenti:

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 è uno strumento di Avito per inviare i log di nginx a Clickhouse

Singlestat Tempo Medio di Risposta:

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

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Singlestat Tempo Max di Risposta:

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

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Conteggio Stato:

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

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Per visualizzare i dati come un grafico a torta, è necessario installare il plugin e riavviare grafana.

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

Torta TOP 5 Stato:

SELECT
    1, 
    status,
    sum(status) AS Reqs
FROM $table
WHERE $timeFilter
GROUP BY status
ORDER BY Reqs desc
LIMIT 5

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Successivamente fornirò le query senza screenshot:

Conteggio http_user_agent:

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

Buona Percentuale / Cattiva Percentuale:

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

Tempi di Risposta:

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

Tempo di risposta del backend (tempo di risposta del primo backend):

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

Conteggio Stato della Tabella per tutti i vhost:

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

Vista generale del dashboard

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Confronto avg() e quantile()

avg()
Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse
quantile()
Nginx-log-collector è uno strumento di Avito per inviare i log di nginx a Clickhouse

Conclusione:

Spero che la community partecipi allo sviluppo/test e utilizzo di nginx-log-collector.
E chiunque implementi nginx-log-collector racconterà quanto ha risparmiato in spazio disco, RAM, CPU.

Canali Telegram:

Millisecondi:

Chi è interessato ai millisecondi, per favore scrivere o votare in questo problema.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster