Aleksey Lizunov, chef för kompetenscentret för fjÀrrtjÀnstkanaler vid direktoratet för informationsteknologi vid MKB
Som ett alternativ till ELK-stacken (ElasticSearch, Logstash, Kibana) forskar vi om att anvÀnda ClickHouse-databasen som ett datalager för loggar.
I den hÀr artikeln vill vi prata om vÄr erfarenhet av att anvÀnda ClickHouse-databasen och de preliminÀra resultaten av pilotoperationen. Det bör genast noteras att resultaten var imponerande.
DĂ€refter kommer vi att beskriva mer i detalj hur vĂ„rt system Ă€r konfigurerat och vilka komponenter det bestĂ„r av. Men nu skulle jag vilja prata lite om denna databas som helhet, och varför det Ă€r vĂ€rt att uppmĂ€rksamma. ClickHouse-databasen Ă€r en högpresterande analytisk kolumndatabas frĂ„n Yandex. Det anvĂ€nds i Yandex-tjĂ€nster, initialt Ă€r det den huvudsakliga datalagringen för Yandex.Metrica. Ăppen kĂ€llkodssystem, gratis. Ur en utvecklares synvinkel har jag alltid undrat hur de implementerade det, för det finns fantastiskt stor data. Och Metricas anvĂ€ndargrĂ€nssnitt i sig Ă€r vĂ€ldigt flexibelt och snabbt. Vid den första bekantskapen med denna databas Ă€r intrycket: âJaha, Ă€ntligen! Gjord för folket! Börjar frĂ„n installationsprocessen och slutar med att skicka förfrĂ„gningar.
Denna databas har en mycket lĂ„g ingĂ„ngströskel. Ăven en genomsnittlig skicklig utvecklare kan installera denna databas pĂ„ nĂ„gra minuter och börja anvĂ€nda den. Allt fungerar tydligt. Ăven personer som Ă€r nya i Linux kan snabbt hantera installationen och göra de enklaste operationerna. Om tidigare, med orden Big Data, Hadoop, Google BigTable, HDFS, en vanlig utvecklare hade idĂ©er om att det handlade om nĂ„gra terabyte, petabyte, att vissa övermĂ€nniskor Ă€r involverade i instĂ€llningar och utveckling för dessa system, dĂ„ med tillkomsten av ClickHouse databas, fick vi ett enkelt, begripligt verktyg med vilket du kan lösa ett tidigare ouppnĂ„eligt antal uppgifter. Det tar bara en ganska genomsnittlig maskin och fem minuter att installera. Det vill sĂ€ga, vi fick en sĂ„dan databas som till exempel MySql, men bara för att lagra miljarder poster! En viss superarkiverare med SQL-sprĂ„ket. Det Ă€r som att folk fick utomjordingars vapen.
Om vÄrt loggningssystem
För att samla in information anvÀnds IIS-loggfiler av webbapplikationer i standardformat (vi analyserar ocksÄ för nÀrvarande applikationsloggar, men huvudmÄlet i pilotstadiet Àr att samla in IIS-loggar).
Vi kunde inte helt överge ELK-stacken av olika anledningar, och vi fortsÀtter att anvÀnda LogStash- och Filebeat-komponenterna, som har visat sig vÀl och fungerar ganska tillförlitligt och förutsÀgbart.
Det allmÀnna loggningsschemat visas i figuren nedan:
En funktion för att skriva data till ClickHouse-databasen Àr sÀllsynta (en gÄng per sekund) infogning av poster i stora partier. Detta Àr tydligen den mest "problematiska" delen som du stöter pÄ nÀr du först upplever att arbeta med ClickHouse-databasen: schemat blir lite mer komplicerat.
Plugin för LogStash, som direkt infogar data i ClickHouse, hjÀlpte mycket hÀr. Denna komponent distribueras pÄ samma server som sjÀlva databasen. SÄ generellt sett rekommenderas det inte att göra det, utan ur en praktisk synvinkel, för att inte skapa separata servrar medan den Àr utplacerad pÄ samma server. Vi har inte observerat nÄgra fel eller resurskonflikter med databasen. Dessutom bör det noteras att plugin har en mekanism för att försöka igen vid fel. Och i hÀndelse av fel skriver plugin till disken en sats med data som inte kunde infogas (filformatet Àr bekvÀmt: efter redigering kan du enkelt infoga den korrigerade batchen med clickhouse-klient).
En komplett lista över programvara som anvÀnds i schemat presenteras i tabellen:
Lista över anvÀnda programvara
namn
beskrivning
LĂ€nk till distribution
nginx
OmvÀnd proxy för att begrÀnsa Ätkomst av portar och organisera auktorisering
AnvÀnds för nÀrvarande inte i schemat
FileBeat
Ăverföring av filloggar.
LogStash
Loggsamlare.
AnvÀnds för att samla in loggar frÄn FileBeat, samt för att samla in loggar frÄn RabbitMQ-kön (för servrar som finns i DMZ.)
Logstash-output-clickhouse
Loagstash-plugin för att överföra loggar till ClickHouse-databasen i omgÄngar
/usr/share/logstash/bin/logstash-plugin installera logstash-output-clickhouse
/usr/share/logstash/bin/logstash-plugin installera logstash-filter-prune
/usr/share/logstash/bin/logstash-plugin installera logstash-filter-multiline
klickhus
Logglagring
Notera. FrÄn och med augusti 2018 dök "normala" rpm-byggen för RHEL upp i Yandex-förvaret, sÄ du kan försöka anvÀnda dem. Vid tidpunkten för installationen anvÀnde vi paket byggda av Altinity.
grafana
Loggvisualisering. Konfigurera instrumentpaneler
Redhat & Centos(64 Bit) - senaste versionen
ClickHouse-datakÀlla för Grafana 4.6+
Plugin för Grafana med ClickHouse datakÀlla
LogStash
Logga router frÄn FileBeat till RabbitMQ-kön.
Notera. TyvÀrr skickar FileBeat inte ut direkt till RabbitMQ, sÄ en mellanlÀnk i form av Logstash krÀvs
RabbitMQ
Meddelandekö. Detta Àr en buffert av loggposter i DMZ
Erlang Runtime (krÀvs för RabbitMQ)
Erlang körtid. KrÀvs för att RabbitMQ ska fungera
Serverkonfigurationen med ClickHouse-databasen presenteras i följande tabell:
namn
VĂ€rde
Notera
konfiguration
HDD: 40GB
RAM: 8GB
Processor: Core 2 2Ghz
Du bör vara uppmÀrksam pÄ tipsen för att anvÀnda ClickHouse-databasen (
AllmÀn systemprogramvara
OS: Red Hat Enterprise Linux Server (Maipo)
JRE (Java 8)
Som du kan se Àr detta en vanlig arbetsstation.
Strukturen för tabellen för att lagra loggar Àr som följer:
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 standardpartitionering (efter mÄnad) och indexgranularitet. Alla fÀlt motsvarar praktiskt taget IIS-loggposter för att logga http-förfrÄgningar. Separat noterar vi att det finns separata fÀlt för att lagra utm-taggar (de tolkas vid insÀttningsstadiet i tabellen frÄn frÄgestrÀngsfÀltet).
Dessutom har flera systemfÀlt lagts till i tabellen för att lagra information om system, komponenter, servrar. För en beskrivning av dessa fÀlt, se tabellen nedan. I en tabell lagrar vi loggar för flera system.
namn
beskrivning
Exempel
fld_app_name
Applikations-/systemnamn
Giltiga 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
Giltiga vÀrden:
- webb - Webbplats
- svc - WebbplatstjÀnst
- intgr - Integration Web Service
- bo - Admin (BackOffice)
webb
fld_website_name
Webbplatsnamn i IIS
Flera system kan distribueras pÄ en server, eller till och med flera instanser av en systemmodul
webbhuvud
fld_server_name
Server namn
web1.domain.com
fld_log_file_name
SökvÀg till loggfilen pÄ servern
C:inetpublogsLogFiles
W3SVC1u_ex190711.log
Detta gör att du effektivt kan bygga grafer i Grafana. Visa till exempel förfrÄgningar frÄn frontend av ett visst system. Detta liknar webbplatsrÀknaren i Yandex.Metrica.
HÀr Àr lite statistik om anvÀndningen av databasen 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.)
MÀngden data pÄ disken
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.
Grad av datakomprimering i kolumner
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.
Beskrivning av anvÀnda komponenter
FileBeat. Ăverföra filloggar
Den hÀr komponenten spÄrar Àndringar av loggfiler pÄ disken och skickar informationen till LogStash. Installerad pÄ alla servrar dÀr loggfiler skrivs (vanligtvis IIS). Fungerar i svanslÀge (dvs. överför endast de tillagda posterna till filen). Men separat kan den konfigureras för att överföra hela filer. Detta Àr anvÀndbart nÀr du behöver ladda ner data frÄn tidigare mÄnader. LÀgg bara loggfilen i en mapp sÄ kommer den att lÀsa den i sin helhet.
NÀr tjÀnsten stoppas överförs inte data lÀngre vidare till lagringen.
Ett exempel pÄ en konfiguration ser ut sÄ hÀr:
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"
#================================ Processors =====================================
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
logstash. Loggsamlare
Den hÀr komponenten Àr designad för att ta emot loggposter frÄn FileBeat (eller genom RabbitMQ-kön), analysera och infoga batcher i ClickHouse-databasen.
För att infogas i ClickHouse anvÀnds plugin-programmet Logstash-output-clickhouse. Logstash-pluginet har en begÀran om försök, men med en vanlig avstÀngning Àr det bÀttre att stoppa sjÀlva tjÀnsten. NÀr det stoppas kommer meddelanden att samlas i RabbitMQ-kön, sÄ om stoppet Àr under en lÄng tid Àr det bÀttre att stoppa Filebeats pÄ servrarna. I ett schema dÀr RabbitMQ inte anvÀnds (pÄ det lokala nÀtverket skickar Filebeat loggar direkt till Logstash), fungerar Filebeats ganska acceptabelt och sÀkert, sÄ för dem gÄr otillgÀngligheten av utdata utan konsekvenser.
Ett exempel pÄ en konfiguration ser ut sÄ hÀr:
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"
klickhus. Logglagring
Loggar för alla system sparas i en tabell (se i början av artikeln). Den Àr utformad för att lagra information om förfrÄgningar: alla parametrar Àr lika för olika format, till exempel IIS-loggar, apache- och nginx-loggar. För applikationsloggar dÀr till exempel fel, informationsmeddelanden, varningar registreras, kommer en separat tabell att tillhandahÄllas med lÀmplig struktur (för nÀrvarande pÄ designstadiet).
NÀr du designar en tabell Àr det mycket viktigt att bestÀmma primÀrnyckeln (med vilken data kommer att sorteras under lagring). Graden av datakomprimering och frÄgehastighet beror pÄ detta. I vÄrt exempel Àr nyckeln
BESTĂLL EFTER (fld_app_name, fld_app_module, logdatetime)
Det vill sÀga genom namnet pÄ systemet, namnet pÄ systemkomponenten och datumet för hÀndelsen. Till en början kom datumet för evenemanget först. Efter att ha flyttat den till den sista platsen började frÄgorna fungera ungefÀr dubbelt sÄ snabbt. Att Àndra primÀrnyckeln krÀver att tabellen Äterskapas och data laddas upp igen sÄ att ClickHouse sorterar om data pÄ disken. Detta Àr en svÄr operation, sÄ det Àr lÀmpligt att i förvÀg tÀnka noga pÄ vad som ska ingÄ i sorteringsnyckeln.
Det bör ocksÄ noteras att datatypen LowCardinality har förekommit i relativt nya versioner. NÀr du anvÀnder den reduceras storleken pÄ komprimerad data drastiskt för de fÀlt som har lÄg kardinalitet (fÄ alternativ).
Vi anvÀnder för nÀrvarande version 19.6 och vi planerar att försöka uppdatera till den senaste versionen. De har sÄ underbara funktioner som Adaptive Granularity, Skipping-index och DoubleDelta-codec, till exempel.
Som standard Àr loggningsnivÄn instÀlld pÄ spÄrning under installationen. Loggarna roteras och arkiveras, men de expanderar samtidigt upp till en gigabyte. Om det inte finns nÄgot behov kan du stÀlla in varningsnivÄn, dÄ minskas storleken pÄ stocken drastiskt. LoggningsinstÀllningen stÀlls in i filen config.xml:
<!-- Possible levels: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger. h#L105 -->
<level>warning</level>
NÄgra anvÀndbara kommandon
ĐĐŸŃĐșĐŸĐ»ŃĐșŃ ĐŸŃĐžĐłĐžĐœĐ°Đ»ŃĐœŃĐ” паĐșĐ”ŃŃ ŃŃŃĐ°ĐœĐŸĐČĐșĐž ŃĐŸĐ±ĐžŃĐ°ŃŃŃŃ ĐżĐŸ 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. Logga router frÄn FileBeat till RabbitMQ-kö
Denna komponent anvÀnds för att dirigera loggar som kommer frÄn FileBeat till RabbitMQ-kön. Det finns tvÄ punkter hÀr:
- TyvÀrr har FileBeat inget utdataplugin för att skriva direkt till RabbitMQ. Och sÄdan funktionalitet, att döma av problemet pÄ deras github, Àr inte planerad för implementering. Det finns ett plugin för Kafka, men av nÄgon anledning kan vi inte anvÀnda det hemma.
- Det finns krav för att samla in loggar i DMZ. Baserat pÄ dem mÄste loggarna först lÀggas till i kön och sedan lÀser LogStash in posterna frÄn kön utifrÄn.
DÀrför, speciellt för servrar som finns i en DMZ, Àr det nödvÀndigt att anvÀnda ett sÄ lite komplicerat schema. Ett exempel pÄ en konfiguration ser ut sÄ hÀr:
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ö
Den hĂ€r komponenten anvĂ€nds för att buffra loggposter i DMZ. Inspelning görs genom ett gĂ€ng Filebeat â LogStash. AvlĂ€sning görs utanför DMZ via LogStash. NĂ€r man anvĂ€nder RabboitMQ behandlas cirka 4 tusen meddelanden per sekund.
Meddelandedirigering konfigureras med systemnamn, dvs baserat pÄ FileBeat-konfigurationsdata. Alla meddelanden gÄr till en kö. Om kötjÀnsten av nÄgon anledning stoppas, kommer detta inte att leda till förlust av meddelanden: FileBeats kommer att ta emot anslutningsfel och tillfÀlligt avbryta sÀndningen. Och LogStash som lÀser frÄn kön kommer ocksÄ att ta emot nÀtverksfel och vÀnta pÄ att anslutningen ska ÄterstÀllas. I det hÀr fallet kommer data naturligtvis inte lÀngre att 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. InstrumentbrÀdor
Denna komponent anvÀnds för att visualisera övervakningsdata. I det hÀr fallet mÄste du installera ClickHouse-datakÀllan för Grafana 4.6+ plugin. Vi var tvungna att finjustera det lite för att förbÀttra effektiviteten för bearbetning av SQL-filter pÄ instrumentpanelen.
Till exempel anvÀnder vi variabler, och om de inte Àr instÀllda i filterfÀltet, sÄ vill vi att det inte genererar ett villkor i formulÀrets WHERE ( uriStem = » AND uriStem != » ). I det hÀr fallet kommer ClickHouse att lÀsa kolumnen uriStem. I allmÀnhet provade vi olika alternativ och korrigerade sÄ smÄningom pluginet (makrot $valueIfEmpty) sÄ att det i fallet med ett tomt vÀrde returnerar 1, utan att nÀmna sjÀlva kolumnen.
Och nu kan du anvÀnda den hÀr frÄgan för grafen
$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 översÀtts till denna SQL (observera att de tomma uriStem-fÀlten har konverterats till bara 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
Slutsats
Utseendet pÄ ClickHouse-databasen har blivit en milstolpe pÄ marknaden. Det var svÄrt att förestÀlla sig att vi, helt gratis, pÄ ett ögonblick var bevÀpnade med ett kraftfullt och praktiskt verktyg för att arbeta med big data. Naturligtvis, med ökande behov (till exempel skÀrning och replikering till flera servrar), kommer systemet att bli mer komplicerat. Men vid första intryck Àr det mycket trevligt att arbeta med den hÀr databasen. Det kan ses att produkten Àr gjord "för mÀnniskor".
JÀmfört med ElasticSearch berÀknas kostnaden för lagring och bearbetning av loggar minska med fem till tio gÄnger. Med andra ord, om vi för den aktuella datamÀngden skulle behöva sÀtta upp ett kluster med flera maskiner, dÄ nÀr vi anvÀnder ClickHouse rÀcker det med en lÄgeffektsmaskin för oss. Ja, sjÀlvklart har ElasticSearch Àven datakomprimeringsmekanismer pÄ disk och andra funktioner som avsevÀrt kan minska resursförbrukningen, men jÀmfört med ClickHouse blir detta dyrare.
Utan nÄgra speciella optimeringar frÄn vÄr sida, med standardinstÀllningar, fungerar laddning av data och hÀmtning frÄn databasen med otrolig hastighet. Vi har inte mycket data Ànnu (cirka 200 miljoner poster), men sjÀlva servern Àr svag. Vi kan komma att anvÀnda det hÀr verktyget i framtiden för andra ÀndamÄl som inte Àr relaterade till lagring av loggar. Till exempel för end-to-end-analys, inom omrÄdet sÀkerhet, maskininlÀrning.
I slutet lite om för- och nackdelar.
Nackdelar
- Laddar poster i stora partier. à ena sidan Àr detta en funktion, men du mÄste fortfarande anvÀnda ytterligare komponenter för att buffra poster. Denna uppgift Àr inte alltid lÀtt, men ÀndÄ lösbar. Och jag skulle vilja förenkla schemat.
- Vissa exotiska funktioner eller nya funktioner gÄr ofta sönder i nya versioner. Detta skapar oro, vilket minskar lusten att uppgradera till en ny version. Till exempel Àr Kafka-bordmotorn en mycket anvÀndbar funktion som lÄter dig lÀsa hÀndelser frÄn Kafka direkt, utan att implementera konsumenter. Men att döma av antalet Issues pÄ github, Àr vi fortfarande noga med att inte anvÀnda denna motor i produktionen. Men om du inte gör plötsliga gester Ät sidan och anvÀnder huvudfunktionaliteten sÄ fungerar det stabilt.
Fördelar
- Saknar inte farten.
- LÄg instegströskel.
- Ăppen kĂ€lla.
- Fri.
- Skalar bra (skÀrning/replikering ur lÄdan)
- IngÄr i registret över rysk programvara som rekommenderas av kommunikationsministeriet.
- NÀrvaron av officiellt stöd frÄn Yandex.
KĂ€lla: will.com