Aleksej Lizunov, chef för avdelningen för kompetenscentrum för fjÀrrservicekanaler vid IT-direktionen för MKB

Som ett alternativ till ELK-stacken (ElasticSearch, Logstash, Kibana) genomför vi forskningsarbete om anvÀndningen av ClickHouse-databasen som datalager för loggar.
I denna artikel vill vi berÀtta om vÄra erfarenheter av att anvÀnda ClickHouse-databasen och om de preliminÀra resultaten efter den inledande driften. Det Àr vÀrt att notera frÄn början att resultaten har varit imponerande.

Nedan kommer vi att beskriva mer detaljerat hur vĂ„rt system Ă€r konfigurerat och av vilka komponenter det bestĂ„r. Men vi skulle först vilja berĂ€tta lite om denna databas i allmĂ€nhet och varför den förtjĂ€nar att uppmĂ€rksammas. ClickHouse-databasen Ă€r en högpresterande kolumnorienterad databas frĂ„n Yandex. Den anvĂ€nds i Yandex-tjĂ€nster, och den var frĂ„n början huvudlagret för data för Yandex.Metrica. Systemet Ă€r open-source och gratis. Ur ett utvecklarperspektiv har jag alltid varit nyfiken pĂ„ hur de har implementerat detta, eftersom de hanterar fantastiskt stora data. Och anvĂ€ndargrĂ€nssnittet för Metrica Ă€r mycket flexibelt och snabbt. Vid första bekantskap med denna databas Ă€r intrycket: "Ăntligen! Gjord för mĂ€nniskor!" FrĂ„n installationsprocessen till att skicka förfrĂ„gningar.
Denna databas har en mycket lĂ„g intrĂ€deströskel. Ăven en medelstor utvecklare kan installera denna databas pĂ„ nĂ„gra minuter och börja anvĂ€nda den. Allt fungerar smidigt. Ăven personer som Ă€r dĂ„ligt bekanta med Linux kan snabbt hantera installationen och utföra grundlĂ€ggande operationer. Tidigare, nĂ€r ordet Big Data nĂ€mndes, hade vanliga utvecklare ofta en uppfattning om att det handlade om terabyte, petabyte, att det var övermĂ€n som sysslade med instĂ€llningar och utveckling för dessa system. Men med framkomsten av ClickHouse-databasen har vi fĂ„tt ett enkelt, begripligt verktyg som gör det möjligt att lösa tidigare oöverkomliga uppgifter. Det rĂ€cker med en tĂ€mligen medelmĂ„ttig maskin och fem minuter för installation. SĂ„ vi har fĂ„tt en databas som MySql, fast för att lagra miljarder poster! En slags superkompressor med SQL-sprĂ„k. Det Ă€r som om mĂ€nniskor har fĂ„tt utomjordisk bevĂ€pning.
Om vÄrt loggsamlingssystem
För insamling av information anvÀnds loggfiler frÄn IIS webbapplikationer i standardformat (vi arbetar Àven med att parsa loggar frÄn applikationer, men vÄrt huvudsyfte under pilotdriften Àr insamling av IIS-loggar).
Vi har inte kunnat helt överge ELK-stacken av olika skÀl, och vi fortsÀtter att anvÀnda komponenter som LogStash och Filebeat, vilka har visat sig pÄlitliga och fungerar stabilt.
Den övergripande loggning schemat presenteras i bilden nedan:

