En este artículo se analizará el proyecto , que leerá los registros de nginx y los enviará a un clúster de Clickhouse. Normalmente, se utiliza ElasticSearch para los registros. Clickhouse requiere menos recursos (espacio en disco, RAM, CPU). Clickhouse escribe datos más rápido. Clickhouse comprime datos, lo que hace que la información en disco sea aún más compacta. Las ventajas de Clickhouse se evidencian en 2 diapositivas de la presentación.


Para ver la analítica de los registros, crearemos un dashboard para Grafana.
A los interesados, bienvenidos a continuación.
Instalamos nginx y grafana de manera estándar.
Instalamos un clúster de clickhouse utilizando el ansible-playbook de .
Creación de la base de datos y tablas en Clickhouse
En este se describen las consultas SQL para crear la base de datos y tablas para nginx-log-collector en Clickhouse.
Realizamos cada consulta secuencialmente en cada servidor del clúster de Clickhouse.
Nota importante. En esta línea, logs_cluster debe ser reemplazado por el nombre de su clúster del archivo clickhouse_remote_servers.xml entre "remote_servers" y "shard".
ENGINE = Distributed('logs_cluster', 'nginx', 'access_log_shard', rand())Instalación y configuración de nginx-log-collector-rpm
Nginx-log-collector no tiene rpm. Aquí creamos su rpm. El rpm se construirá con la ayuda de
Instalamos el paquete 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-collectorEditamos la configuración /etc/nginx-log-collector/config.yaml:
.......
upload:
table: nginx.access_log
dsn: http://ip-dirección-del-clúster-clickhouse:8123/
- tag: "nginx_error:"
format: error # access | error
buffer_size: 1048576
upload:
table: nginx.error_log
dsn: http://ip-dirección-del-clúster-clickhouse:8123/Configuración de nginx
Configuración general de nginx:
usuario 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;
}
Un host virtual:
vhost1.conf:
upstream backend {
server ip-address-of-server-with-stub_http_server:8080;
server ip-address-of-server-with-stub_http_server:8080;
server ip-address-of-server-with-stub_http_server:8080;
server ip-address-of-server-with-stub_http_server:8080;
server ip-address-of-server-with-stub_http_server:8080;
}
server {
listen 80;
server_name vhost1;
location / {
proxy_pass http://backend;
}
}Agregamos los hosts virtuales en el archivo /etc/hosts:
ip-address-of-server-with-nginx vhost1Emulador de servidor HTTP
Usaremos como emulador de servidor HTTP desde
Nodejs-stub-server no tiene rpm. Aquí creamos su rpm. El rpm se construirá con la ayuda de
Instalamos el paquete rpm nodejs-stub-server en 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_serverPruebas de carga
Realizamos pruebas utilizando Apache benchmark.
Lo instalamos:
yum install -y httpd-toolsIniciamos la prueba con Apache benchmark desde 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; doneConfiguración de Grafana
En el sitio web oficial de Grafana no encontrarás un tablero.
Así que lo haremos manualmente.
Puedes encontrar mi tablero guardado .
También necesitas crear una variable table con el contenido nginx.access_log.

Total de solicitudes de Singlestat:
SELECT
1 as t,
count(*) as c
FROM $table
WHERE $timeFilter GROUP BY t
Solicitudes fallidas de Singlestat:
SELECT
1 as t,
count(*) as c
FROM $table
WHERE $timeFilter AND status NOT IN (200, 201, 401) GROUP BY t
Porcentaje de fallos de 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
Tiempo de respuesta promedio de Singlestat:
SELECT
1, avg(request_time) FROM $table
WHERE $timeFilter GROUP BY 1
Tiempo de respuesta máximo de Singlestat:
SELECT
1 as t, max(request_time) as c
FROM $table
WHERE $timeFilter GROUP BY t
Contar estado:
$columns(status, count(*) as c) from $table
Para mostrar los datos como un gráfico circular, necesitas instalar el complemento y reiniciar grafana.
grafana-cli plugins install grafana-piechart-panel
service grafana-server restartGráfico circular de los 5 principales estados:
SELECT
1,
/* valor de tiempo falso */
status,
sum(status) AS Reqs
FROM $table
WHERE $timeFilter
GROUP BY status
ORDER BY Reqs desc
LIMIT 5
A continuación, proporcionaré las consultas sin capturas de pantalla:
Contar http_user_agent:
$columns(http_user_agent, count(*) c) FROM $tableTasa buena/tasa mala:
$rate(countIf(status = 200) AS good, countIf(status != 200) AS bad) FROM $tableTemporización de respuesta:
$rate(avg(request_time) as request_time) FROM $tableTiempo de respuesta del upstream (tiempo de respuesta del primer upstream):
$rate(avg(arrayElement(upstream_response_time,1)) as upstream_response_time) FROM $tableContar estado de tabla para todos los vhosts:
$columns(status, count(*) as c) from $tableVista general del dashboard



Comparación de avg() y quantile()
avg()

quantile()

Salida:
Espero que la comunidad se una al desarrollo/prueba y uso de nginx-log-collector.
Y alguien que implemente nginx-log-collector cuente cuánto ha ahorrado en disco, RAM, CPU.
Canales de Telegram:
Milisegundos:
A quienes les importan los milisegundos, por favor, escriban o voten en esto .
Fuente: habr.com
