Alekszej Lizunov, az MKB Információs Technológiai Igazgatóság Távszolgáltatási Csatornái Kompetencia Központ vezetője
Az ELK verem (ElasticSearch, Logstash, Kibana) alternatívájaként kutatunk a ClickHouse adatbázis naplók adattárolójaként való használatával kapcsolatban.
Ebben a cikkben a ClickHouse adatbázis használatának tapasztalatairól és a kísérleti üzemeltetés előzetes eredményeiről szeretnénk beszélni. Azonnal meg kell jegyezni, hogy az eredmények lenyűgözőek voltak.
Ezután részletesebben leírjuk, hogyan van beállítva a rendszerünk, és milyen összetevőkből áll. De most erről az adatbázisról, mint egészről szeretnék egy kicsit beszélni, és hogy miért érdemes erre odafigyelni. A ClickHouse adatbázis a Yandex nagy teljesítményű elemző oszlopos adatbázisa. A Yandex szolgáltatásokban használatos, kezdetben a Yandex.Metrica fő adattárolója. Nyílt forráskódú rendszer, ingyenes. Fejlesztői szempontból mindig is kíváncsi voltam, hogyan valósították meg, mert fantasztikusan nagy adatok vannak. Maga a Metrica felhasználói felülete pedig nagyon rugalmas és gyors. Az adatbázis első megismerésekor az a benyomásom, hogy „Na végre! Az embereknek készült! A telepítési folyamattól kezdve a kérések elküldésével.
Ennek az adatbázisnak nagyon alacsony a belépési küszöbe. Még egy átlagosan képzett fejlesztő is néhány perc alatt telepítheti ezt az adatbázist, és elkezdheti használni. Minden egyértelműen működik. Még azok is, akik még nem ismerik a Linuxot, gyorsan tudják kezelni a telepítést és elvégezni a legegyszerűbb műveleteket. Ha korábban a Big Data, Hadoop, Google BigTable, HDFS szavakkal egy hétköznapi fejlesztőnek olyan ötlete támadt, hogy néhány terabájtról, petabájtról van szó, hogy néhány emberfeletti ember foglalkozik ezeknek a rendszereknek a beállításával és fejlesztésével, akkor a ClickHouse megjelenésével adatbázis, kaptunk egy egyszerű, érthető eszközt, amellyel korábban elérhetetlen feladatsort oldhat meg. Csak egy meglehetősen átlagos gépet és öt percet vesz igénybe a telepítés. Vagyis kaptunk egy olyan adatbázist, mint például a MySql, de csak több milliárd rekord tárolására! Egy bizonyos szuper-archiváló SQL nyelvvel. Mintha az emberek kezébe adták volna az idegenek fegyvereit.
Naplórendszerünkről
Az információgyűjtéshez szabványos formátumú webalkalmazások IIS naplófájljait használjuk (jelenleg az alkalmazásnaplók elemzését is végezzük, de a kísérleti szakaszban a fő cél az IIS naplók gyűjtése).
Különféle okok miatt nem tudtuk teljesen elhagyni az ELK stacket, továbbra is a LogStash és Filebeat komponenseket használjuk, amelyek jól beváltak, és meglehetősen megbízhatóan és kiszámíthatóan működnek.
Az általános naplózási séma az alábbi ábrán látható:
A ClickHouse adatbázisba való adatírás egyik jellemzője a rekordok ritkán (másodpercenként egyszeri) beillesztése nagy kötegekben. Úgy tűnik, ez a „legproblémásabb” rész, amivel találkozik, amikor először tapasztalja a ClickHouse adatbázissal való munkát: a séma kissé bonyolultabbá válik.
Itt sokat segített a LogStash bővítménye, amely közvetlenül a ClickHouse-ba illeszti be az adatokat. Ez az összetevő ugyanazon a kiszolgálón van telepítve, mint maga az adatbázis. Általánosságban elmondható tehát, hogy nem ajánlatos megtenni, hanem gyakorlati szempontból, hogy ne jöjjön létre külön szerver, miközben ugyanazon a szerveren van telepítve. Nem észleltünk meghibásodást vagy erőforrás-ütközést az adatbázisban. Ezenkívül meg kell jegyezni, hogy a beépülő modulnak van egy újrapróbálkozási mechanizmusa hibák esetén. Hiba esetén a beépülő modul olyan adatköteget ír a lemezre, amelyet nem lehetett beilleszteni (a fájlformátum kényelmes: szerkesztés után egyszerűen beillesztheti a javított köteget a clickhouse-client segítségével).
A sémában használt szoftverek teljes listája a táblázatban látható:
A használt szoftverek listája
Név
Leírás
Terjesztési link
nginx
Fordított proxy a portok hozzáférésének korlátozásához és az engedélyezés megszervezéséhez
Jelenleg nem használják a rendszerben
FileBeat
Fájlnaplók átvitele.
logstash
Rönkgyűjtő.
A FileBeat naplóinak gyűjtésére, valamint a RabbitMQ sorból való naplók gyűjtésére szolgál (a DMZ-ben lévő szerverekhez).
Logstash-output-clickhouse
Loagstash bővítmény a naplók kötegelt átviteléhez a ClickHouse adatbázisba
/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
Kattintson a Ház gombra
Rönktárolás
Jegyzet. 2018 augusztusától a Yandex adattárában megjelentek az RHEL „normál” rpm buildjei, így megpróbálhatja használni őket. A telepítés idején az Altinity által készített csomagokat használtuk.
grafana
Napló vizualizáció. Irányítópultok beállítása
Redhat & Centos (64 bites) - legújabb verzió
ClickHouse adatforrás a Grafana 4.6+-hoz
Grafana bővítmény ClickHouse adatforrással
logstash
Az útválasztó naplózása a FileBeatből a RabbitMQ sorba.
Jegyzet. Sajnos a FileBeatnek nincs közvetlen kimenete a RabbitMQ-hoz, ezért szükség van egy köztes hivatkozásra Logstash formájában
Nyúl MQ
üzenetsor. Ez a napló puffer a DMZ-ben
Erlang Runtime (szükséges a RabbitMQ-hoz)
Erlang futási idő. Szükséges a RabbitMQ működéséhez
A szerver konfigurációja a ClickHouse adatbázissal az alábbi táblázatban látható:
Név
Érték
Megjegyzés
Configuration
HDD: 40GB
RAM: 8GB
Processzor: Core 2 2GHz
Figyelni kell a ClickHouse adatbázis kezelésével kapcsolatos tippekre (
Általános rendszerszoftver
OS: Red Hat Enterprise Linux Server (Maipo)
JRE (Java 8)
Amint látja, ez egy közönséges munkaállomás.
A naplók tárolására szolgáló táblázat felépítése a következő:
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;
Alapértelmezett particionálást (havi) és indexrészletezést használunk. Az összes mező gyakorlatilag megfelel az IIS naplóbejegyzéseinek a http kérések naplózására. Külön megjegyezzük, hogy külön mezők vannak az utm-címkék tárolására (a lekérdezési karakterlánc mezőből a táblázatba történő beszúrás szakaszában kerülnek elemzésre).
Emellett több rendszermező is hozzáadásra került a táblához a rendszerekről, összetevőkről és szerverekről szóló információk tárolására. A mezők leírását lásd az alábbi táblázatban. Egy táblázatban több rendszer naplóit tároljuk.
Név
Leírás
Példa
fld_app_name
Alkalmazás/rendszer neve
Érvényes értékek:
- site1.domain.com Külső webhely 1
- site2.domain.com Külső webhely 2
- belső-hely1.domain.local 1. belső webhely
site1.domain.com
fld_app_module
Rendszer modul
Érvényes értékek:
- web - Weboldal
- svc – Webhelyszolgáltatás
- intgr – Integrációs webszolgáltatás
- bo - Adminisztrátor (BackOffice)
háló
fld_webhely_neve
A webhely neve az IIS-ben
Egy kiszolgálón több rendszer, vagy akár egy rendszermodul több példánya is telepíthető
web fő
fld_szerver_neve
Szerver név
web1.domain.com
fld_log_file_name
A szerveren lévő naplófájl elérési útja
C:inetpublogsLogFiles
W3SVC1u_ex190711.log
Ez lehetővé teszi, hogy hatékonyan készítsen grafikonokat a Grafanában. Például megtekintheti egy adott rendszer frontendjétől érkező kéréseket. Ez hasonló a Yandex.Metrica webhelyszámlálójához.
Íme néhány statisztikai adat az adatbázis két hónapos használatáról.
A rekordok száma rendszerek és összetevőik szerinti bontásban
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 lemezen lévő adatmennyiség
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.
Az adattömörítés mértéke oszlopokban
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.
A használt alkatrészek leírása
FileBeat. Fájlnaplók átvitele
Ez az összetevő nyomon követi a lemezen lévő naplófájlok változásait, és továbbítja az információkat a LogStash-nak. Telepítve minden olyan szerveren, ahol naplófájlok vannak írva (általában IIS). Tail módban működik (azaz csak a hozzáadott rekordokat viszi át a fájlba). De külön-külön is beállítható teljes fájlok átvitelére. Ez akkor hasznos, ha előző hónapok adatait kell letöltenie. Csak helyezze a naplófájlt egy mappába, és a teljes egészében elolvassa.
A szolgáltatás leállításakor az adatok már nem kerülnek tovább a tárolóba.
Egy példa konfiguráció így néz ki:
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. Rönkgyűjtő
Ezt az összetevőt úgy tervezték, hogy fogadja a naplóbejegyzéseket a FileBeattől (vagy a RabbitMQ soron keresztül), elemezze és beilleszti a kötegeket a ClickHouse adatbázisba.
A ClickHouse-ba való beillesztéshez a Logstash-output-clickhouse bővítményt kell használni. A Logstash beépülő modul rendelkezik egy kérési újrapróbálkozási mechanizmussal, de rendszeres leállítás esetén jobb magát a szolgáltatást leállítani. Leállításkor az üzenetek felhalmozódnak a RabbitMQ sorban, így ha a leállás hosszú ideig tart, akkor jobb, ha leállítja a Filebeats-et a szervereken. Egy olyan sémában, ahol a RabbitMQ-t nem használják (a helyi hálózaton a Filebeat közvetlenül küld naplókat a Logstash-nak), a Filebeats meglehetősen elfogadhatóan és biztonságosan működik, így számukra a kimenet elérhetetlensége következmények nélkül múlik el.
Egy példa konfiguráció így néz ki:
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"
}
}
}
csővezetékek.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. Rönktárolás
Az összes rendszer naplói egy táblázatban vannak tárolva (lásd a cikk elején). Célja a kérésekkel kapcsolatos információk tárolása: minden paraméter hasonló a különböző formátumokhoz, például az IIS-naplókhoz, az apache- és az nginx-naplókhoz. Az alkalmazási naplókhoz, amelyekben például hibák, információs üzenetek, figyelmeztetések vannak rögzítve, külön táblázatot biztosítunk a megfelelő szerkezettel (jelenleg tervezési szakaszban).
A táblázat megtervezésekor nagyon fontos eldönteni, hogy melyik elsődleges kulcs (mely alapján lesznek rendezve az adatok a tárolás során). Ettől függ az adattömörítés mértéke és a lekérdezési sebesség. Példánkban a kulcs az
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Vagyis a rendszer nevével, a rendszerkomponens nevével és az esemény dátumával. Kezdetben az esemény dátuma volt az első. Miután áthelyezte az utolsó helyre, a lekérdezések körülbelül kétszer gyorsabban kezdtek működni. Az elsődleges kulcs megváltoztatásához újra létre kell hozni a táblát, és újra kell tölteni az adatokat, hogy a ClickHouse újrarendezze az adatokat a lemezen. Ez egy nehéz művelet, ezért érdemes sokat gondolkozni azon, hogy mi kerüljön bele a rendezési kulcsba.
Azt is meg kell jegyezni, hogy a LowCardinality adattípus viszonylag friss verziókban jelent meg. Használatakor a tömörített adatok mérete drasztikusan lecsökken azoknál a mezőknél, amelyeknek alacsony a számossága (kevés lehetőség).
Jelenleg a 19.6-os verzió használatban van, és azt tervezzük, hogy megpróbáljuk frissíteni a legújabb verzióra. Olyan csodálatos tulajdonságokkal rendelkeznek, mint például az Adaptive Granularity, a Skipping indexek és a DoubleDelta kodek.
Alapértelmezés szerint a telepítés során a naplózási szint nyomkövetésre van állítva. A naplókat elforgatják és archiválják, ugyanakkor akár egy gigabájtra bővülnek. Ha nincs rá szükség, akkor beállíthatja a figyelmeztetési szintet, ekkor a rönk mérete drasztikusan csökken. A naplózási beállítás a config.xml fájlban van beállítva:
<!-- Possible levels: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger. h#L105 -->
<level>warning</level>
Néhány hasznos parancs
Поскольку оригинальные пакеты установки собираются по 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. Az útválasztó naplózása a FileBeatből a RabbitMQ sorba
Ez az összetevő a FileBeatből érkező naplók RabbitMQ-sorba irányítására szolgál. Itt két pont van:
- Sajnos a FileBeat nem rendelkezik kimeneti beépülő modullal, amely közvetlenül írhatna a RabbitMQ-ba. És az ilyen funkcionalitást a githubon lévő probléma alapján nem tervezik implementálni. Van egy plugin a Kafkához, de valamiért nem tudjuk otthon használni.
- A DMZ-ben követelmények vonatkoznak a naplók gyűjtésére. Ezek alapján először a naplókat kell hozzáadni a sorhoz, majd a LogStash kívülről beolvassa a sor bejegyzéseit.
Ezért arra az esetre, ha a szerverek a DMZ-ben találhatók, egy ilyen kissé bonyolult sémát kell alkalmazni. Egy példa konfiguráció így néz ki:
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. üzenetsor
Ez az összetevő a naplóbejegyzések pufferelésére szolgál a DMZ-ben. A rögzítés egy csomó Filebeat → LogStash segítségével történik. Az olvasás a DMZ-n kívülről történik a LogStash segítségével. Ha a RabboitMQ-n keresztül működik, másodpercenként körülbelül 4 ezer üzenet kerül feldolgozásra.
Az üzenetek továbbítása a rendszernév szerint van konfigurálva, azaz a FileBeat konfigurációs adatai alapján. Minden üzenet egy sorba kerül. Ha valamilyen oknál fogva a sorbaállítási szolgáltatás leáll, akkor ez nem vezet az üzenetek elvesztéséhez: a FileBeats csatlakozási hibákat kap, és ideiglenesen felfüggeszti a küldést. A sorból olvasó LogStash pedig hálózati hibákat is kap, és várja a kapcsolat helyreállítását. Ebben az esetben az adatok természetesen már nem kerülnek be az adatbázisba.
A sorok létrehozásához és konfigurálásához a következő utasításokat kell használni:
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. Irányítópultok
Ez az összetevő a megfigyelési adatok megjelenítésére szolgál. Ebben az esetben telepítenie kell a ClickHouse adatforrást a Grafana 4.6+ bővítményhez. Kicsit módosítanunk kellett, hogy javítsuk az SQL-szűrők feldolgozásának hatékonyságát az irányítópulton.
Például változókat használunk, és ha ezek nincsenek beállítva a szűrőmezőben, akkor szeretnénk, ha nem generálna feltételt az űrlap WHERE részében ( uriStem = » AND uriStem != » ). Ebben az esetben a ClickHouse beolvassa az uriStem oszlopot. Általában különböző lehetőségeket próbáltunk ki, és végül kijavítottuk a beépülő modult (a $valueIfEmpty makrót), hogy üres érték esetén 1-et adjon vissza anélkül, hogy magát az oszlopot említené.
És most már használhatja ezt a lekérdezést a grafikonhoz
$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')
ami lefordítja ezt az SQL-t (megjegyzendő, hogy az üres uriStem mezők csak 1-re lettek konvertálva)
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
Következtetés
A ClickHouse adatbázis megjelenése mérföldkővé vált a piacon. Nehéz volt elképzelni, hogy teljesen ingyenesen egy pillanat alatt felvérteztünk egy hatékony és praktikus eszközt a big data kezeléséhez. Természetesen a növekvő igények miatt (például felosztás és replikáció több szerverre) a séma bonyolultabbá válik. De első benyomásra nagyon kellemes ezzel az adatbázissal dolgozni. Látható, hogy a termék "emberek számára" készült.
Az ElasticSearch-hez képest a naplók tárolásának és feldolgozásának költsége a becslések szerint öt-tízszeresére csökken. Vagyis ha a jelenlegi adatmennyiséghez több gépből álló klasztert kellene felállítanunk, akkor ClickHouse használatakor elég nekünk egy kis fogyasztású gép. Igen, természetesen az ElasticSearch is rendelkezik lemezen található adattömörítési mechanizmusokkal és egyéb funkciókkal, amelyek jelentősen csökkenthetik az erőforrás-felhasználást, de a ClickHouse-hoz képest ez drágább lesz.
Részünkről különösebb optimalizálás nélkül, alapbeállítások mellett az adatok betöltése és az adatbázisból való kiválasztás elképesztő sebességgel működik. Még nincs sok adatunk (kb. 200 millió rekord), de maga a szerver gyenge. Ezt az eszközt a jövőben más, nem a naplók tárolásával kapcsolatos célokra is használhatjuk. Például a végpontok közötti elemzéshez, a biztonság, a gépi tanulás területén.
A végén egy kicsit az előnyeiről és hátrányairól.
Hátrányok
- Rekordok betöltése nagy tételekben. Ez egyrészt egy szolgáltatás, de a rekordok puffereléséhez továbbra is további összetevőket kell használni. Ez a feladat nem mindig könnyű, de mégis megoldható. És szeretném leegyszerűsíteni a sémát.
- Egyes egzotikus funkciók vagy új funkciók gyakran megszakadnak az új verziókban. Ez aggodalomra ad okot, csökkentve az új verzióra való frissítés iránti vágyat. Például a Kafka táblázatmotor egy nagyon hasznos funkció, amely lehetővé teszi a Kafka események közvetlen olvasását anélkül, hogy fogyasztókat kellene alkalmazni. De a githubon megjelenő problémák számából ítélve továbbra is ügyelünk arra, hogy ne használjuk ezt a motort a gyártás során. Ha azonban nem tesz hirtelen gesztusokat oldalra, és használja a fő funkciót, akkor stabilan működik.
Érvek
- Nem lassít.
- Alacsony belépési küszöb.
- Nyílt forráskód.
- Ingyenes.
- Jól skálázható (szilánkolás/replikáció a dobozból)
- Szerepel a Hírközlési Minisztérium által ajánlott orosz szoftverek nyilvántartásában.
- A Yandex hivatalos támogatásának jelenléte.
Forrás: will.com