ClickHouse Datebank fir Mënschen, oder Alien Technologies

Alexey Lizunov, Chef vum Kompetenzzenter fir Fernservicekanäl vun der Informatiounstechnologie Direktorat vun der ICB

ClickHouse Datebank fir Mënschen, oder Alien Technologies

Als Alternativ zum ELK Stack (ElasticSearch, Logstash, Kibana) maache mir Fuerschung iwwer d'Benotzung vun der ClickHouse Datebank als Datelagerung fir Logbicher.

An dësem Artikel wëlle mir iwwer eis Erfahrung mat der ClickHouse Datebank a virleefeg Resultater vun der Pilotoperatioun schwätzen. Et ass derwäert ze notéieren direkt datt d'Resultater beandrockend waren.


ClickHouse Datebank fir Mënschen, oder Alien Technologies

Als nächst wäerte mir méi detailléiert beschreiwen wéi eise System konfiguréiert ass a wéi eng Komponenten et besteet. Awer elo wëll ech e bëssen iwwer dës Datebank als Ganzt schwätzen, a firwat et derwäert ass opmierksam ze maachen. D'ClickHouse Datebank ass eng héich-Performance analytesch columnar Datebank vu Yandex. Benotzt an Yandex Servicer, am Ufank ass dëst den Haaptdatenlagerung fir Yandex.Metrica. Open-Source System, gratis. Aus der Siicht vum Entwéckler hunn ech mech ëmmer gefrot wéi se dat ëmgesat hunn, well et fantastesch grouss Daten gëtt. An d'Benotzerinterface vu Metrica selwer ass ganz flexibel a funktionnéiert séier. Wann Dir dës Datebank fir d'éischt kennt, kritt Dir den Androck: "Ma, endlech! Gemaach "fir d'Leit"! Vum Installatiounsprozess bis Ufroen schécken.

Dës Datebank huet eng ganz niddereg Entrée Barrière. Och en duerchschnëttlechen Entwéckler kann dës Datebank an e puer Minutten installéieren an ufänken se ze benotzen. Alles funktionnéiert glat. Och Leit, déi nei op Linux sinn, kënne séier mat der Installatioun eens ginn an einfach Operatiounen maachen. Wann fréier, wann Dir d'Wierder Big Data, Hadoop, Google BigTable, HDFS héieren huet, den duerchschnëttlechen Entwéckler d'Iddi hat datt se iwwer e puer Terabytes, Petabytes geschwat hunn, datt e puer Supermënschen an der Opstellung an Entwécklung fir dës Systemer involvéiert waren, dann mat der Advent vun der ClickHouse Datebank hu mir en einfachen, verständlechen Tool mat deem Dir eng virdru onerreechbar Palette vu Probleemer léise kënnt. Alles wat et brauch ass eng zimlech duerchschnëttlech Maschinn a fënnef Minutten fir ze installéieren. Dat ass, mir hunn eng Datebank wéi zum Beispill MySql, awer nëmme fir Milliarden records ze späicheren! Eng Zort Superarchiver mat SQL Sprooch. Et ass wéi wann d'Leit auslännesch Waffe kruten.

Iwwer eise Log Sammelsystem

Fir Informatioun ze sammelen, ginn IIS Logdateien vu Webapplikatioune vum Standardformat benotzt (mir sinn och am Moment mat der Parsing vun Applikatiounsprotokoller engagéiert, awer eist Haaptziel op der Pilotstadium ass IIS Logbicher ze sammelen).

Mir konnten den ELK Stack aus verschiddene Grënn net komplett opzeginn, a mir benotze weider d'LogStash a Filebeat Komponenten, déi sech gutt bewisen hunn a ganz zouverlässeg a prévisibel funktionnéieren.

Den allgemenge Logschema gëtt an der Figur hei ënnen gewisen:

ClickHouse Datebank fir Mënschen, oder Alien Technologies

Eng Feature fir Daten an der ClickHouse Datebank opzehuelen ass déi selten (eemol pro Sekonn) Aféierung vun Opzeechnungen a grousse Chargen. Dëst, anscheinend, ass dee "problemateschen" Deel deen Dir begéint wann Dir mat der ClickHouse Datebank fir d'éischte Kéier schafft: de Schema gëtt e bësse méi komplizéiert.
De Plugin fir LogStash, deen direkt Daten an ClickHouse setzt, huet hei vill gehollef. Dëse Komponent ass um selwechte Server wéi d'Datebank selwer ofgesat. Also, allgemeng geschwat, ass et net recommandéiert dëst ze maachen, awer aus enger praktescher Siicht, fir net separat Serveren ze kreéieren wärend et um selwechte Server ofgesat ass. Mir hu keng Feeler oder Ressourcekonflikter mat der Datebank observéiert. Zousätzlech ass et ze bemierken datt de Plugin e Retraymechanismus am Fall vu Feeler huet. An am Fall vu Feeler schreift de Plugin eng Partie Daten op Disk, déi net agefouert kënne ginn (d'Dateiformat ass bequem: no der Redaktioun kënnt Dir de korrigéierte Batch einfach mat Clickhouse-Client asetzen).

