ClickHouse baza podataka za ljude ili vanzemaljske tehnologije

Aleksej Lizunov, voditelj Centra kompetencija za kanale daljinskih usluga Uprave za informacijske tehnologije MKB-a

ClickHouse baza podataka za ljude ili vanzemaljske tehnologije

Kao alternativu ELK stacku (ElasticSearch, Logstash, Kibana), istražujemo korištenje baze podataka ClickHouse kao pohrane podataka za zapise.

U ovom članku želimo govoriti o našem iskustvu korištenja baze podataka ClickHouse i preliminarnim rezultatima pilot operacije. Odmah treba napomenuti da su rezultati bili impresivni.


ClickHouse baza podataka za ljude ili vanzemaljske tehnologije

Zatim ćemo detaljnije opisati kako je naš sustav konfiguriran i od kojih se komponenti sastoji. Ali sada bih želio govoriti malo o ovoj bazi podataka u cjelini i zašto je vrijedno pažnje. Baza podataka ClickHouse je visokoučinkovita analitička baza podataka u stupcima tvrtke Yandex. Koristi se u uslugama Yandex, u početku je glavna pohrana podataka za Yandex.Metricu. Sustav otvorenog koda, besplatan. Sa stajališta programera, uvijek sam se pitao kako su to implementirali, jer ima fantastično velikih podataka. I samo korisničko sučelje Metrice vrlo je fleksibilno i brzo. Pri prvom upoznavanju s ovom bazom podataka dojam je: „E, konačno! Stvoreno za ljude! Počevši od procesa instalacije pa sve do slanja zahtjeva.

Ova baza podataka ima vrlo nizak ulazni prag. Čak i prosječno vješt programer može instalirati ovu bazu podataka u nekoliko minuta i početi je koristiti. Sve radi jasno. Čak i ljudi koji su novi u Linuxu mogu brzo obaviti instalaciju i izvesti najjednostavnije operacije. Ako je ranije uz riječi Big Data, Hadoop, Google BigTable, HDFS obični programer imao ideje da se radi o nekim terabajtima, petabajtima, da se nekim nadljudima bave postavkama i razvojem za te sustave, onda je pojavom ClickHousea baze podataka, dobili smo jednostavan, razumljiv alat s kojim možete riješiti dosad nedostižan niz zadataka. Za instalaciju je potreban samo jedan prilično prosječan stroj i pet minuta. Odnosno, dobili smo takvu bazu podataka kao što je, na primjer, MySql, ali samo za pohranjivanje milijardi zapisa! Određeni super-arhivator sa SQL jezikom. Kao da je ljudima predano oružje vanzemaljaca.

O našem sustavu zapisivanja

Za prikupljanje informacija koriste se IIS log datoteke web aplikacija standardnog formata (trenutačno analiziramo i logove aplikacija, ali glavni cilj u pilot fazi je prikupljanje IIS logova).

Iz različitih razloga nismo mogli u potpunosti napustiti ELK stack, te nastavljamo koristiti LogStash i Filebeat komponente, koje su se dobro pokazale i rade prilično pouzdano i predvidljivo.

Opća shema zapisivanja prikazana je na donjoj slici:

ClickHouse baza podataka za ljude ili vanzemaljske tehnologije

Značajka pisanja podataka u bazu podataka ClickHouse je rijetko (jednom u sekundi) umetanje zapisa u velikim serijama. Ovo je, očito, "najproblematičniji" dio s kojim se susrećete kada prvi put iskusite rad s bazom podataka ClickHouse: shema postaje malo kompliciranija.
Tu je puno pomogao dodatak za LogStash koji izravno ubacuje podatke u ClickHouse. Ova komponenta je postavljena na istom poslužitelju kao i sama baza podataka. Dakle, općenito govoreći, nije preporučljivo to raditi, ali s praktične točke gledišta, kako se ne bi proizvodili zasebni poslužitelji dok je raspoređen na istom poslužitelju. Nismo primijetili nikakve kvarove ili sukobe resursa s bazom podataka. Osim toga, treba napomenuti da dodatak ima mehanizam ponovnog pokušaja u slučaju pogreške. A u slučaju pogrešaka, dodatak zapisuje na disk skup podataka koji se ne mogu umetnuti (format datoteke je prikladan: nakon uređivanja možete jednostavno umetnuti ispravljeni paket pomoću clickhouse-clienta).

Kompletan popis softvera koji se koristi u shemi prikazan je u tablici:

Popis korištenog softvera

ime

Opis

Distribucijska veza

Nginx

Reverse-proxy za ograničavanje pristupa portovima i organiziranje autorizacije

Trenutno se ne koristi u shemi

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

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

FileBeat

Prijenos zapisa datoteka.

https://www.elastic.co/downloads/beats/filebeat (distribucijski komplet za Windows 64bit).

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

