Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Este artigo discutirá o projeto coletor de log nginx, que lerá os logs do nginx e os enviará para o cluster Clickhouse. Normalmente o ElasticSearch é usado para logs. Clickhouse requer menos recursos (espaço em disco, RAM, CPU). Clickhouse registra dados com mais rapidez. Clickhouse compacta dados, tornando os dados em disco ainda mais compactos. As vantagens do Clickhouse ficam visíveis em 2 slides do relatório Como o VK insere dados no ClickHouse de dezenas de milhares de servidores.

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Para visualizar análises baseadas em logs, criaremos um painel para Grafana.

Quem estiver interessado, seja bem-vindo ao gato.

Instale o nginx, grafana da maneira padrão.

Instalando um cluster clickhouse usando ansible-playbook de Denis Proskurin.

Criando bancos de dados e tabelas no Clickhouse

Neste arquivo São descritas consultas SQL para criação de bancos de dados e tabelas para nginx-log-collector em Clickhouse.

Fazemos cada solicitação uma por uma em cada servidor do cluster Clickhouse.

Nota importante. Nesta linha, logs_cluster precisa ser substituído pelo nome do cluster do arquivo clickhouse_remote_servers.xml entre "remote_servers" e "shard".

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

Instalando e configurando nginx-log-collector-rpm

O Nginx-log-collector não possui rpm. Aqui https://github.com/patsevanton/nginx-log-collector-rpm crie rpm para ele. rpm será compilado usando Fedora CoprName

Instale o pacote 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

Edite a configuração /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/

Configurando o nginx

Configuração geral do 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;
}

Um host virtual:

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

Adicione hosts virtuais ao arquivo /etc/hosts:

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

Emulador de servidor HTTP

Como emulador de servidor HTTP usaremos servidor nodejs-stub de Máximo Ignatenko

Nodejs-stub-server não possui rpm. Aqui https://github.com/patsevanton/nodejs-stub-server crie rpm para ele. rpm será compilado usando Fedora CoprName

Instale o pacote nodejs-stub-server no 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

Teste de estresse

Realizamos testes usando o benchmark Apache.

Instale-o:

yum install -y httpd-tools

Começamos os testes usando o benchmark Apache de 5 servidores diferentes:

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

Configurando o Grafana

Você não encontrará um painel no site oficial do Grafana.

Portanto, faremos isso manualmente.

Você pode encontrar meu painel salvo aqui.

Você também precisa criar uma variável de tabela com o conteúdo nginx.access_log.
Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Total de solicitações do Singlestat:

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

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Solicitações com falha no Singlestat:

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

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Porcentagem de falha do Singlestat:

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

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Tempo médio de resposta do Singlestat:

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

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Tempo máximo de resposta do Singlestat:

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

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Status da contagem:

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

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Para gerar dados como uma torta, você precisa instalar o plugin e reiniciar o grafana.

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

Torta 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

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Além disso, darei solicitações sem capturas de tela:

Contagem http_user_agent:

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

Taxa boa/taxa ruim:

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

Tempo de resposta:

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

Tempo de resposta upstream (1º tempo de resposta upstream):

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

Status de contagem de tabelas para todos os vhost:

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

Visão geral do painel

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Comparação de avg() e quantil()

média()
Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse
quantil()
Utilitário Nginx-log-collector da Avito para enviar logs nginx para Clickhouse

Conclusão:

Espero que a comunidade se envolva no desenvolvimento/teste e no uso do nginx-log-collector.
E quando alguém implementa o nginx-log-collector, ele dirá quanto disco, RAM e CPU economizaram.

Canais de telegrama:

Milissegundos:

Para quem os milissegundos importam, por favor escreva ou vote neste emitem.

Fonte: habr.com

Adicionar um comentário