Eng komplett Lëscht vu Software, déi am Schema benotzt gëtt, gëtt an der Tabell presentéiert:

Lëscht vun Software benotzt

Titelen

Beschreiwung

Link op d'Verdeelung

NGINX

Reverse-Proxy fir den Zougang per Hafen ze beschränken an d'Autorisatioun z'organiséieren

Moment net am Schema benotzt

https://nginx.org/ru/download.html

https://nginx.org/download/nginx-1.16.0.tar.gz

FileBeat

Transfert vun Fichier Logbicher.

https://www.elastic.co/downloads/beats/filebeat (Verdeelung fir Windows 64bit).

https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.3.0-windows-x86_64.zip

LogStash

Log Sammler.

Benotzt fir Logbicher aus FileBeat ze sammelen, wéi och fir Logbicher aus der RabbitMQ Schlaang ze sammelen (fir Serveren an der DMZ.)

https://www.elastic.co/products/logstash

https://artifacts.elastic.co/downloads/logstash/logstash-7.0.1.rpm

Logstash- Output- Clickhouse

Loagstash Plugin fir Logbicher an d'ClickHouse Datebank a Chargen ze transferéieren

https://github.com/mikechris/logstash-output-clickhouse

/usr/share/logstash/bin/logstash-plugin installéieren logstash-output-clickhouse

/usr/share/logstash/bin/logstash-plugin installéieren logstash-filter-prune

/usr/share/logstash/bin/logstash-plugin installéieren logstash-filter-multiline

clickhouse

Log Stockage https://clickhouse.yandex/docs/ru/

https://packagecloud.io/Altinity/clickhouse/packages/el/7/clickhouse-server-19.5.3.8-1.el7.x86_64.rpm

https://packagecloud.io/Altinity/clickhouse/packages/el/7/clickhouse-client-19.5.3.8-1.el7.x86_64.rpm

Note. Vun August 2018 un, sinn "normale" RPM Builds fir RHEL am Yandex Repository erschien, sou datt Dir probéiert se ze benotzen. Zu der Zäit vun der Installatioun hu mir Pakete benotzt, kompiléiert vun Altinity.

grafana

Visualiséierung vu Logbicher. Ariichten Dashboards

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 Bit) - lescht Versioun

ClickHouse Datenquell fir Grafana 4.6+

Plugin fir Grafana mat ClickHouse Datenquell

https://grafana.com/plugins/vertamedia-clickhouse-datasource

https://grafana.com/api/plugins/vertamedia-clickhouse-datasource/versions/1.8.1/download

LogStash

Log Router vu FileBeat op RabbitMQ Queue.

Note. Leider huet FileBeat keen Output direkt op RabbitMQ, also ass en Zwëschenlink a Form vu Logstash erfuerderlech

https://www.elastic.co/products/logstash

https://artifacts.elastic.co/downloads/logstash/logstash-7.0.1.rpm

Kanéngchen MQ

Message Schlaang. Dëst ass e Puffer vu Log-Entréen am DMZ

https://www.rabbitmq.com/download.html

https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.14/rabbitmq-server-3.7.14-1.el7.noarch.rpm

Erlang Runtime (erfuerderlech fir RabbitMQ)

Erlang Runtime. Néideg fir RabbitMQ ze schaffen

http://www.erlang.org/download.html

https://www.rabbitmq.com/install-rpm.html#install-erlang http://www.erlang.org/downloads/21.3

D'Serverkonfiguratioun mat der ClickHouse Datebank gëtt an der folgender Tabell presentéiert:

Titelen

Wäert

Remarque

Configuratioun

HDD: 40 GB
RAM: 8GB
Prozessor: Core 2 2Ghz