En specifik egenskap för att skriva data i ClickHouse-databasen Àr den sÀllsynta (en gÄng per sekund) insÀttningen av poster i stora batchar. Detta Àr nÀmligen den mest «problematiska» delen som man stöter pÄ vid första anvÀndning av ClickHouse: schemat blir nÄgot mer komplicerat.
HÀr hjÀlpte en plugin för LogStash, som direkt sÀtter in data i ClickHouse. Denna komponent installeras pÄ samma server som databasen. Generellt sett rekommenderas inte detta, men praktiskt sett, för att undvika att skapa separata servrar, Àr det acceptabelt sÄ lÀnge den Àr installerad pÄ samma server. Vi har inte observerat nÄgra krascher eller resurskonflikter med databasen. Dessutom Àr det vÀrt att nÀmna att plugin har en retry-mekanism vid fel. Vid fel skriver plugin en batch data som inte kunde sÀttas in pÄ disk (filformatet Àr bekvÀmt: efter redigering kan man enkelt ÄterinsÀtta den korrigerade batchen med hjÀlp av clickhouse-client).
Den fullstÀndiga listan över programvara som anvÀnds i schemat presenteras i tabellen:
Lista över anvÀnda programvaror
Namn
Beskrivning
LĂ€nk till distributionen
NGINX
Reverse-proxy för att begrÀnsa Ätkomst via portar och organisera autentisering
AnvÀnds för nÀrvarande inte i schemat
FileBeat
Ăverföring av loggfiler.
(distribution för Windows 64bit).
LogStash
Loggsamlare.
AnvÀnds för insamling av loggar frÄn FileBeat samt för att samla loggar frÄn RabbitMQ-kön (för servrar som finns i DMZ).
Logstash-output-clickhouse
Logstash-plugin för att överföra loggar till ClickHouse-databasen i batchar
/usr/share/logstash/bin/logstash-plugin install logstash-output-clickhouse
/usr/share/logstash/bin/logstash-plugin install logstash-filter-prune
/usr/share/logstash/bin/logstash-plugin install logstash-filter-multiline
ClickHouse
Logglagring
AnmÀrkning. FrÄn och med augusti 2018 finns det "normala" rpm-byggnader i Yandex-repositoriet för RHEL, sÄ de kan provas. Vid installationstillfÀllet anvÀnde vi paket byggda av Altinity.
Grafana
Visualisering av loggar. InstÀllning av instrumentpaneler
Redhat & Centos (64 Bit) â senaste versionen
ClickHouse-datakÀlla för Grafana 4.6+
Plugin för Grafana med ClickHouse datakÀlla
LogStash
Loggrouter frÄn FileBeat till RabbitMQ-kön.
Observera. TyvÀrr har FileBeat ingen direkt output till RabbitMQ, sÄ en mellanhand i form av Logstash krÀvs.
RabbitMQ
Meddelandekö. Detta Àr en buffert för loggposter i DMZ.
Erlang Runtime (NödvÀndigt för RabbitMQ)
Erlang-miljö. KrÀvs för att köra RabbitMQ.
Serverkonfiguration med ClickHouse-databas redovisas i följande tabell:
Namn
VĂ€rde
AnmÀrkning
Konfiguration
HDD: 40GB
RAM: 8GB
Processor: Core 2 2Ghz
Det Àr viktigt att följa rÄden för anvÀndning av ClickHouse-databasen ()
Systemprogramvara
OS: Red Hat Enterprise Linux Server (Maipo)
JRE (Java 8)
Â
Som synes Àr det en vanlig arbetsstation.
Tabellstrukturen för att lagra loggar ser ut pÄ följande sÀtt:
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;Vi anvÀnder standardvÀrden för partitionering (per mÄnad) och indexgranularitet. Alla fÀlt stÀmmer praktiskt taget överens med loggposterna frÄn IIS för registrering av http-förfrÄgningar. SÀrskilt mÀrkta Àr separata fÀlt för lagring av utm-taggar (de parsas vid insÀttning i tabellen frÄn förfrÄgningsstrÀngen).
I tabellen har Àven flera systemfÀlt lagts till för att lagra information om system, komponenter, servrar. Beskrivning av dessa fÀlt finns nedan i tabellen. I en tabell lagrar vi loggar frÄn flera system.
Namn
Beskrivning
Exempel
fld_app_name
Namn pÄ applikationen/systemet
TillÄtna vÀrden:
- site1.domain.com Extern webbplats 1
- site2.domain.com Extern webbplats 2
- internal-site1.domain.local Intern webbplats 1
site1.domain.com
fld_app_module
Systemmodul
TillÄtna vÀrden:
- web â Webbplats
- svc â Webbservice för webbplatsen
- intgr â Integrations-webbservice
- bo â Admin (BackOffice)
web
fld_website_name
Namn pÄ webbplatsen i IIS
PĂ„ en server kan flera system vara installerade, eller till och med flera instanser av en modul.
web-main
fld_server_name
Servernamn
web1.domain.com
fld_log_file_name
SökvÀg till loggfilen pÄ servern
C:inetpublogsLogFiles
W3SVC1u_ex190711.log
Det hÀr gör det möjligt att effektivt bygga diagram i Grafana. Till exempel, att se förfrÄgningar frÄn frontend av ett visst system. Det liknar en webbplatsrÀknare i Yandex.Metrika.
HÀr Àr lite statistik om databasanvÀndning under tvÄ mÄnader.
Antal poster uppdelade efter system och deras komponenter
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.)DataomfÄng pÄ disk
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.Kompressionen av data i kolumner
VĂLJ
namn,
formatReadableSize(data_uncompressed_bytes) SOM okomprimerad,
formatReadableSize(data_compressed_bytes) SOM komprimerad,
data_uncompressed_bytes / data_compressed_bytes SOM komprimeringsförhÄllande
FRĂ
N system.columns
DĂR tabell = 'log_web'
âânamnâââââââââââââââââââââŹâokomprimeradââŹâkomprimeradââŹâââââkomprimeringsförhĂ„llandeââ
â logdatum â 401.53 MiB â 1.80 MiB â 223.16665968777315 â
â logdatumtid â 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 â
â metod â 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 â
â anvĂ€ndarnamn â 318.08 MiB â 26.93 MiB â 11.812513794583598 â
â klientIP â 2.35 GiB â 82.59 MiB â 29.132328640073343 â
â klientRealIP â 2.49 GiB â 465.05 MiB â 5.478382297052563 â
â anvĂ€ndarAgent â 18.34 GiB â 764.08 MiB â 24.57905114484208 â
â referens â 14.71 GiB â 1.37 GiB â 10.736792723669906 â
â svar â 803.06 MiB â 83.81 MiB â 9.582334090987247 â
â delat svar â 399.87 MiB â 1.83 MiB â 218.4831068635027 â
â win32svar â 407.86 MiB â 7.41 MiB â 55.050315514606815 â
â tidsĂ„tgĂ„ng â 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 rader i uppsÀttning. Förfluten tid: 0.005 sek.Beskrivning av anvÀnda komponenter
FileBeat. Ăverföring av filloggar
Denna komponent övervakar Àndringar i loggfiler pÄ disken och skickar information till LogStash. Installationen görs pÄ alla servrar dÀr loggfiler skrives (vanligtvis IIS). Arbetar i tail-lÀge (dvs skickar endast tillagda poster i filen). Men kan Àven konfigureras för att överföra hela filer. Detta Àr praktiskt nÀr du behöver ladda upp data frÄn föregÄende mÄnader. SÀtt bara loggfilen i mappen sÄ lÀser den automatiskt hela filen.
NÀr tjÀnsten stÀngs av slutar data att överföras vidare till lagringsutrymmet.
Ett exempel pÄ konfigurationen ser ut som följer:
filebeat.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"
#================================ Processorer =====================================
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~LogStash. Logsamlaren
Den hÀr komponenten Àr avsedd att ta emot loggar frÄn FileBeat (antingen via RabbitMQ-kö), parsning och batchinmatning i ClickHouse-databasen.
För insÀttning i ClickHouse anvÀnds Logstash-output-clickhouse-plugin. Logstash-plugin har en mekanism för att Äterförsöka förfrÄgningar, men vid normal avstÀngning Àr det bÀttre att stÀnga sjÀlva tjÀnsten. Vid avstÀngning kommer meddelanden att samlas i RabbitMQ-kö, sÄ om avstÀngningen Àr lÄngvarig Àr det bÀttre att stÀnga av Filebeat pÄ servrarna. I schemat dÀr RabbitMQ inte anvÀnds (i det lokala nÀtverket skickar Filebeat loggar direkt till Logstash) fungerar Filebeat fullt acceptabelt och sÀkert, sÄ för dem gÄr avsaknaden av output utan konsekvenser.
Ett exempel pÄ konfigurationen ser ut som följer:
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. Logg förvaring
Loggar frÄn alla system sparas i en och samma tabell (se i början av artikeln). Den Àr avsedd för lagring av förfrÄgningsinformation: alla parametrar Àr liknande för olika format, till exempel IIS-loggar, apache-loggar och nginx-loggar. För applikationsloggar, dÀr till exempel fel, informationsmeddelanden och varningar registreras, kommer det att finnas en separat tabell med motsvarande struktur (just nu under utveckling).
Vid utformningen av tabellen Àr det mycket viktigt att bestÀmma primÀrnyckeln (som kommer att anvÀndas för att sortera data vid lagring). Detta pÄverkar graden av datakomprimering och hastigheten pÄ förfrÄgningar. I vÄrt exempel Àr nyckeln
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Det vill sÀga baserat pÄ systemnamnet, komponentnamnet för systemet och hÀndelsedatumet. Ursprungligen var hÀndelsedatumet först. Efter att ha flyttat det till sista platsen blev förfrÄgningarna ungefÀr dubbelt sÄ snabba. Att Àndra primÀrnyckeln krÀver att tabellen Äterskapas och att data laddas om sÄ att ClickHouse kan omordna data pÄ disken. Detta Àr en tung operation, sÄ det Àr bÀst att noga övervÀga vad som ska ingÄ i sorteringsnyckeln i god tid.
Det Àr ocksÄ vÀrt att notera att i de senaste versionerna har datatypen LowCardinality introducerats. Med dess anvÀndning minskar storleken pÄ de komprimerade data drastiskt för de fÀlt som har lÄg kardinalitet (fÄ alternativ).
För nÀrvarande anvÀnds version 19.6, och vi planerar att försöka uppgradera till den senaste versionen. I dem har det dykt upp fantastiska funktioner som Adaptiv granularitet, Skipping indices och DoubleDelta-kodek, till exempel.
Som standard Àr loggnivÄn trace instÀlld vid installation i konfigurationen. Loggar roteras och arkiveras, men expanderar samtidigt till en gigabyte. Om det inte Àr nödvÀndigt kan loggnivÄn sÀttas till warning, vilket kraftigt minskar loggens storlek. LogginstÀllningarna anges i filen config.xml:
warningNÄgra anvÀndbara kommandon
Eftersom de ursprungliga installationspaketen Àr samlade frÄn Debian, mÄste paket som samlas av Altinity anvÀndas för andra versioner av Linux.
HÀr Àr instruktioner med lÀnkar till deras repository: https://www.altinity.com/blog/2017/12/18/logstash-with-clickhouse
sudo yum search clickhouse-server
sudo yum install clickhouse-server.noarch
1. kontrollera status
sudo systemctl status clickhouse-server
2. stoppa servern
sudo systemctl stop clickhouse-server
3. starta servern
sudo systemctl start clickhouse-server
Starta för att utföra frÄgor i flermoduslÀge (körs efter tecknet ";")
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
Logstash ClickHouse-plugin sparar hela batchen i filen /tmp/log_web_failed.json i hÀndelse av ett fel pÄ en rad.
Denna fil kan manuellt korrigeras och laddas upp till databasen manuellt:
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
avsluta kommandoraden
quit;
## TLS Konfiguration
https://www.altinity.com/blog/2019/3/5/clickhouse-networking-part-2
openssl s_client -connect log.domain.com:9440 < /dev/nullLogStash. Log-router frÄn FileBeat till RabbitMQ-kö
Denna komponent anvÀnds för att vidarebefordra loggar som kommer frÄn FileBeat till RabbitMQ-kön. HÀr finns tvÄ frÄgor:
- TyvÀrr har FileBeat ingen output-plugin för att skriva direkt till RabbitMQ. Den funktionen, enligt issue pÄ deras GitHub, planeras inte att implementeras. Det finns en plugin för Kafka, men av vissa skÀl kan vi inte anvÀnda den hos oss.
- Det finns krav för insamling av loggar i DMZ. UtifrÄn dessa krav mÄste loggar först placeras i en kö, och sedan lÀser LogStash externt frÄn kön.
DÀrför mÄste en nÄgot mer komplicerad schema anvÀndas nÀr servrarna Àr placerade i DMZ. Ett exempel pÄ konfiguration ser ut pÄ följande sÀtt:
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. Meddelandekö
Denna komponent anvĂ€nds för att buffra loggposter i DMZ. Inspelningen görs genom kombinationen Filebeat â LogStash. LĂ€sning sker utanför DMZ via LogStash. Vid drift via RabbitMQ bearbetas cirka 4 000 meddelanden per sekund.
Meddelandena routas baserat pÄ systemets namn, det vill sÀga baserat pÄ konfigurationsdata frÄn FileBeat. Alla meddelanden hamnar i en kö. Om meddelandeköservicen av nÄgon anledning stoppas, leder det inte till meddelandeförlust: FileBeat kommer att fÄ anslutningsfel och tillfÀlligt pausa sÀndningen. LogStash, som lÀser frÄn kön, kommer ocksÄ att fÄ nÀtverksfel och vÀnta pÄ att anslutningen ska ÄterstÀllas. Under tiden kommer data naturligtvis att sluta skrivas till databasen.
Följande instruktioner anvÀnds för att skapa och konfigurera köer:
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. Instrumentpaneler
Denna komponent anvÀnds för att visualisera övervakningsdata. Det Àr nödvÀndigt att installera pluginen ClickHouse datasource for Grafana 4.6+. Vi var tvungna att justera den nÄgot för att öka effektiviteten i hanteringen av SQL-filter pÄ instrumentpanelen.
Till exempel anvÀnder vi variabler och om de inte Àr angivna i filtreringsfÀltet, skulle vi gÀrna se att det inte genererade ett villkor i WHERE av typen ( uriStem = » AND uriStem != » ). I sÄ fall kommer ClickHouse att lÀsa kolumnen uriStem. Generellt prövade vi olika alternativ och slutligen justerade vi pluginen (makroet $valueIfEmpty), sÄ att den vid tomt vÀrde returnerade 1, utan att nÀmna sjÀlva kolumnen.
Och nu kan vi anvÀnda en sÄdan frÄga för diagrammet
$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')som som omvandlas till följande SQL (notera att tomma fÀlt uriStem har omvandlats till bara 1)
VĂLj
t,
groupArray((response, c)) AS groupArr
FRĂ
N (
VĂLj
(intDiv(toUInt32(logdatetime), 60) * 60) * 1000 AS t, response,
count(*) AS c FRĂ
N default.log_web
VAR (logdate >= toDate(1565061982)) OCH (logdatetime >= toDateTime(1565061982)) OCH 1 OCH (fld_app_name = 'site1.domain.ru') OCH (fld_app_module = 'web') OCH 1 OCH 1 OCH 1
GRUPPERA EFTER
t, response
ORDNA EFTER
t ASC,
response ASC
)
GRUPPERA EFTER t ORDNA EFTER t ASCSlutsats
Införandet av ClickHouse-databasen var en betydande hÀndelse pÄ marknaden. Det var svÄrt att förestÀlla sig att vi plötsligt fick ett kraftfullt och praktiskt verktyg för arbete med stora datamÀngder helt gratis. SjÀlvklart kommer schemat att bli mer komplext nÀr kraven ökar (som sharding och replikering pÄ flera servrar). Men vid första intrycket Àr det mycket trevligt att arbeta med denna databas. Det Àr tydligt att produkten Àr gjord "för mÀnniskor".
JÀmfört med ElasticSearch berÀknas kostnaderna för lagring och bearbetning av loggar minska mellan fem och tio gÄnger. Med andra ord, om vi behövde konfigurera ett kluster av flera maskiner för den aktuella datavolymen, skulle vi med ClickHouse rÀcka med en svag maskin. Ja, det finns Àven mekanismer för datakomprimering pÄ disken i ElasticSearch och andra funktioner som kraftigt kan minska resursförbrukningen, men jÀmfört med ClickHouse krÀver det högre kostnader.
Utan nÄgra speciella optimeringar frÄn vÄr sida, med standardinstÀllningar, fungerar dataladdning och frÄgor mot databasen med fantastisk hastighet. Vi har för tillfÀllet inte mycket data (ungefÀr 200 miljoner poster), men sjÀlva servern Àr svag. Detta verktyg kan vi i framtiden Àven anvÀnda för andra ÀndamÄl som Àr orelaterade till logglagring. Till exempel för end-to-end-analys, inom sÀkerhet, maskininlÀrning.
Slutligen, lite om för- och nackdelar.
Nackdelar
- Laddning av poster i stora partier. à ena sidan Àr detta en funktion, men det krÀvs ÀndÄ ytterligare komponenter för buffring av poster. Denna uppgift Àr inte alltid enkel, men den Àr ÀndÄ lösbar. Och vi skulle vilja förenkla schemat.
- Vissa exotiska funktioner eller nya funktioner bryter ofta i nya versioner. Detta vÀcker oro och minskar viljan att uppgradera till den nya versionen. Till exempel, Kafka-tabellmotorn Àr en mycket anvÀndbar funktion som lÄter dig lÀsa hÀndelser direkt frÄn Kafka, utan att implementera konsumenter. Men med tanke pÄ antalet problem pÄ GitHub, Àr vi osÀkra pÄ att anvÀnda denna motor i produktion. Men om man undviker hastiga förÀndringar och anvÀnder den grundlÀggande funktionaliteten, fungerar den stabilt.
Fördelar
- Ingen försening.
- LÄg tröskel för intrÀde.
- Ăppen kĂ€llkod.
- Gratis.
- Skalar bra (sharding/replicering "ur lÄdan")
- Inkluderad i registret över ryska mjukvaror rekommenderade av MinComSvyaz.
- Officiellt stöd frÄn Yandex.
KĂ€lla: habr.com
