Aleksei Lizunov, MKB:n tietotekniikan osaston etäpalvelukanavien osaamiskeskuksen johtaja
Vaihtoehtona ELK-pinolle (ElasticSearch, Logstash, Kibana) tutkimme ClickHouse-tietokannan käyttöä lokien tietovarastona.
Tässä artikkelissa haluamme kertoa kokemuksistamme ClickHouse-tietokannan käytöstä ja pilottitoiminnan alustavista tuloksista. On heti huomattava, että tulokset olivat vaikuttavia.
Seuraavaksi kuvailemme yksityiskohtaisemmin, kuinka järjestelmämme on konfiguroitu ja mistä komponenteista se koostuu. Mutta nyt haluaisin puhua hieman tästä tietokannasta kokonaisuutena ja miksi siihen kannattaa kiinnittää huomiota. ClickHouse-tietokanta on Yandexin tehokas analyyttinen saraketietokanta. Sitä käytetään Yandex-palveluissa, alun perin se on Yandex.Metrican tärkein tietojen tallennuspaikka. Avoimen lähdekoodin järjestelmä, ilmainen. Kehittäjän näkökulmasta olen aina ihmetellyt, kuinka he sen toteuttavat, koska dataa on fantastisen paljon. Ja Metrican käyttöliittymä itsessään on erittäin joustava ja nopea. Ensimmäisellä tutustumisella tähän tietokantaan, vaikutelma on: "No, vihdoin! Tehty ihmisiä varten! Alkaen asennusprosessista ja päättyen pyyntöjen lähettämiseen.
Tällä tietokannalla on erittäin alhainen pääsykynnys. Jopa keskimäärin taitava kehittäjä voi asentaa tämän tietokannan muutamassa minuutissa ja aloittaa sen käytön. Kaikki toimii selkeästi. Jopa ihmiset, jotka ovat uusia Linuxin käyttäjiä, voivat hoitaa asennuksen nopeasti ja tehdä yksinkertaisimmatkin toiminnot. Jos aiemmin sanoilla Big Data, Hadoop, Google BigTable, HDFS, tavallisella kehittäjällä oli ajatuksia, että kyse oli joistakin teratavuista, petatavuista, että jotkut yli-ihmiset ovat tekemisissä näiden järjestelmien asetuksissa ja kehittämisessä, niin ClickHousen tultua tietokanta, saimme yksinkertaisen, ymmärrettävän työkalun, jolla voit ratkaista aiemmin saavuttamattomia tehtäviä. Asennus kestää vain yhden melko keskimääräisen koneen ja viisi minuuttia. Eli meillä on sellainen tietokanta kuin esimerkiksi MySql, mutta vain miljardien tietueiden tallentamiseen! Tietty superarkistaattori SQL-kielellä. Se on kuin ihmisille annettaisiin muukalaisten aseet.
Tietoja lokijärjestelmästämme
Tietojen keräämiseen käytetään standardimuotoisten web-sovellusten IIS-lokitiedostoja (parsiamme myös sovelluslokeja, mutta pilottivaiheen päätavoitteena on kerätä IIS-lokeja).
Eri syistä emme päässeet kokonaan luopumaan ELK-pinosta, vaan käytämme edelleen LogStash- ja Filebeat-komponentteja, jotka ovat osoittautuneet hyvin ja toimivat varsin luotettavasti ja ennustettavasti.
Yleinen kirjauskaavio on esitetty alla olevassa kuvassa:
Datan kirjoittamisen ominaisuus ClickHouse-tietokantaan on harvinainen (kerran sekunnissa) tietueiden lisääminen suuriin eriin. Tämä on ilmeisesti "ongelmallisin" osa, jonka kohtaat, kun koet ensimmäisen kerran työskennellessäsi ClickHouse-tietokannan kanssa: järjestelmästä tulee hieman monimutkaisempi.
LogStashin lisäosa, joka lisää tiedot suoraan ClickHouseen, auttoi tässä paljon. Tämä komponentti on otettu käyttöön samassa palvelimessa kuin itse tietokanta. Yleisesti ottaen sitä ei siis suositella, vaan käytännön näkökulmasta, jotta ei muodostu erillisiä palvelimia, kun se otetaan käyttöön samalla palvelimella. Emme havainneet vikoja tai resurssiristiriitoja tietokannan kanssa. Lisäksi on huomattava, että laajennuksessa on uudelleenyritysmekanismi virheiden varalta. Ja jos ilmenee virheitä, laajennus kirjoittaa levylle joukon tietoja, joita ei voitu lisätä (tiedostomuoto on kätevä: muokkaamisen jälkeen voit helposti lisätä korjatun erän clickhouse-client-sovelluksella).
Täydellinen luettelo järjestelmässä käytetyistä ohjelmistoista on esitetty taulukossa:
Luettelo käytetyistä ohjelmistoista
Nimi
Kuvaus
Linkki jakeluun
nginx
Käänteinen välityspalvelin rajoittaa porttien käyttöä ja järjestää valtuutuksen
Ei tällä hetkellä käytössä järjestelmässä
FileBeat
Tiedostolokien siirto.
logstash
Hirsien keräilijä.
Käytetään lokien keräämiseen FileBeatista sekä lokien keräämiseen RabbitMQ-jonosta (palvelimille, jotka ovat DMZ:ssä.)
Logstash-output-clickhouse
Loagstash-laajennus lokien siirtämiseen ClickHouse-tietokantaan erissä
/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
Napsauta taloa
Tukkivarasto
Huomautus. Elokuusta 2018 alkaen RHEL:n "normaalit" rpm-koontiversiot ilmestyivät Yandex-tietovarastoon, joten voit yrittää käyttää niitä. Asennushetkellä käytimme Altinityn valmistamia paketteja.
grafana
Lokin visualisointi. Kojetaulujen määrittäminen
Redhat & Centos (64 Bit) - uusin versio
ClickHouse-tietolähde Grafana 4.6+:lle
Grafana-laajennus ClickHouse-tietolähteellä
logstash
Kirjaa reititin FileBeatista RabbitMQ-jonoon.
Huomautus. Valitettavasti FileBeat ei tulosta suoraan RabbitMQ:lle, joten välilinkki Logstashin muodossa tarvitaan
RabbitMQ
viestijono. Tämä on lokipuskuri DMZ:ssä
Erlang Runtime (pakollinen RabbitMQ:lle)
Erlang-ajoaika. Vaaditaan, jotta RabbitMQ toimii
Palvelimen kokoonpano ClickHouse-tietokannan kanssa on esitetty seuraavassa taulukossa:
Nimi
Arvo
Huomata
kokoonpano
Kiintolevy: 40GB
RAM: 8GB
Prosessori: Core 2 2GHz
On syytä kiinnittää huomiota ClickHouse-tietokannan käyttövinkkeihin (
Yleinen järjestelmäohjelmisto
Käyttöjärjestelmä: Red Hat Enterprise Linux Server (Maipo)
JRE (Java 8)
Kuten näet, tämä on tavallinen työasema.
Lokkien varastointitaulukon rakenne on seuraava:
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;
Käytämme oletusosiointia (kuukausittain) ja indeksin tarkkuutta. Kaikki kentät vastaavat käytännössä IIS-lokimerkintöjä http-pyyntöjen kirjaamiseen. Huomaamme erikseen, että utm-tunnisteiden tallentamiseen on erilliset kentät (ne jäsennetään siinä vaiheessa, kun ne lisätään taulukkoon kyselymerkkijonokentästä).
Lisäksi taulukkoon on lisätty useita järjestelmäkenttiä tietojen tallentamiseksi järjestelmistä, komponenteista ja palvelimista. Katso alla olevasta taulukosta näiden kenttien kuvaus. Yhteen taulukkoon tallennamme useiden järjestelmien lokit.
Nimi
Kuvaus
Esimerkki
fld_app_name
Sovelluksen/järjestelmän nimi
Kelvolliset arvot:
- site1.domain.com Ulkoinen sivusto 1
- site2.domain.com Ulkoinen sivusto 2
- internal-site1.domain.local Sisäinen sivusto 1
site1.domain.com
fld_app_module
Järjestelmämoduuli
Kelvolliset arvot:
- web - Verkkosivusto
- svc - Web-sivustopalvelu
- intgr - Integration Web Service
- bo - Järjestelmänvalvoja (BackOffice)
verkko
fld_sivuston_nimi
Sivuston nimi IIS:ssä
Yhdelle palvelimelle voidaan ottaa käyttöön useita järjestelmiä tai jopa useita yhden järjestelmämoduulin esiintymiä
web pää
fld_palvelimen_nimi
Palvelimen nimi
web1.domain.com
fld_loki_tiedoston_nimi
Polku palvelimella olevaan lokitiedostoon
C:inetpublogsLogFiles
W3SVC1u_ex190711.log
Tämän avulla voit rakentaa kaavioita tehokkaasti Grafanassa. Voit esimerkiksi tarkastella pyyntöjä tietyn järjestelmän käyttöliittymästä. Tämä on samanlainen kuin Yandex.Metrican sivustolaskuri.
Tässä muutamia tilastoja tietokannan käytöstä kahden kuukauden ajalta.
Tietueiden lukumäärä järjestelmien ja niiden komponenttien mukaan
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.)
Levyllä olevan tiedon määrä
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.
Tietojen pakkausaste sarakkeissa
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.
Kuvaus käytetyistä komponenteista
FileBeat. Tiedostolokien siirtäminen
Tämä komponentti seuraa muutoksia levyllä oleviin lokitiedostoihin ja välittää tiedot LogStashiin. Asennettu kaikille palvelimille, joille lokitiedostoja kirjoitetaan (yleensä IIS). Toimii häntätilassa (eli siirtää vain lisätyt tietueet tiedostoon). Mutta erikseen se voidaan määrittää siirtämään kokonaisia tiedostoja. Tästä on hyötyä, kun sinun on ladattava tietoja edellisiltä kuukausilta. Laita lokitiedosto kansioon ja se lukee sen kokonaisuudessaan.
Kun palvelu lopetetaan, tietoja ei enää siirretä edelleen tallennustilaan.
Esimerkkikokoonpano näyttää tältä:
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. Hirsikerääjä
Tämä komponentti on suunniteltu vastaanottamaan lokimerkintöjä FileBeatista (tai RabbitMQ-jonon kautta), jäsentämään ja lisäämään eriä ClickHouse-tietokantaan.
ClickHouseen lisäämiseen käytetään Logstash-output-clickhouse-laajennusta. Logstash-laajennuksessa on pyyntöjen uudelleenyritysmekanismi, mutta tavallisella sammutuksella on parempi lopettaa itse palvelu. Pysäytettynä viestit kerääntyvät RabbitMQ-jonoon, joten jos pysähdys kestää pitkään, on parempi pysäyttää Filebeats palvelimilla. Kaavassa, jossa RabbitMQ:ta ei käytetä (paikallisessa verkossa Filebeat lähettää lokit suoraan Logstashille), Filebeats toimii varsin hyväksyttävästi ja turvallisesti, joten heille lähdön puuttuminen kulkee ilman seurauksia.
Esimerkkikokoonpano näyttää tältä:
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. Tukkivarasto
Kaikkien järjestelmien lokit tallennetaan yhteen taulukkoon (katso artikkelin alussa). Se on tarkoitettu tallentamaan tietoja pyynnöistä: kaikki parametrit ovat samanlaisia eri muodoissa, kuten IIS-lokeissa, apache- ja nginx-lokeissa. Sovelluslokeille, joihin tallennetaan esimerkiksi virheitä, tietoviestejä, varoituksia, järjestetään erillinen taulukko sopivalla rakenteella (tällä hetkellä suunnitteluvaiheessa).
Taulukkoa suunniteltaessa on erittäin tärkeää päättää ensisijainen avain (jonka mukaan tiedot lajitellaan tallennuksen aikana). Tietojen pakkausaste ja kyselyn nopeus riippuvat tästä. Esimerkissämme avain on
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Eli järjestelmän nimen, järjestelmäkomponentin nimen ja tapahtuman päivämäärän mukaan. Aluksi tapahtuman päivämäärä oli ensin. Kun se oli siirretty viimeiseen paikkaan, kyselyt alkoivat toimia noin kaksi kertaa nopeammin. Ensisijaisen avaimen muuttaminen edellyttää taulukon luomista uudelleen ja tietojen lataamista uudelleen, jotta ClickHouse lajittelee tiedot uudelleen levyllä. Tämä on raskas operaatio, joten on hyvä ajatus miettiä paljon, mitä lajitteluavaimeen pitäisi sisällyttää.
On myös huomattava, että LowCardinality-tietotyyppi on esiintynyt suhteellisen uusissa versioissa. Sitä käytettäessä pakattujen tietojen koko pienenee huomattavasti niille kentille, joilla on alhainen kardinaliteetti (vähän vaihtoehtoja).
Versio 19.6 on tällä hetkellä käytössä ja aiomme yrittää päivittää uusimpaan versioon. Niissä on sellaisia upeita ominaisuuksia kuin esimerkiksi Adaptive Granularity, Skipping-indeksit ja DoubleDelta-koodekki.
Asennuksen aikana lokikirjaustasoksi asetetaan oletusarvoisesti jäljitys. Lokeja pyöritetään ja arkistoidaan, mutta samalla ne laajenevat jopa gigatavuun. Jos tarvetta ei ole, voit asettaa varoitustason, jolloin puun koko pienenee huomattavasti. Kirjausasetus on määritetty config.xml-tiedostossa:
<!-- Possible levels: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger. h#L105 -->
<level>warning</level>
Muutamia hyödyllisiä komentoja
Поскольку оригинальные пакеты установки собираются по 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. Kirjaa reititin FileBeatista RabbitMQ-jonoon
Tätä komponenttia käytetään FileBeatista tulevien lokien reitittämiseen RabbitMQ-jonoon. Tässä on kaksi kohtaa:
- Valitettavasti FileBeatilla ei ole ulostulolaajennusta, joka kirjoittaa suoraan RabbitMQ:hen. Ja tällaista toimivuutta heidän githubin ongelmasta päätellen ei ole suunniteltu toteutettavaksi. Kafkalle on lisäosa, mutta emme jostain syystä voi käyttää sitä kotona.
- DMZ:ssä on lokien keräämistä koskevia vaatimuksia. Niiden perusteella lokit on ensin lisättävä jonoon ja sitten LogStash lukee merkinnät jonosta ulkopuolelta.
Siksi siinä tapauksessa, että palvelimet sijaitsevat DMZ:ssä, on käytettävä tällaista hieman monimutkaista järjestelmää. Esimerkkikokoonpano näyttää tältä:
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. viestijono
Tätä komponenttia käytetään puskuroimaan lokimerkinnät DMZ:ssä. Nauhoitus tehdään Filebeat → LogStashin avulla. Lukeminen tapahtuu DMZ:n ulkopuolelta LogStashin kautta. RabboitMQ:n kautta toimittaessa käsitellään noin 4 tuhatta viestiä sekunnissa.
Viestien reititys määritetään järjestelmän nimen mukaan eli FileBeat-määritystietojen perusteella. Kaikki viestit menevät yhteen jonoon. Jos jonotuspalvelu jostain syystä pysäytetään, tämä ei johda viestien katoamiseen: FileBeats vastaanottaa yhteysvirheet ja keskeyttää lähettämisen väliaikaisesti. Ja jonosta lukeva LogStash saa myös verkkovirheitä ja odottaa yhteyden palautumista. Tässä tapauksessa tietoja ei tietenkään enää kirjoiteta tietokantaan.
Seuraavia ohjeita käytetään jonojen luomiseen ja määrittämiseen:
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. Kojelaudat
Tätä komponenttia käytetään monitorointitietojen visualisointiin. Tässä tapauksessa sinun on asennettava ClickHouse-tietolähde Grafana 4.6+ -laajennukselle. Meidän piti säätää sitä hieman parantaaksemme SQL-suodattimien käsittelyn tehokkuutta kojelaudalla.
Käytämme esimerkiksi muuttujia, ja jos niitä ei ole asetettu suodatinkenttään, niin haluamme, ettei se luo ehtoa lomakkeen WHERE-kenttään ( uriStem = » AND uriStem != » ). Tässä tapauksessa ClickHouse lukee uriStem-sarakkeen. Yleensä kokeilimme eri vaihtoehtoja ja lopulta korjasimme laajennuksen ($valueIfEmpty-makro) niin, että tyhjän arvon tapauksessa se palauttaa arvon 1 mainitsematta itse saraketta.
Ja nyt voit käyttää tätä kyselyä kaaviossa
$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')
joka tarkoittaa tätä SQL:ää (huomaa, että tyhjät uriStem-kentät on muunnettu vain 1:ksi)
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
Johtopäätös
ClickHouse-tietokannan ilmestymisestä on tullut markkinoiden maamerkkitapahtuma. Oli vaikea kuvitella, että olimme hetkessä aseistettu täysin maksutta tehokkaalla ja käytännöllisellä työkalulla big datan käsittelyyn. Tietenkin, kun tarpeet kasvavat (esimerkiksi jakaminen ja replikointi useille palvelimille), järjestelmästä tulee monimutkaisempi. Mutta ensivaikutelman perusteella työskentely tämän tietokannan kanssa on erittäin miellyttävää. Voidaan nähdä, että tuote on tehty "ihmisiä varten".
ElasticSearchiin verrattuna lokien säilytys- ja käsittelykustannusten arvioidaan laskevan viidestä kymmeneen kertaan. Toisin sanoen, jos nykyiselle datamäärälle joutuisi perustamaan usean koneen klusteri, niin ClickHousea käytettäessä yksi pienitehoinen kone riittää meille. Kyllä, tietysti ElasticSearchilla on myös levyllä olevia tietojen pakkausmekanismeja ja muita ominaisuuksia, jotka voivat vähentää resurssien kulutusta merkittävästi, mutta ClickHouseen verrattuna tämä tulee kalliimmaksi.
Ilman erityisiä optimointejamme, oletusasetuksilla tietojen lataaminen ja valinta tietokannasta toimii hämmästyttävän nopeasti. Meillä ei ole vielä paljon dataa (noin 200 miljoonaa tietuetta), mutta itse palvelin on heikko. Voimme käyttää tätä työkalua jatkossa muihin tarkoituksiin, jotka eivät liity lokien tallentamiseen. Esimerkiksi päästä päähän -analytiikkaan turvallisuuden, koneoppimisen alalla.
Lopuksi vähän plussat ja miinukset.
Miinukset
- Ladataan tietueita suurissa erissä. Toisaalta tämä on ominaisuus, mutta sinun on silti käytettävä lisäkomponentteja tietueiden puskurointiin. Tämä tehtävä ei ole aina helppo, mutta silti ratkaistavissa. Ja haluaisin yksinkertaistaa järjestelmää.
- Jotkut eksoottiset toiminnot tai uudet ominaisuudet rikkoutuvat usein uusissa versioissa. Tämä aiheuttaa huolta ja vähentää halukkuutta päivittää uuteen versioon. Esimerkiksi Kafka-taulukkomoottori on erittäin hyödyllinen ominaisuus, jonka avulla voit lukea tapahtumia suoraan Kafkasta ilman kuluttajien käyttöönottoa. Mutta githubin ongelmien määrän perusteella olemme edelleen varovaisia, ettemme käytä tätä moottoria tuotannossa. Jos et kuitenkaan tee äkillisiä eleitä sivulle ja käytä päätoimintoa, se toimii vakaasti.
Pros
- Ei hidasta.
- Alhainen tulokynnys.
- Avoin lähdekoodi.
- Se on ilmainen.
- Skaalautuu hyvin (sharjoittelu/replikointi valmiina)
- Sisältyy viestintäministeriön suosittelemaan venäläisten ohjelmistojen rekisteriin.
- Yandexin virallisen tuen läsnäolo.
Lähde: will.com