Dir sollt op d'Tipps oppassen fir d'ClickHouse Datebank ze benotzen (https://clickhouse.yandex/docs/ru/operations/tips/)

System-breet Software

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Wéi Dir kënnt gesinn, ass dëst eng regulär Aarbechtsstatioun.

D'Struktur vum Dësch fir Logbicher ze späicheren ass wéi follegt:

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;

Mir benotze Standardwäerter fir Partitionéierung (monatlecht) an Indexgranularitéit. All Felder entspriechen praktesch IIS Log Entréen fir http Ufroen opzehuelen. Separat bemierken mir datt et getrennte Felder sinn fir utm Tags ze späicheren (si ginn an der Etapp vun der Aféierung an d'Tabell aus dem Ufro String Feld parséiert).

Och verschidde Systemfelder goufen un den Dësch bäigefüügt fir Informatioun iwwer Systemer, Komponenten a Serveren ze späicheren. Fir eng Beschreiwung vun dëse Felder, gesinn d'Tabell ënnert. An enger Tabell späichere mir Logbicher fir verschidde Systemer.

Titelen

Beschreiwung

Beispill:

fld_app_name

Applikatioun / System Numm
Gülteg Wäerter:

  • site1.domain.com Extern Site 1
  • site2.domain.com Extern Site 2
  • intern-site1.domain.local Interne Site 1

site1.domain.com

fld_app_module

System Modul
Gülteg Wäerter:

  • Web - Websäit
  • svc - Websäit Webservice
  • intgr - Webintegratiounsservice
  • bo - Administrator (BackOffice)

Web

fld_website_name

Site Numm an IIS

Verschidde Systemer kënnen op engem Server agesat ginn, oder souguer e puer Instanzen vun engem Systemmodul

web-main

fld_server_name

Server Numm

web1.domain.com

fld_log_file_name

Wee op d'Logbuchdatei um Server

Vun: inetpublogsLogFiles
W3SVC1u_ex190711.log

Dëst erlaabt Iech effizient Grafiken an Grafana ze bauen. Zum Beispill, kuckt Ufroe vum Frontend vun engem spezifesche System. Dëst ass ähnlech wéi de Site Konter an Yandex.Metrica.

Hei sinn e puer Statistiken iwwer d'Datebankverbrauch fir zwee Méint.

Zuel vun records duerch System a Komponent

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.)

Disk Daten Volumen

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.

Kolonn Daten Kompressioun Verhältnis

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.

Beschreiwung vun benotzt Komponente

FileBeat. Iwwerdroung vun Fichier Logbicher

Dëse Komponent iwwerwaacht Ännerungen fir Logdateien op Disk a passéiert d'Informatioun un LogStash. Installéiert op all Server wou Logdateien geschriwwe sinn (normalerweis IIS). Schafft am Schwanzmodus (dh, et transferéiert nëmmen addéiert records op d'Datei). Awer Dir kënnt et separat konfiguréieren fir ganz Dateien ze transferéieren. Dëst ass praktesch wann Dir Donnéeën fir de leschte Méint erofluede musst. Gitt einfach d'Logbuchdatei an en Dossier an et liest se a senger ganzer.

Wann de Service ophält, stoppt d'Daten weider op d'Späichere transferéiert.

Eng Beispillkonfiguratioun gesäit esou aus:

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. Log Sammler

Dëse Komponent ass entwéckelt fir Logbicher vu FileBeat (oder duerch eng RabbitMQ Schlaang) ze kréien, ze analyséieren an a Chargen an d'ClickHouse Datebank ze setzen.

Fir an ClickHouse ze setzen, benotzt de Logstash-output-clickhouse Plugin. De Logstash Plugin huet e Mechanismus fir Ufroen zréckzekréien, awer wärend engem reguläre Shutdown ass et besser de Service selwer ze stoppen. Wann et gestoppt gëtt, sammelen d'Messagen an der RabbitMQ Schlaang, also wann de Stop fir eng laang Zäit ass, dann ass et besser fir Filebeats op de Serveren ze stoppen. An engem Schema wou RabbitMQ net benotzt gëtt (am lokalen Netzwierk Filebeat schéckt direkt Logbicher op Logstash), funktionnéiert Filebeats ganz akzeptabel a sécher, also fir si huet d'Onverfügbarkeet vum Output keng Konsequenzen.

Eng Beispillkonfiguratioun gesäit esou aus:

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. Log Stockage

Logbicher fir all Systemer ginn an enger Tabell gespäichert (kuckt am Ufank vum Artikel). Et ass entwéckelt fir Informatioun iwwer Ufroen ze späicheren: all Parameter sinn ähnlech fir verschidde Formater, zum Beispill IIS Logbicher, Apache an nginx Logbicher. Fir Applikatiounsprotokoller, an deenen zum Beispill Feeler, Informatiounsmeldungen, Warnungen opgeholl ginn, gëtt eng separat Tabell mat der entspriechender Struktur (am Moment an der Designstadium) geliwwert.