logstash

Sakupljač trupaca.

Koristi se za prikupljanje zapisa iz FileBeata, kao i za prikupljanje zapisa iz RabbitMQ reda (za poslužitelje koji su u DMZ-u.)

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

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

Logstash-output-clickhouse

Dodatak Loagstash za prijenos zapisa u bazu podataka ClickHouse u serijama

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

/usr/share/logstash/bin/logstash-plugin instalacija logstash-output-clickhouse

/usr/share/logstash/bin/logstash-plugin instalacija logstash-filter-prune

/usr/share/logstash/bin/logstash-plugin instalacija logstash-filter-multiline

klikanica

Pohranjivanje dnevnika 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

Bilješka. Počevši od kolovoza 2018., "normalne" rpm verzije za RHEL pojavile su se u Yandex repozitoriju, tako da ih možete pokušati koristiti. U vrijeme instalacije koristili smo pakete koje je izradio Altinity.

grafana

Vizualizacija dnevnika. Postavljanje nadzornih ploča

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 Bit) - najnovija verzija

ClickHouse izvor podataka za Grafana 4.6+

Dodatak za Grafanu s izvorom podataka ClickHouse

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

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

logstash

Zapišite usmjerivač iz FileBeata u RabbitMQ red čekanja.

Bilješka. Nažalost, FileBeat nema izlaz izravno na RabbitMQ, pa je potrebna posredna poveznica u obliku Logstasha

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

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

Zec MQ

red poruka. Ovo je međuspremnik dnevnika u DMZ-u

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 (Potrebno za RabbitMQ)

Erlang runtime. Potreban za rad RabbitMQ-a

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

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

Konfiguracija poslužitelja s bazom podataka ClickHouse prikazana je u sljedećoj tablici:

ime

Vrijednost

Primijetiti

Konfiguracija

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

Potrebno je obratiti pažnju na savjete za rad baze podataka ClickHouse (https://clickhouse.yandex/docs/ru/operations/tips/)

Opći sistemski softver

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Kao što vidite, ovo je obična radna stanica.

Struktura tablice za pohranjivanje dnevnika je sljedeća:

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;

Koristimo zadanu particiju (po mjesecima) i granularnost indeksa. Sva polja praktički odgovaraju IIS log unosima za bilježenje http zahtjeva. Zasebno napominjemo da postoje zasebna polja za pohranjivanje utm-oznaka (raščlanjuju se u fazi umetanja u tablicu iz polja niza upita).

Također, u tablicu je dodano nekoliko sistemskih polja za pohranu informacija o sustavima, komponentama, poslužiteljima. Za opis ovih polja pogledajte tablicu u nastavku. U jednoj tablici pohranjujemo zapise za nekoliko sustava.

ime

Opis

Primjer

naziv_fld_aplikacije

Naziv aplikacije/sustava
Važeće vrijednosti:

  • site1.domain.com Vanjska stranica 1
  • site2.domain.com Vanjska stranica 2
  • interna-stranica1.domena.lokalno Interna stranica 1

site1.domain.com

fld_app_module

Modul sustava
Važeće vrijednosti:

  • web - Web stranica
  • svc - Usluga web stranice
  • intgr - Integracijska web usluga
  • bo - Administrator (BackOffice)

tkanje

fld_website_name

Naziv stranice u IIS-u

Na jednom poslužitelju može se postaviti nekoliko sustava ili čak nekoliko instanci jednog modula sustava

web glavni

ime_poslužitelja_fld

Naziv poslužitelja

web1.domena.com

fld_log_file_name

Put do datoteke dnevnika na poslužitelju

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

To vam omogućuje učinkovitu izradu grafikona u Grafani. Na primjer, pregledajte zahtjeve sa sučelja određenog sustava. Ovo je slično brojaču stranica u Yandex.Metrici.

Evo nekoliko statistika o korištenju baze podataka za dva mjeseca.

Broj zapisa raščlanjenih po sustavima i njihovim komponentama

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

Količina podataka na disku

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.

Stupanj kompresije podataka u stupcima

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.

Opis korištenih komponenti

FileBeat. Prijenos zapisnika datoteka

Ova komponenta prati promjene u log datotekama na disku i prosljeđuje informacije LogStashu. Instalirano na svim poslužiteljima na kojima se pišu datoteke dnevnika (obično IIS). Radi u repnom načinu (tj. prenosi samo dodane zapise u datoteku). Ali zasebno se može konfigurirati za prijenos cijelih datoteka. Ovo je korisno kada trebate preuzeti podatke iz prethodnih mjeseci. Samo stavite log datoteku u mapu i on će je pročitati u cijelosti.

Kada se usluga zaustavi, podaci se više ne prenose dalje u pohranu.

Primjer konfiguracije izgleda ovako:

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. Sakupljač dnevnika

Ova je komponenta dizajnirana za primanje unosa dnevnika od FileBeata (ili kroz RabbitMQ red čekanja), analiziranje i umetanje serija u bazu podataka ClickHouse.

Za umetanje u ClickHouse koristi se dodatak Logstash-output-clickhouse. Dodatak Logstash ima mehanizam za ponovni pokušaj zahtjeva, ali s redovitim gašenjem bolje je zaustaviti sam servis. Kada se zaustave, poruke će se akumulirati u RabbitMQ redu čekanja, pa ako je zaustavljanje na duže vrijeme, onda je bolje zaustaviti Filebeats na poslužiteljima. U shemi gdje se RabbitMQ ne koristi (na lokalnoj mreži Filebeat izravno šalje logove u Logstash), Filebeati rade sasvim prihvatljivo i sigurno, pa za njih nedostupnost izlaza prolazi bez posljedica.

Primjer konfiguracije izgleda ovako:

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"
        }
    }
 
}

