Aleksey Lizunov, Chefe do Centro de Competência para Canais de Atendimento Remoto da Diretoria de Tecnologias da Informação do MKB
Como alternativa à pilha ELK (ElasticSearch, Logstash, Kibana), estamos pesquisando sobre o uso do banco de dados ClickHouse como um armazenamento de dados para logs.
Neste artigo, gostaríamos de falar sobre nossa experiência de uso do banco de dados ClickHouse e os resultados preliminares da operação piloto. Deve-se notar desde já que os resultados foram impressionantes.
A seguir, descreveremos com mais detalhes como nosso sistema está configurado e em quais componentes ele consiste. Mas agora gostaria de falar um pouco sobre esse banco de dados como um todo e porque vale a pena ficar atento. O banco de dados ClickHouse é um banco de dados colunar analítico de alto desempenho da Yandex. É usado nos serviços Yandex, inicialmente é o principal armazenamento de dados do Yandex.Metrica. Sistema de código aberto, gratuito. Do ponto de vista de um desenvolvedor, sempre me perguntei como eles o implementaram, porque há dados fantasticamente grandes. E a própria interface de usuário do Metrica é muito flexível e rápida. Ao primeiro contato com esse banco de dados, a impressão é: “Bem, finalmente! Feito para o povo! Começando com o processo de instalação e terminando com o envio de solicitações.
Este banco de dados tem um limite de entrada muito baixo. Mesmo um desenvolvedor mediano pode instalar esse banco de dados em poucos minutos e começar a usá-lo. Tudo funciona claramente. Mesmo as pessoas que são novas no Linux podem lidar rapidamente com a instalação e fazer as operações mais simples. Se antes, com as palavras Big Data, Hadoop, Google BigTable, HDFS, um desenvolvedor comum tinha ideias de que se tratava de alguns terabytes, petabytes, que alguns super-humanos estão envolvidos em configurações e desenvolvimento para esses sistemas, então com o advento do ClickHouse banco de dados, temos uma ferramenta simples e compreensível com a qual você pode resolver uma gama de tarefas anteriormente inatingíveis. Leva apenas uma máquina razoavelmente média e cinco minutos para instalar. Ou seja, obtivemos um banco de dados como, por exemplo, MySql, mas apenas para armazenar bilhões de registros! Um certo super-arquivador com a linguagem SQL. É como se as pessoas tivessem recebido armas de alienígenas.
Sobre nosso sistema de registro
Para coletar informações, são usados arquivos de log do IIS de aplicativos da Web de formato padrão (no momento, também estamos analisando logs de aplicativos, mas o objetivo principal no estágio piloto é coletar logs do IIS).
Por vários motivos, não poderíamos abandonar completamente a pilha ELK e continuamos a usar os componentes LogStash e Filebeat, que se mostraram bons e funcionam de maneira confiável e previsível.
O esquema geral de registro é mostrado na figura abaixo:
Um recurso de gravação de dados no banco de dados ClickHouse é a inserção pouco frequente (uma vez por segundo) de registros em grandes lotes. Esta, aparentemente, é a parte mais “problemática” que você encontra quando trabalha pela primeira vez com o banco de dados ClickHouse: o esquema torna-se um pouco mais complicado.
O plugin para LogStash, que insere dados diretamente no ClickHouse, ajudou muito aqui. Esse componente é implantado no mesmo servidor que o próprio banco de dados. Então, de um modo geral, não é recomendável fazê-lo, mas do ponto de vista prático, para não produzir servidores separados enquanto estiver implantado no mesmo servidor. Não observamos nenhuma falha ou conflito de recursos com o banco de dados. Além disso, deve-se notar que o plug-in possui um mecanismo de repetição em caso de erros. E em caso de erros, o plug-in grava no disco um lote de dados que não pôde ser inserido (o formato do arquivo é conveniente: após a edição, você pode inserir facilmente o lote corrigido usando o clickhouse-client).
Uma lista completa de softwares usados no esquema é apresentada na tabela:
Lista de softwares usados
Nome
descrição
link de distribuição
NGINX
Proxy reverso para restringir o acesso por portas e organizar a autorização
Atualmente não usado no esquema
ArquivoBeat
Transferência de logs de arquivo.
logstash
Coletor de log.
Usado para coletar logs do FileBeat, bem como para coletar logs da fila do RabbitMQ (para servidores que estão na DMZ).
Logstash-output-clickhouse
Plug-in Loagstash para transferir logs para o banco de dados ClickHouse em lotes
/usr/share/logstash/bin/logstash-plugin instalar logstash-output-clickhouse
/usr/share/logstash/bin/logstash-plugin instalar logstash-filter-prune
/usr/share/logstash/bin/logstash-plugin instalar logstash-filter-multiline
clickhouse
Armazenamento de registros
Observação. A partir de agosto de 2018, as compilações rpm “normais” para RHEL apareceram no repositório Yandex, para que você possa tentar usá-las. No momento da instalação, estávamos usando pacotes criados pelo Altinity.
grafana
Visualização de log. Configurando painéis
Redhat & Centos(64 bits) - versão mais recente
Fonte de dados ClickHouse para Grafana 4.6+
Plugin para Grafana com fonte de dados ClickHouse
logstash
Roteador de log do FileBeat para a fila do RabbitMQ.
Observação. Infelizmente, o FileBeat não envia diretamente para o RabbitMQ, portanto, é necessário um link intermediário na forma de Logstash
RabbitMQ
fila de mensagens. Este é o buffer de log na DMZ
Erlang Runtime (Necessário para RabbitMQ)
Tempo de execução do Erlang. Necessário para RabbitMQ funcionar
A configuração do servidor com o banco de dados ClickHouse é apresentada na tabela a seguir:
Nome
Valor
Nota
Configuração
HDD: 40GB
RAM: 8GB
Processador: Core 2 2Ghz
É preciso ficar atento às dicas de operação do banco de dados ClickHouse (
Software geral do sistema
SO: Red Hat Enterprise Linux Server (Maipo)
JRE (Java8)
Como você pode ver, esta é uma estação de trabalho comum.
A estrutura da tabela para armazenamento de logs é a seguinte:
log_web.sql
CREATE TABLE log_web (
logdate Date,
logdatetime DateTime CODEC(Delta, LZ4HC),
fld_log_file_name LowCardinality( String ),
fld_server_name LowCardinality( String ),
fld_app_name LowCardinality( String ),
fld_app_module LowCardinality( String ),
fld_website_name LowCardinality( String ),
serverIP LowCardinality( String ),
method LowCardinality( String ),
uriStem String,
uriQuery String,
port UInt32,
username LowCardinality( String ),
clientIP String,
clientRealIP String,
userAgent String,
referer String,
response String,
subresponse String,
win32response String,
timetaken UInt64
, uriQuery__utm_medium String
, uriQuery__utm_source String
, uriQuery__utm_campaign String
, uriQuery__utm_term String
, uriQuery__utm_content String
, uriQuery__yclid String
, uriQuery__region String
) Engine = MergeTree()
PARTITION BY toYYYYMM(logdate)
ORDER BY (fld_app_name, fld_app_module, logdatetime)
SETTINGS index_granularity = 8192;
Usamos particionamento padrão (por mês) e granularidade de índice. Todos os campos correspondem praticamente às entradas de log do IIS para registrar solicitações http. Separadamente, notamos que existem campos separados para armazenar tags utm (eles são analisados no estágio de inserção na tabela a partir do campo de string de consulta).
Além disso, vários campos do sistema foram adicionados à tabela para armazenar informações sobre sistemas, componentes e servidores. Consulte a tabela abaixo para obter uma descrição desses campos. Em uma tabela, armazenamos logs para vários sistemas.
Nome
descrição
Exemplo
fld_app_name
Nome do aplicativo/sistema
Valores válidos:
- site1.domain.com Site externo 1
- site2.domain.com Site externo 2
- internal-site1.domain.local Site interno 1
site1.dominio.com
fld_app_module
módulo do sistema
Valores válidos:
- web - site
- svc - serviço de site
- intgr - Serviço Web de Integração
- bo - Admin (BackOffice)
web
fld_website_name
Nome do site no IIS
Vários sistemas podem ser implantados em um servidor ou até mesmo várias instâncias de um módulo de sistema
web principal
nome_do_servidor_fld
Nome do servidor
web1.dominio.com
fld_log_file_name
Caminho para o arquivo de log no servidor
C:inetpublogsLogFiles
W3SVC1u_ex190711.log
Isso permite que você crie gráficos com eficiência no Grafana. Por exemplo, visualize as solicitações do front-end de um sistema específico. Isso é semelhante ao contador de sites no Yandex.Metrica.
Aqui estão algumas estatísticas sobre o uso do banco de dados por dois meses.
Número de registros divididos por sistemas e seus componentes
SELECT
fld_app_name,
fld_app_module,
count(fld_app_name) AS rows_count
FROM log_web
GROUP BY
fld_app_name,
fld_app_module
WITH TOTALS
ORDER BY
fld_app_name ASC,
rows_count DESC
┌─fld_app_name─────┬─fld_app_module─┬─rows_count─┐
│ site1.domain.ru │ web │ 131441 │
│ site2.domain.ru │ web │ 1751081 │
│ site3.domain.ru │ web │ 106887543 │
│ site3.domain.ru │ svc │ 44908603 │
│ site3.domain.ru │ intgr │ 9813911 │
│ site4.domain.ru │ web │ 772095 │
│ site5.domain.ru │ web │ 17037221 │
│ site5.domain.ru │ intgr │ 838559 │
│ site5.domain.ru │ bo │ 7404 │
│ site6.domain.ru │ web │ 595877 │
│ site7.domain.ru │ web │ 27778858 │
└──────────────────┴────────────────┴────────────┘
Totals:
┌─fld_app_name─┬─fld_app_module─┬─rows_count─┐
│ │ │ 210522593 │
└──────────────┴────────────────┴────────────┘
11 rows in set. Elapsed: 4.874 sec. Processed 210.52 million rows, 421.67 MB (43.19 million rows/s., 86.51 MB/s.)
A quantidade de dados no disco
SELECT
formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed,
formatReadableSize(sum(data_compressed_bytes)) AS compressed,
sum(rows) AS total_rows
FROM system.parts
WHERE table = 'log_web'
┌─uncompressed─┬─compressed─┬─total_rows─┐
│ 54.50 GiB │ 4.86 GiB │ 211427094 │
└──────────────┴────────────┴────────────┘
1 rows in set. Elapsed: 0.035 sec.
Grau de compactação de dados em colunas
SELECT
name,
formatReadableSize(data_uncompressed_bytes) AS uncompressed,
formatReadableSize(data_compressed_bytes) AS compressed,
data_uncompressed_bytes / data_compressed_bytes AS compress_ratio
FROM system.columns
WHERE table = 'log_web'
┌─name───────────────────┬─uncompressed─┬─compressed─┬─────compress_ratio─┐
│ logdate │ 401.53 MiB │ 1.80 MiB │ 223.16665968777315 │
│ logdatetime │ 803.06 MiB │ 35.91 MiB │ 22.363966401202305 │
│ fld_log_file_name │ 220.66 MiB │ 2.60 MiB │ 84.99905736932571 │
│ fld_server_name │ 201.54 MiB │ 50.63 MiB │ 3.980924816977078 │
│ fld_app_name │ 201.17 MiB │ 969.17 KiB │ 212.55518183686877 │
│ fld_app_module │ 201.17 MiB │ 968.60 KiB │ 212.67805817411906 │
│ fld_website_name │ 201.54 MiB │ 1.24 MiB │ 162.7204926761546 │
│ serverIP │ 201.54 MiB │ 50.25 MiB │ 4.010824061219731 │
│ method │ 201.53 MiB │ 43.64 MiB │ 4.617721053304486 │
│ uriStem │ 5.13 GiB │ 832.51 MiB │ 6.311522291936919 │
│ uriQuery │ 2.58 GiB │ 501.06 MiB │ 5.269731450124478 │
│ port │ 803.06 MiB │ 3.98 MiB │ 201.91673864241824 │
│ username │ 318.08 MiB │ 26.93 MiB │ 11.812513794583598 │
│ clientIP │ 2.35 GiB │ 82.59 MiB │ 29.132328640073343 │
│ clientRealIP │ 2.49 GiB │ 465.05 MiB │ 5.478382297052563 │
│ userAgent │ 18.34 GiB │ 764.08 MiB │ 24.57905114484208 │
│ referer │ 14.71 GiB │ 1.37 GiB │ 10.736792723669906 │
│ response │ 803.06 MiB │ 83.81 MiB │ 9.582334090987247 │
│ subresponse │ 399.87 MiB │ 1.83 MiB │ 218.4831068635027 │
│ win32response │ 407.86 MiB │ 7.41 MiB │ 55.050315514606815 │
│ timetaken │ 1.57 GiB │ 402.06 MiB │ 3.9947395692010637 │
│ uriQuery__utm_medium │ 208.17 MiB │ 12.29 MiB │ 16.936148912472955 │
│ uriQuery__utm_source │ 215.18 MiB │ 13.00 MiB │ 16.548367623199912 │
│ uriQuery__utm_campaign │ 381.46 MiB │ 37.94 MiB │ 10.055156353418509 │
│ uriQuery__utm_term │ 231.82 MiB │ 10.78 MiB │ 21.502540454070672 │
│ uriQuery__utm_content │ 441.34 MiB │ 87.60 MiB │ 5.038260760449327 │
│ uriQuery__yclid │ 216.88 MiB │ 16.58 MiB │ 13.07721335008116 │
│ uriQuery__region │ 204.35 MiB │ 9.49 MiB │ 21.52661903446796 │
└────────────────────────┴──────────────┴────────────┴────────────────────┘
28 rows in set. Elapsed: 0.005 sec.
Descrição dos componentes usados
FileBeat. Transferindo logs de arquivo
Esse componente rastreia as alterações nos arquivos de log no disco e passa as informações para o LogStash. Instalado em todos os servidores onde os arquivos de log são gravados (geralmente IIS). Funciona em modo tail (ou seja, transfere apenas os registros adicionados ao arquivo). Mas separadamente pode ser configurado para transferir arquivos inteiros. Isso é útil quando você precisa baixar dados de meses anteriores. Basta colocar o arquivo de log em uma pasta e ele o lerá na íntegra.
Quando o serviço é interrompido, os dados não são mais transferidos para o armazenamento.
Um exemplo de configuração se parece com isto:
arquivobeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- C:/inetpub/logs/LogFiles/W3SVC1/*.log
exclude_files: ['.gz$','.zip$']
tail_files: true
ignore_older: 24h
fields:
fld_server_name: "site1.domain.ru"
fld_app_name: "site1.domain.ru"
fld_app_module: "web"
fld_website_name: "web-main"
- type: log
enabled: true
paths:
- C:/inetpub/logs/LogFiles/__Import/access_log-*
exclude_files: ['.gz$','.zip$']
tail_files: false
fields:
fld_server_name: "site2.domain.ru"
fld_app_name: "site2.domain.ru"
fld_app_module: "web"
fld_website_name: "web-main"
fld_logformat: "logformat__apache"
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
reload.period: 2s
output.logstash:
hosts: ["log.domain.com:5044"]
ssl.enabled: true
ssl.certificate_authorities: ["C:/filebeat/certs/ca.pem", "C:/filebeat/certs/ca-issuing.pem"]
ssl.certificate: "C:/filebeat/certs/site1.domain.ru.cer"
ssl.key: "C:/filebeat/certs/site1.domain.ru.key"
#================================ Processors =====================================
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
logstash. Coletor de registros
Este componente é projetado para receber entradas de log do FileBeat (ou através da fila RabbitMQ), analisando e inserindo lotes no banco de dados ClickHouse.
Para inserção no ClickHouse, o plug-in Logstash-output-clickhouse é usado. O plug-in Logstash possui um mecanismo de repetição de consulta, mas com um desligamento regular, é melhor interromper o próprio serviço. Quando parado, as mensagens serão acumuladas na fila do RabbitMQ, portanto, se a parada for por muito tempo, é melhor parar o Filebeats nos servidores. Em um esquema em que o RabbitMQ não é usado (na rede local, o Filebeat envia logs diretamente para o Logstash), o Filebeats funciona de maneira bastante aceitável e segura, portanto, para eles, a indisponibilidade da saída passa sem consequências.
Um exemplo de configuração se parece com isto:
log_web__filebeat_clickhouse.conf
input {
beats {
port => 5044
type => 'iis'
ssl => true
ssl_certificate_authorities => ["/etc/logstash/certs/ca.cer", "/etc/logstash/certs/ca-issuing.cer"]
ssl_certificate => "/etc/logstash/certs/server.cer"
ssl_key => "/etc/logstash/certs/server-pkcs8.key"
ssl_verify_mode => "peer"
add_field => {
"fld_server_name" => "%{[fields][fld_server_name]}"
"fld_app_name" => "%{[fields][fld_app_name]}"
"fld_app_module" => "%{[fields][fld_app_module]}"
"fld_website_name" => "%{[fields][fld_website_name]}"
"fld_log_file_name" => "%{source}"
"fld_logformat" => "%{[fields][fld_logformat]}"
}
}
rabbitmq {
host => "queue.domain.com"
port => 5671
user => "q-reader"
password => "password"
queue => "web_log"
heartbeat => 30
durable => true
ssl => true
#ssl_certificate_path => "/etc/logstash/certs/server.p12"
#ssl_certificate_password => "password"
add_field => {
"fld_server_name" => "%{[fields][fld_server_name]}"
"fld_app_name" => "%{[fields][fld_app_name]}"
"fld_app_module" => "%{[fields][fld_app_module]}"
"fld_website_name" => "%{[fields][fld_website_name]}"
"fld_log_file_name" => "%{source}"
"fld_logformat" => "%{[fields][fld_logformat]}"
}
}
}
filter {
if [message] =~ "^#" {
drop {}
}
if [fld_logformat] == "logformat__iis_with_xrealip" {
grok {
match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{IP:serverIP} %{WORD:method} %{NOTSPACE:uriStem} %{NOTSPACE:uriQuery} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:clientIP} %{NOTSPACE:userAgent} %{NOTSPACE:referer} %{NUMBER:response} %{NUMBER:subresponse} %{NUMBER:win32response} %{NUMBER:timetaken} %{NOTSPACE:xrealIP} %{NOTSPACE:xforwarderfor}"]
}
} else {
grok {
match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{IP:serverIP} %{WORD:method} %{NOTSPACE:uriStem} %{NOTSPACE:uriQuery} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:clientIP} %{NOTSPACE:userAgent} %{NOTSPACE:referer} %{NUMBER:response} %{NUMBER:subresponse} %{NUMBER:win32response} %{NUMBER:timetaken}"]
}
}
date {
match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss" ]
timezone => "Etc/UTC"
remove_field => [ "log_timestamp", "@timestamp" ]
target => [ "log_timestamp2" ]
}
ruby {
code => "tstamp = event.get('log_timestamp2').to_i
event.set('logdatetime', Time.at(tstamp).strftime('%Y-%m-%d %H:%M:%S'))
event.set('logdate', Time.at(tstamp).strftime('%Y-%m-%d'))"
}
if [bytesSent] {
ruby {
code => "event['kilobytesSent'] = event['bytesSent'].to_i / 1024.0"
}
}
if [bytesReceived] {
ruby {
code => "event['kilobytesReceived'] = event['bytesReceived'].to_i / 1024.0"
}
}
ruby {
code => "event.set('clientRealIP', event.get('clientIP'))"
}
if [xrealIP] {
ruby {
code => "event.set('clientRealIP', event.get('xrealIP'))"
}
}
if [xforwarderfor] {
ruby {
code => "event.set('clientRealIP', event.get('xforwarderfor'))"
}
}
mutate {
convert => ["bytesSent", "integer"]
convert => ["bytesReceived", "integer"]
convert => ["timetaken", "integer"]
convert => ["port", "integer"]
add_field => {
"clientHostname" => "%{clientIP}"
}
}
useragent {
source=> "useragent"
prefix=> "browser"
}
kv {
source => "uriQuery"
prefix => "uriQuery__"
allow_duplicate_values => false
field_split => "&"
include_keys => [ "utm_medium", "utm_source", "utm_campaign", "utm_term", "utm_content", "yclid", "region" ]
}
mutate {
join => { "uriQuery__utm_source" => "," }
join => { "uriQuery__utm_medium" => "," }
join => { "uriQuery__utm_campaign" => "," }
join => { "uriQuery__utm_term" => "," }
join => { "uriQuery__utm_content" => "," }
join => { "uriQuery__yclid" => "," }
join => { "uriQuery__region" => "," }
}
}
output {
#stdout {codec => rubydebug}
clickhouse {
headers => ["Authorization", "Basic abcdsfks..."]
http_hosts => ["http://127.0.0.1:8123"]
save_dir => "/etc/logstash/tmp"
table => "log_web"
request_tolerance => 1
flush_size => 10000
idle_flush_time => 1
mutations => {
"fld_log_file_name" => "fld_log_file_name"
"fld_server_name" => "fld_server_name"
"fld_app_name" => "fld_app_name"
"fld_app_module" => "fld_app_module"
"fld_website_name" => "fld_website_name"
"logdatetime" => "logdatetime"
"logdate" => "logdate"
"serverIP" => "serverIP"
"method" => "method"
"uriStem" => "uriStem"
"uriQuery" => "uriQuery"
"port" => "port"
"username" => "username"
"clientIP" => "clientIP"
"clientRealIP" => "clientRealIP"
"userAgent" => "userAgent"
"referer" => "referer"
"response" => "response"
"subresponse" => "subresponse"
"win32response" => "win32response"
"timetaken" => "timetaken"
"uriQuery__utm_medium" => "uriQuery__utm_medium"
"uriQuery__utm_source" => "uriQuery__utm_source"
"uriQuery__utm_campaign" => "uriQuery__utm_campaign"
"uriQuery__utm_term" => "uriQuery__utm_term"
"uriQuery__utm_content" => "uriQuery__utm_content"
"uriQuery__yclid" => "uriQuery__yclid"
"uriQuery__region" => "uriQuery__region"
}
}
}
pipelines.yml
# This file is where you define your pipelines. You can define multiple.
# For more information on multiple pipelines, see the documentation:
# https://www.elastic.co/guide/en/logstash/current/multiple-pipelines.html
- pipeline.id: log_web__filebeat_clickhouse
path.config: "/etc/logstash/log_web__filebeat_clickhouse.conf"
clickhouse. Armazenamento de registros
Os logs de todos os sistemas são armazenados em uma tabela (veja no início do artigo). Destina-se a armazenar informações sobre as solicitações: todos os parâmetros são semelhantes para diferentes formatos, como logs do IIS, apache e logs do nginx. Para logs de aplicativos, nos quais, por exemplo, erros, mensagens informativas, avisos são registrados, uma tabela separada será fornecida com a estrutura apropriada (atualmente em estágio de design).
Ao projetar uma tabela, é muito importante decidir sobre a chave primária (pela qual os dados serão classificados durante o armazenamento). O grau de compactação de dados e a velocidade da consulta dependem disso. No nosso exemplo, a chave é
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Ou seja, pelo nome do sistema, o nome do componente do sistema e a data do evento. Inicialmente, a data do evento veio primeiro. Depois de movê-lo para o último lugar, as consultas começaram a funcionar duas vezes mais rápido. A alteração da chave primária exigirá a recriação da tabela e o recarregamento dos dados para que o ClickHouse reordene os dados no disco. Esta é uma operação pesada, então é uma boa ideia pensar muito sobre o que deve ser incluído na chave de classificação.
Também deve ser observado que o tipo de dados LowCardinality apareceu em versões relativamente recentes. Ao utilizá-lo, o tamanho dos dados compactados é drasticamente reduzido para aqueles campos que possuem baixa cardinalidade (poucas opções).
A versão 19.6 está atualmente em uso e planejamos tentar atualizar para a versão mais recente. Eles têm recursos maravilhosos como Adaptive Granularity, Skipping indexs e o codec DoubleDelta, por exemplo.
Por padrão, durante a instalação, o nível de criação de log é definido como rastreamento. Os logs são girados e arquivados, mas ao mesmo tempo se expandem para um gigabyte. Se não houver necessidade, você pode definir o nível de aviso e o tamanho do log será drasticamente reduzido. A configuração de registro é definida no arquivo config.xml:
<!-- Possible levels: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger. h#L105 -->
<level>warning</level>
Alguns comandos úteis
Поскольку оригинальные пакеты установки собираются по Debian, то для других версий Linux необходимо использовать пакеты собранные компанией Altinity.
Вот по этой ссылке есть инструкции с ссылками на их репозиторий: https://www.altinity.com/blog/2017/12/18/logstash-with-clickhouse
sudo yum search clickhouse-server
sudo yum install clickhouse-server.noarch
1. проверка статуса
sudo systemctl status clickhouse-server
2. остановка сервера
sudo systemctl stop clickhouse-server
3. запуск сервера
sudo systemctl start clickhouse-server
Запуск для выполнения запросов в многострочном режиме (выполнение после знака ";")
clickhouse-client --multiline
clickhouse-client --multiline --host 127.0.0.1 --password pa55w0rd
clickhouse-client --multiline --host 127.0.0.1 --port 9440 --secure --user default --password pa55w0rd
Плагин кликлауза для логстеш в случае ошибки в одной строке сохраняет всю пачку в файл /tmp/log_web_failed.json
Можно вручную исправить этот файл и попробовать залить его в БД вручную:
clickhouse-client --host 127.0.0.1 --password password --query="INSERT INTO log_web FORMAT JSONEachRow" < /tmp/log_web_failed__fixed.json
sudo mv /etc/logstash/tmp/log_web_failed.json /etc/logstash/tmp/log_web_failed__fixed.json
sudo chown user_dev /etc/logstash/tmp/log_web_failed__fixed.json
sudo clickhouse-client --host 127.0.0.1 --password password --query="INSERT INTO log_web FORMAT JSONEachRow" < /etc/logstash/tmp/log_web_failed__fixed.json
sudo mv /etc/logstash/tmp/log_web_failed__fixed.json /etc/logstash/tmp/log_web_failed__fixed_.json
выход из командной строки
quit;
## Настройка TLS
https://www.altinity.com/blog/2019/3/5/clickhouse-networking-part-2
openssl s_client -connect log.domain.com:9440 < /dev/null
logstash. Roteador de log do FileBeat para a fila do RabbitMQ
Este componente é usado para rotear logs vindos do FileBeat para a fila do RabbitMQ. Há dois pontos aqui:
- Infelizmente, o FileBeat não possui um plug-in de saída para gravar diretamente no RabbitMQ. E essa funcionalidade, a julgar pelo problema em seu github, não está planejada para implementação. Existe um plugin para o Kafka, mas por algum motivo não podemos usá-lo em casa.
- Existem requisitos para coletar logs na DMZ. Com base neles, os logs devem primeiro ser adicionados à fila e, em seguida, o LogStash lê as entradas da fila de fora.
Portanto, é para o caso em que os servidores estão localizados na DMZ que é necessário usar um esquema um pouco complicado. Um exemplo de configuração se parece com isto:
iis_w3c_logs__filebeat_rabbitmq.conf
input {
beats {
port => 5044
type => 'iis'
ssl => true
ssl_certificate_authorities => ["/etc/pki/tls/certs/app/ca.pem", "/etc/pki/tls/certs/app/ca-issuing.pem"]
ssl_certificate => "/etc/pki/tls/certs/app/queue.domain.com.cer"
ssl_key => "/etc/pki/tls/certs/app/queue.domain.com-pkcs8.key"
ssl_verify_mode => "peer"
}
}
output {
#stdout {codec => rubydebug}
rabbitmq {
host => "127.0.0.1"
port => 5672
exchange => "monitor.direct"
exchange_type => "direct"
key => "%{[fields][fld_app_name]}"
user => "q-writer"
password => "password"
ssl => false
}
}
RabbitMQ. fila de mensagens
Este componente é usado para armazenar em buffer as entradas de log na DMZ. A gravação é feita através de um monte de Filebeat → LogStash. A leitura é feita de fora da DMZ via LogStash. Ao operar através do RabboitMQ, são processadas cerca de 4 mil mensagens por segundo.
O roteamento de mensagens é configurado pelo nome do sistema, ou seja, com base nos dados de configuração do FileBeat. Todas as mensagens vão para uma fila. Se, por algum motivo, o serviço de enfileiramento for interrompido, isso não levará à perda de mensagens: o FileBeats receberá erros de conexão e suspenderá temporariamente o envio. E o LogStash que lê da fila também receberá erros de rede e aguardará a restauração da conexão. Nesse caso, os dados, é claro, não serão mais gravados no banco de dados.
As seguintes instruções são usadas para criar e configurar filas:
sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin declare exchange --vhost=/ name=monitor.direct type=direct sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin declare queue --vhost=/ name=web_log durable=true
sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin --vhost="/" declare binding source="monitor.direct" destination_type="queue" destination="web_log" routing_key="site1.domain.ru"
sudo /usr/local/bin/rabbitmqadmin/rabbitmqadmin --vhost="/" declare binding source="monitor.direct" destination_type="queue" destination="web_log" routing_key="site2.domain.ru"
Grafana. Painéis
Este componente é usado para visualizar os dados de monitoramento. Nesse caso, você precisa instalar a fonte de dados ClickHouse para o plug-in Grafana 4.6+. Tivemos que ajustá-lo um pouco para melhorar a eficiência do processamento de filtros SQL no painel.
Por exemplo, usamos variáveis, e se elas não estiverem definidas no campo filtro, então gostaríamos que não gerasse uma condição no WHERE do formulário ( uriStem = » AND uriStem != » ). Neste caso, o ClickHouse irá ler a coluna uriStem. Em geral, tentamos diferentes opções e eventualmente corrigimos o plug-in (a macro $valueIfEmpty) para que, no caso de um valor vazio, ele retorne 1, sem mencionar a coluna em si.
E agora você pode usar esta consulta para o gráfico
$columns(response, count(*) c) from $table where $adhoc
and $valueIfEmpty($fld_app_name, 1, fld_app_name = '$fld_app_name')
and $valueIfEmpty($fld_app_module, 1, fld_app_module = '$fld_app_module') and $valueIfEmpty($fld_server_name, 1, fld_server_name = '$fld_server_name') and $valueIfEmpty($uriStem, 1, uriStem like '%$uriStem%')
and $valueIfEmpty($clientRealIP, 1, clientRealIP = '$clientRealIP')
que traduz para este SQL (observe que os campos uriStem vazios foram convertidos para apenas 1)
SELECT
t,
groupArray((response, c)) AS groupArr
FROM (
SELECT
(intDiv(toUInt32(logdatetime), 60) * 60) * 1000 AS t, response,
count(*) AS c FROM default.log_web
WHERE (logdate >= toDate(1565061982)) AND (logdatetime >= toDateTime(1565061982)) AND 1 AND (fld_app_name = 'site1.domain.ru') AND (fld_app_module = 'web') AND 1 AND 1 AND 1
GROUP BY
t, response
ORDER BY
t ASC,
response ASC
)
GROUP BY t ORDER BY t ASC
Conclusão
O surgimento do banco de dados ClickHouse tornou-se um marco no mercado. Era difícil imaginar que, de forma totalmente gratuita, em um instante estivéssemos munidos de uma ferramenta poderosa e prática para trabalhar com big data. Obviamente, com necessidades crescentes (por exemplo, sharding e replicação para vários servidores), o esquema se tornará mais complicado. Mas nas primeiras impressões, trabalhar com esse banco de dados é muito agradável. Percebe-se que o produto é feito "para as pessoas".
Comparado ao ElasticSearch, estima-se que o custo de armazenamento e processamento de logs seja reduzido de cinco a dez vezes. Em outras palavras, se para a quantidade atual de dados teríamos que configurar um cluster de várias máquinas, ao usar o ClickHouse, uma máquina de baixo consumo é suficiente para nós. Sim, claro, o ElasticSearch também possui mecanismos de compactação de dados em disco e outros recursos que podem reduzir significativamente o consumo de recursos, mas em comparação com o ClickHouse, isso será mais caro.
Sem nenhuma otimização especial de nossa parte, nas configurações padrão, o carregamento de dados e a seleção do banco de dados funcionam em uma velocidade incrível. Ainda não temos muitos dados (cerca de 200 milhões de registros), mas o servidor em si é fraco. Podemos usar essa ferramenta no futuro para outras finalidades não relacionadas ao armazenamento de logs. Por exemplo, para análise de ponta a ponta, no campo da segurança, aprendizado de máquina.
No final, um pouco sobre os prós e contras.
Contras
- Carregando registros em grandes lotes. Por um lado, esse é um recurso, mas você ainda precisa usar componentes adicionais para armazenar registros em buffer. Esta tarefa nem sempre é fácil, mas ainda solucionável. E eu gostaria de simplificar o esquema.
- Algumas funcionalidades exóticas ou novos recursos geralmente são interrompidos em novas versões. Isso causa preocupação, diminuindo o desejo de atualizar para uma nova versão. Por exemplo, o mecanismo de tabela Kafka é um recurso muito útil que permite ler eventos diretamente do Kafka, sem implementar consumidores. Mas, a julgar pelo número de problemas no github, ainda tomamos cuidado para não usar esse mecanismo em produção. No entanto, se você não fizer gestos bruscos para o lado e usar a funcionalidade principal, ele funcionará de forma estável.
Prós
- Não desacelera.
- Limite de entrada baixo.
- Código aberto.
- Livre.
- Escala bem (sharding/replicação pronta para uso)
- Incluído no registro de software russo recomendado pelo Ministério das Comunicações.
- A presença de suporte oficial do Yandex.
Fonte: habr.com