Wann Dir en Dësch designt, ass et ganz wichteg iwwer de primäre Schlëssel ze entscheeden (duerch deen d'Donnéeën während der Lagerung zortéiert ginn). De Grad vun der Datekompressioun an der Ufrogeschwindegkeet hänkt dovun of. An eisem Beispill ass de Schlëssel
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Dat ass, mam Numm vum System, dem Numm vun der Systemkomponent an dem Datum vum Event. Am Ufank ass den Datum vum Event als éischt komm. Nodeems et op déi lescht Plaz geplënnert ass, hunn Ufroen ugefaang ongeféier duebel sou séier ze schaffen. De primäre Schlëssel z'änneren erfuerdert d'Tabell nei ze kreéieren an d'Daten nei eropzelueden, sou datt ClickHouse d'Donnéeën op der Disk nei sortéiert. Dëst ass eng schwiereg Operatioun, also ass et unzeroden am Viraus suergfälteg nozedenken wat an der Sortéierungsschlëssel abegraff sinn.

Et sollt och bemierkt ginn datt den LowCardinality Datentyp a relativ rezente Versioune erschéngt. Wann Dir se benotzt, gëtt d'Gréisst vun de kompriméierte Daten staark reduzéiert fir déi Felder déi niddereg Kardinalitéit hunn (puer Optiounen).

Mir benotzen de Moment Versioun 19.6 a mir plangen ze probéieren op déi lescht Versioun ze aktualiséieren. Si hunn sou wonnerbar Features wéi Adaptive Granularity, Skipping Indizes an den DoubleDelta Codec, zum Beispill.

Par défaut, wärend der Installatioun ass de Konfiguratiounsprotokollniveau op Trace gesat. Logbicher ginn rotéiert an archivéiert, awer gläichzäiteg erweideren se bis zu engem Gigabyte. Wann et kee Besoin ass, da kënnt Dir den Niveau op Warnung setzen, da wäert d'Loggréisst staark erofgoen. D'Logéierungsastellunge ginn an der config.xml Datei spezifizéiert:

<!-- Possible levels: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger. h#L105 -->
<level>warning</level>

E puer nëtzlech Kommandoen

Поскольку оригинальные пакеты установки собираются по 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. Log Router vu FileBeat op RabbitMQ Queue

Dëse Komponent gëtt benotzt fir Logbicher aus FileBeat an d'RabbitMQ Schlaang ze routen. Et ginn zwee Punkten hei:

  1. Leider huet FileBeat keen Output Plugin fir direkt op RabbitMQ ze schreiwen. An esou Funktionalitéit, no der Post op hirem Github beurteelen, ass net fir d'Ëmsetzung geplangt. Et gëtt e Plugin fir Kafka, awer aus bestëmmte Grënn kënne mir et net selwer benotzen.
  2. Et gi Viraussetzunge fir Logbicher am DMZ ze sammelen. Baséierend op hinnen, mussen d'Logbicher als éischt an der Schlaang gesat ginn an dann liest LogStash records aus der Schlaang extern.

Dofir, speziell fir de Fall vun Serveren an engem DMZ, ass et néideg esou e bësse komplizéiert Schema ze benotzen. Eng Beispillkonfiguratioun gesäit esou aus:

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. Message Queue

Dëse Bestanddeel gëtt benotzt fir d'Logbicher an der DMZ ze bufferen. Opnam gëtt duerch de Filebeat → LogStash Link gemaach. D'Liesen gëtt vu baussen der DMZ iwwer LogStash gemaach. Wann Dir duerch RabbitMQ funktionnéiert, ginn ongeféier 4 dausend Messagen pro Sekonn veraarbecht.

Message Routing ass vum Systemnumm konfiguréiert, dh baséiert op FileBeat Konfiguratiounsdaten. All Message ginn an eng Schlaang. Wann aus irgendege Grënn de Schlaangservice gestoppt gëtt, féiert dat net zu Messageverloscht: FileBeats kritt Verbindungsfehler a wäert temporär ophalen ze schécken. A LogStash, déi aus der Schlaang liest, kritt och Netzwierkfehler a waart op d'Verbindung restauréiert. An dësem Fall ginn d'Donnéeën natierlech net méi an d'Datebank geschriwwe ginn.

Déi folgend Instruktioune gi benotzt fir Schlaangen ze kreéieren an ze konfiguréieren:

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. Dashboards

Dëse Komponent gëtt benotzt fir Iwwerwaachungsdaten ze visualiséieren. An dësem Fall musst Dir de ClickHouse Datasource fir Grafana 4.6+ Plugin installéieren. Mir hu missen et e bëssen tweaken fir d'Effizienz vun der Veraarbechtung vun SQL Filteren um Dashboard ze verbesseren.

Zum Beispill benotze mir Variablen, a wa se net am Filterfeld spezifizéiert sinn, da géife mir gär datt et keng Konditioun an der WHERE vun der Form generéiert ( uriStem = "AN uriStem != "). An dësem Fall liest ClickHouse d'uriStem Kolonn. Also hu mir verschidden Optiounen probéiert an endlech de Plugin fixéiert (den $valueIfEmpty Makro) fir 1 am Fall vun engem eidele Wäert zréckzekommen, ouni d'Kolonn selwer ze ernimmen.

An elo kënnt Dir dës Ufro fir d'Grafik benotzen

$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')

deen esou an SQL ëmgewandelt gëtt (notéiert datt eidel uriStem Felder op just 1 ëmgewandelt ginn)

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

Konklusioun

D'Erscheinung vun der ClickHouse Datebank ass e Landmark Event um Maart ginn. Et war schwéier ze virstellen datt mir an engem Moment, komplett gratis, mat engem mächtege a praktesche Tool bewaffnet waren fir mat Big Data ze schaffen. Natierlech, wéi d'Bedierfnesser eropgoen (zum Beispill Sharding a Replikatioun op verschidde Serveren), gëtt de Schema méi komplex. Awer no éischten Andréck, mat dëser Datebank ze schaffen ass ganz agreabel. Et ass kloer datt de Produit "fir Leit" gemaach gëtt.

Am Verglach mat ElasticSearch sinn d'Käschte fir d'Lagerung an d'Veraarbechtung vu Logbicher, laut virleefeg Schätzungen, ëm fënnef bis zéng Mol reduzéiert. An anere Wierder, wa mir fir den aktuellen Datenvolumen e Stärekoup vu verschiddene Maschinnen opriichte mussen, da brauche mir wann Dir ClickHouse benotzt, nëmmen eng Low-Power Maschinn. Jo, natierlech, ElasticSearch huet och On-Disk Datekompressiounsmechanismen an aner Funktiounen, déi de Ressourceverbrauch wesentlech reduzéiere kënnen, awer am Verglach zum ClickHouse wäert dëst méi grouss Käschten erfuerderen.

Ouni speziell Optimisatiounen vun eiser Säit, mat Standardastellungen, Luede Daten an Erhuelung vun Daten aus der Datebank funktionnéiert mat erstaunlecher Geschwindegkeet. Mir hunn nach net vill Daten (ongeféier 200 Millioune Rekorder), awer de Server selwer ass schwaach. Mir kënnen dëst Tool an Zukunft fir aner Zwecker benotzen, déi net mam Logbicher späicheren. Zum Beispill, fir End-to-End Analyse, am Beräich Sécherheet, Maschinnléieren.

Zum Schluss e bëssen iwwer d'Virdeeler an Nodeeler.

Минусы

  1. Luede records a grousse Chargen. Engersäits ass dëst eng Feature, awer Dir musst nach ëmmer zousätzlech Komponenten benotze fir Rekorder ze bufferen. Dës Aufgab ass net ëmmer einfach, awer trotzdem léisbar. An ech wéilt de Schema vereinfachen.
  2. E puer exotesch Funktionalitéit oder nei Fonctiounen briechen dacks an nei Versiounen. Dëst mécht Bedenken, reduzéieren de Wonsch op eng nei Versioun Upgrade. Zum Beispill ass de Kafka Dëschmotor eng ganz nëtzlech Feature déi Iech erlaabt direkt Eventer vu Kafka ze liesen, ouni d'Konsumenten ëmzesetzen. Awer duerch d'Zuel vun den Themen op Github beurteelen, si mir nach ëmmer virsiichteg fir dëse Motor an der Produktioun ze benotzen. Wann Dir awer keng plötzlech Beweegungen op d'Säit maacht an d'Basisfunktionalitéit benotzt, da funktionnéiert et stabil.

Plus

  1. Bréngt net méi lues.
  2. Niddereg Entrée Schwell.
  3. Open Source.
  4. fräi.
  5. Skalierbar (Sharding / Out-of-the-Box Replikatioun)
  6. Abegraff am Register vun russesch Software recommandéiert vum Ministère fir Kommunikatioun.
  7. Disponibilitéit vun offiziell Ënnerstëtzung vun Yandex.

Source: will.com

Setzt e Commentaire