cjevovodi.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"

klikanica. Pohranjivanje dnevnika

Dnevnici za sve sustave pohranjuju se u jednu tablicu (vidi na početku članka). Namijenjen je pohrani informacija o zahtjevima: svi parametri su slični za različite formate, kao što su IIS zapisnici, apache i nginx zapisnici. Za zapise aplikacija, u koje se bilježe npr. pogreške, informativne poruke, upozorenja, bit će osigurana posebna tablica s odgovarajućom strukturom (trenutačno u fazi projektiranja).

Prilikom izrade tablice vrlo je važno odlučiti se o primarnom ključu (po kojem će se podaci sortirati tijekom pohrane). O tome ovisi stupanj kompresije podataka i brzina upita. U našem primjeru, ključ je
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Odnosno prema nazivu sustava, nazivu komponente sustava i datumu događaja. U početku je na prvom mjestu bio datum događaja. Nakon što su ga premjestili na posljednje mjesto, upiti su počeli raditi otprilike dvostruko brže. Promjena primarnog ključa zahtijevat će ponovno stvaranje tablice i ponovno učitavanje podataka tako da ClickHouse ponovno sortira podatke na disku. Ovo je teška operacija, stoga je dobra ideja puno razmišljati o tome što bi trebalo biti uključeno u ključ sortiranja.

Također treba napomenuti da se tip podataka LowCardinality relativno pojavio u novijim verzijama. Kada ga koristite, veličina komprimiranih podataka je drastično smanjena za ona polja koja imaju nisku kardinalnost (malo opcija).

Trenutno je u upotrebi verzija 19.6 i planiramo pokušati ažurirati na najnoviju verziju. Imaju tako divne značajke kao što su Adaptive Granularity, Skipping indeksi i DoubleDelta kodek, na primjer.

Prema zadanim postavkama, tijekom instalacije, razina zapisivanja postavljena je na praćenje. Dnevnici se rotiraju i arhiviraju, ali se istovremeno proširuju do gigabajta. Ako nema potrebe, možete postaviti razinu upozorenja, tada se veličina dnevnika drastično smanjuje. Postavka zapisivanja postavljena je u datoteci config.xml:

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

Neke korisne naredbe

Поскольку оригинальные пакеты установки собираются по 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. Zapišite usmjerivač iz FileBeata u RabbitMQ red čekanja

Ova se komponenta koristi za usmjeravanje zapisa koji dolaze iz FileBeata u RabbitMQ red čekanja. Ovdje postoje dvije točke:

  1. Nažalost, FileBeat nema izlazni dodatak za izravno pisanje u RabbitMQ. A takva funkcionalnost, sudeći po pitanju na njihovom githubu, nije planirana za implementaciju. Postoji dodatak za Kafku, ali ga iz nekog razloga ne možemo koristiti kod kuće.
  2. Postoje zahtjevi za prikupljanje trupaca u DMZ. Na temelju njih, dnevnici se prvo moraju dodati u red čekanja, a zatim LogStash izvana čita unose iz reda čekanja.

Stoga se za slučaj kada se poslužitelji nalaze u DMZ-u mora koristiti ovakva pomalo komplicirana shema. Primjer konfiguracije izgleda ovako:

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. red poruka

Ova se komponenta koristi za međuspremnik unosa dnevnika u DMZ. Snimanje se vrši kroz hrpu Filebeat → LogStash. Čitanje se vrši izvan DMZ-a putem LogStasha. Pri radu preko RabboitMQ-a obrađuje se oko 4 tisuće poruka u sekundi.

Usmjeravanje poruka konfigurirano je prema nazivu sustava, tj. na temelju FileBeat konfiguracijskih podataka. Sve poruke idu u jedan red. Ako se iz nekog razloga usluga čekanja zaustavi, to neće dovesti do gubitka poruka: FileBeats će primiti pogreške veze i privremeno obustaviti slanje. A LogStash koji čita iz reda čekanja također će primati mrežne pogreške i čekati da se veza uspostavi. U tom slučaju podaci, naravno, više neće biti upisani u bazu podataka.

Za izradu i konfiguraciju redova čekanja koriste se sljedeće upute:

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. Nadzorne ploče

Ova se komponenta koristi za vizualizaciju podataka praćenja. U tom slučaju trebate instalirati izvor podataka ClickHouse za Grafana 4.6+ dodatak. Morali smo ga malo prilagoditi kako bismo poboljšali učinkovitost obrade SQL filtara na nadzornoj ploči.

Na primjer, koristimo varijable, a ako one nisu postavljene u polje filtera, tada bismo željeli da ne generira uvjet u WHERE obrasca ( uriStem = » AND uriStem != » ). U ovom slučaju, ClickHouse će pročitati stupac uriStem. Općenito, isprobali smo različite opcije i na kraju ispravili dodatak (makronaredba $valueIfEmpty) tako da u slučaju prazne vrijednosti vraća 1, bez spominjanja samog stupca.

Sada možete koristiti ovaj upit za grafikon

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

što se prevodi u ovaj SQL (imajte na umu da su prazna uriStem polja pretvorena u samo 1)

SELECT
t,
groupArray((response, c)) AS groupArr
FROM (
SELECT
(intDiv(toUInt32(logdatetime), 60) * 60) * 1000 AS t, response,
count(*) AS c FROM default.log_web
WHERE (logdate >= toDate(1565061982)) AND (logdatetime >= toDateTime(1565061982)) AND 1 AND (fld_app_name = 'site1.domain.ru') AND (fld_app_module = 'web') AND 1 AND 1 AND 1
GROUP BY
t, response
ORDER BY
t ASC,
response ASC
)
GROUP BY t ORDER BY t ASC

Zaključak

Pojava baze podataka ClickHouse postala je značajan događaj na tržištu. Bilo je teško zamisliti da smo, potpuno besplatno, u trenu dobili moćan i praktičan alat za rad s velikim podacima. Naravno, s povećanjem potreba (na primjer, dijeljenje i replikacija na više poslužitelja), shema će postati kompliciranija. Ali na prvi dojam, rad s ovom bazom podataka je vrlo ugodan. Vidi se da je proizvod napravljen "za ljude".

U usporedbi s ElasticSearchom, procjenjuje se da su troškovi pohrane i obrade zapisa smanjeni pet do deset puta. Drugim riječima, ako bismo za trenutnu količinu podataka morali postaviti klaster od nekoliko strojeva, onda nam je kod ClickHousea dovoljan jedan stroj male snage. Da, naravno, ElasticSearch također ima mehanizme kompresije podataka na disku i druge značajke koje mogu značajno smanjiti potrošnju resursa, ali u usporedbi s ClickHouseom, to će biti skuplje.

Bez ikakvih posebnih optimizacija s naše strane, na zadanim postavkama, učitavanje podataka i odabir iz baze radi nevjerojatnom brzinom. Još nemamo puno podataka (oko 200 milijuna zapisa), ali sam poslužitelj je slab. Ovaj alat možemo koristiti u budućnosti u druge svrhe koje nisu povezane s pohranjivanjem dnevnika. Na primjer, za end-to-end analitiku, u području sigurnosti, strojnog učenja.

Na kraju, malo o prednostima i manama.

Cons

  1. Učitavanje zapisa u velikim serijama. S jedne strane, ovo je značajka, ali još uvijek morate koristiti dodatne komponente za međuspremnik zapisa. Ovaj zadatak nije uvijek lak, ali ipak rješiv. I želio bih pojednostaviti shemu.
  2. Neke egzotične funkcije ili nove značajke često se kvare u novim verzijama. To izaziva zabrinutost, smanjujući želju za nadogradnjom na novu verziju. Na primjer, Kafka table engine je vrlo korisna značajka koja vam omogućuje izravno čitanje događaja iz Kafke, bez implementacije potrošača. No, sudeći po broju problema na githubu, još uvijek pazimo da ne koristimo ovaj mehanizam u proizvodnji. Međutim, ako ne radite nagle geste u stranu i koristite glavnu funkcionalnost, tada radi stabilno.

Prozodija

  1. Ne usporava.
  2. Nizak prag ulaska.
  3. Otvoreni izvor.
  4. Besplatno.
  5. Dobro se skalira (sharding/replikacija izvan kutije)
  6. Uključeno u registar ruskog softvera koje je preporučilo Ministarstvo komunikacija.
  7. Prisutnost službene podrške od Yandex.

Izvor: www.habr.com

Dodajte komentar