Baza podatkov ClickHouse za ljudi ali Alien Technologies

Aleksej Lizunov, vodja kompetenčnega centra za kanale storitev na daljavo Direktorata za informacijsko tehnologijo ICB

Baza podatkov ClickHouse za ljudi ali Alien Technologies

Kot alternativo skladu ELK (ElasticSearch, Logstash, Kibana) izvajamo raziskavo o uporabi baze podatkov ClickHouse kot shranjevanja podatkov za dnevnike.

V tem članku bi radi govorili o naših izkušnjah z uporabo baze podatkov ClickHouse in preliminarnih rezultatih pilotnega delovanja. Takoj velja omeniti, da so bili rezultati impresivni.


Baza podatkov ClickHouse za ljudi ali Alien Technologies

Nato bomo podrobneje opisali, kako je naš sistem konfiguriran in iz katerih komponent je sestavljen. Zdaj pa bi rad nekaj govoril o tej bazi podatkov kot celoti in zakaj je vredno pozornosti nanjo. Podatkovna baza ClickHouse je visoko zmogljiva analitična stolpična baza podatkov podjetja Yandex. Uporablja se v storitvah Yandex, sprva je to glavna shramba podatkov za Yandex.Metrica. Odprtokodni sistem, brezplačen. Z vidika razvijalca sem se vedno spraševal, kako so to implementirali, saj je podatkov fantastično veliko. In sam uporabniški vmesnik Metrica je zelo prilagodljiv in deluje hitro. Ko se prvič seznanite s to bazo podatkov, dobite vtis: »No, končno! Narejeno "za ljudi"! Od postopka namestitve do pošiljanja zahtev.”

Ta zbirka podatkov ima zelo nizko vstopno oviro. Tudi povprečen razvijalec lahko to bazo podatkov namesti v nekaj minutah in jo začne uporabljati. Vse deluje gladko. Celo ljudje, ki so novi v Linuxu, se lahko hitro spopadejo z namestitvijo in izvajajo preproste operacije. Če je prej, ko je slišal besede Big Data, Hadoop, Google BigTable, HDFS, imel povprečni razvijalec idejo, da je govora o nekih terabajtih, petabajtih, da so neki superljudje vpleteni v nastavitev in razvoj teh sistemov, potem je z S pojavom baze podatkov ClickHouse smo dobili preprosto in razumljivo orodje, s katerim lahko rešite doslej nedosegljivo vrsto težav. Vse, kar potrebujete, je en dokaj povprečen stroj in pet minut za namestitev. To pomeni, da smo dobili bazo podatkov, kot je na primer MySql, vendar samo za shranjevanje milijard zapisov! Nekakšen superarhiver z jezikom SQL. Kot da bi ljudje dobili nezemljansko orožje.

O našem sistemu zbiranja dnevnikov

Za zbiranje informacij se uporabljajo IIS dnevniške datoteke spletnih aplikacij standardnega formata (trenutno se ukvarjamo tudi z razčlenjevanjem aplikacijskih dnevnikov, vendar je naš glavni cilj v pilotni fazi zbiranje IIS dnevnikov).

Sklada ELK zaradi različnih razlogov nismo mogli popolnoma opustiti, še naprej pa uporabljamo komponenti LogStash in Filebeat, ki sta se izkazali in delujeta precej zanesljivo in predvidljivo.

Splošna shema beleženja je prikazana na spodnji sliki:

Baza podatkov ClickHouse za ljudi ali Alien Technologies

Značilnost beleženja podatkov v bazi podatkov ClickHouse je redko (enkrat na sekundo) vstavljanje zapisov v velikih serijah. To je očitno najbolj "problematičen" del, s katerim se srečate, ko prvič delate z bazo podatkov ClickHouse: shema postane nekoliko bolj zapletena.
Tu je veliko pomagal vtičnik za LogStash, ki neposredno vnaša podatke v ClickHouse. Ta komponenta je nameščena na istem strežniku kot baza podatkov. Torej na splošno tega ni priporočljivo storiti, vendar s praktičnega vidika, da ne ustvarite ločenih strežnikov, medtem ko je nameščen na istem strežniku. Nismo opazili nobenih napak ali konfliktov virov z bazo podatkov. Poleg tega je treba opozoriti, da ima vtičnik mehanizem ponovnega predvajanja v primeru napak. In v primeru napak, vtičnik zapiše na disk paket podatkov, ki jih ni bilo mogoče vstaviti (oblika datoteke je priročna: po urejanju lahko preprosto vstavite popravljeni paket s klientom clickhouse).

Celoten seznam programske opreme, uporabljene v shemi, je predstavljen v tabeli:

Seznam uporabljene programske opreme

Ime

Opis

Povezava do distribucije

nginx

Reverse-proxy za omejevanje dostopa po vratih in organiziranje avtorizacije

Trenutno se ne uporablja v shemi

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

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

FileBeat

Prenos dnevnikov datotek.

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

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

LogStash

Zbiralec hlodov.

Uporablja se za zbiranje dnevnikov iz FileBeat, kot tudi za zbiranje dnevnikov iz čakalne vrste RabbitMQ (za strežnike, ki se nahajajo v DMZ.)

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

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

Logstash- output- clickhouse

Vtičnik Loagstash za paketni prenos dnevnikov v bazo podatkov ClickHouse

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

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

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

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

KlikniteHouse

Shranjevanje 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

Opomba. Od avgusta 2018 so se v repozitoriju Yandex pojavile »običajne« rpm gradnje za RHEL, tako da jih lahko poskusite uporabiti. V času namestitve smo uporabljali pakete, ki jih je prevedel Altinity.

grafana

Vizualizacija dnevnikov. Nastavitev nadzornih plošč

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 Bit) – najnovejša različica

Vir podatkov ClickHouse za Grafana 4.6+

Vtičnik za Grafana z izvorom podatkov ClickHouse

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

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

LogStash

Zabeleži usmerjevalnik iz FileBeat v čakalno vrsto RabbitMQ.

Opomba. Na žalost FileBeat nima izhoda neposredno v RabbitMQ, zato je potrebna vmesna povezava v obliki Logstash

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

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

RabbitMQ

Čakalna vrsta sporočil. To je medpomnilnik vnosov dnevnika v 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 (zahtevan za RabbitMQ)

Erlang runtime. Potreben za delovanje RabbitMQ

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

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

Konfiguracija strežnika z bazo podatkov ClickHouse je predstavljena v naslednji tabeli:

Ime

Vrednost

Obvestilo

Konfiguracija

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

Pozorni bodite na nasvete za uporabo baze podatkov ClickHouse (https://clickhouse.yandex/docs/ru/operations/tips/)

Sistemska programska oprema

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Kot lahko vidite, je to običajna delovna postaja.

Struktura tabele za shranjevanje dnevnikov je naslednja:

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;

Uporabljamo privzete vrednosti za particioniranje (mesečno) in razdrobljenost indeksa. Vsa polja praktično ustrezajo vnosom v dnevnik IIS za beleženje zahtev http. Ločeno ugotavljamo, da obstajajo ločena polja za shranjevanje oznak utm (razčlenjena so na stopnji vstavljanja v tabelo iz polja poizvedbenega niza).

Poleg tega je bilo v tabelo dodanih več sistemskih polj za shranjevanje informacij o sistemih, komponentah in strežnikih. Za opis teh polj glejte spodnjo tabelo. V eni tabeli hranimo dnevnike za več sistemov.

Ime

Opis

Primer

ime_fld_aplikacije

Ime aplikacije/sistema
Veljavne vrednosti:

  • site1.domain.com Zunanje mesto 1
  • site2.domain.com Zunanje mesto 2
  • internal-site1.domain.local Interno mesto 1

mesto1.domena.com

fld_app_module

Sistemski modul
Veljavne vrednosti:

  • splet - Spletna stran
  • svc — Spletna storitev spletnega mesta
  • intgr — storitev spletne integracije
  • bo — Administrator (BackOffice)

web

fld_ime_spletnega mesta

Ime mesta v IIS

Na enem strežniku je lahko nameščenih več sistemov ali celo več primerkov enega sistemskega modula

spletna glavna

ime_strežnika_fld

Ime strežnika

splet1.domena.com

fld_log_file_name

Pot do dnevniške datoteke na strežniku

Od:inetpublogsLogFiles
W3SVC1u_ex190711.log

To vam omogoča učinkovito gradnjo grafov v Grafani. Oglejte si na primer zahteve s sprednjega dela določenega sistema. To je podobno števcu spletnih mest v Yandex.Metrici.

Tukaj je nekaj statističnih podatkov o uporabi baze podatkov za dva meseca.

Število zapisov po sistemu in komponenti

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

Prostornina podatkov 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.

Razmerje stiskanja podatkov stolpca

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 uporabljenih komponent

FileBeat. Prenos dnevnikov datotek

Ta komponenta spremlja spremembe dnevniških datotek na disku in posreduje informacije v LogStash. Nameščen na vseh strežnikih, kjer se pišejo dnevniške datoteke (običajno IIS). Deluje v repnem načinu (tj. v datoteko prenese samo dodane zapise). Lahko pa ga ločeno konfigurirate za prenos celotnih datotek. To je priročno, ko morate prenesti podatke za prejšnje mesece. Preprosto shranite dnevniško datoteko v mapo in prebrala jo bo v celoti.

Ko se storitev ustavi, se podatki nehajo prenašati naprej v shrambo.

Primer konfiguracije izgleda takole:

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. Zbiralec dnevnikov

Ta komponenta je zasnovana tako, da sprejema zapise dnevnika iz FileBeata (ali prek čakalne vrste RabbitMQ), jih razčlenjuje in v paketih vstavlja v bazo podatkov ClickHouse.

Za vstavljanje v ClickHouse uporabite vtičnik Logstash-output-clickhouse. Vtičnik Logstash ima mehanizem za ponovno sledenje zahtevam, vendar je med rednim izklopom bolje ustaviti samo storitev. Ko so ustavljena, se bodo sporočila kopičila v čakalni vrsti RabbitMQ, tako da če je ustavitev daljša, je bolje, da Filebeats zaustavite na strežnikih. V shemi, kjer RabbitMQ ni uporabljen (v lokalnem omrežju Filebeat neposredno pošilja dnevnike v Logstash), Filebeati delujejo dokaj sprejemljivo in varno, zato zanje nedostopnost izpisa nima posledic.

Primer konfiguracije izgleda takole:

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

cevovodi.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. Shranjevanje dnevnika

Dnevniki za vse sisteme so shranjeni v eni tabeli (glej na začetku članka). Zasnovan je za shranjevanje informacij o zahtevah: vsi parametri so podobni za različne formate, na primer dnevnike IIS, dnevnike apache in nginx. Za dnevnike aplikacij, v katere se beležijo npr. napake, informativna sporočila, opozorila, bo ločena tabela z ustrezno strukturo (trenutno v fazi projektiranja).

Pri oblikovanju tabele je zelo pomembna odločitev o primarnem ključu (po katerem bodo razvrščeni podatki med shranjevanjem). Od tega je odvisna stopnja stiskanja podatkov in hitrost poizvedb. V našem primeru je ključno
ORDER BY (fld_app_name, fld_app_module, logdatetime)
To je po imenu sistema, imenu sistemske komponente in datumu dogodka. Sprva je bil na prvem mestu datum dogodka. Po prestavitvi na zadnje mesto so poizvedbe začele delovati približno dvakrat hitreje. Spreminjanje primarnega ključa bo zahtevalo ponovno ustvarjanje tabele in ponovno nalaganje podatkov, tako da bo ClickHouse ponovno razvrstil podatke na disku. To je težka operacija, zato je priporočljivo vnaprej dobro premisliti, kaj naj bo vključeno v ključ za razvrščanje.

Prav tako je treba opozoriti, da se je podatkovni tip LowCardinality pojavil v relativno nedavnih različicah. Pri njegovi uporabi se velikost stisnjenih podatkov močno zmanjša za tista polja, ki imajo nizko kardinalnost (malo možnosti).

Trenutno uporabljamo različico 19.6 in nameravamo poskusiti posodobiti na najnovejšo različico. Imajo tako čudovite lastnosti, kot so na primer prilagodljiva zrnatost, preskakovanje indeksov in kodek DoubleDelta.

Privzeto je med namestitvijo raven beleženja konfiguracije nastavljena na sledenje. Dnevniki se rotirajo in arhivirajo, hkrati pa se širijo do gigabajta. Če ni potrebe, lahko nastavite raven na opozorilo, nato pa se bo velikost dnevnika močno zmanjšala. Nastavitve beleženja so določene v datoteki config.xml:

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

Nekaj ​​uporabnih ukazov

Поскольку оригинальные пакеты установки собираются по 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. Zabeleži usmerjevalnik iz FileBeat v čakalno vrsto RabbitMQ

Ta komponenta se uporablja za usmerjanje dnevnikov, ki prihajajo iz FileBeat, v čakalno vrsto RabbitMQ. Tukaj sta dve točki:

  1. Na žalost FileBeat nima izhodnega vtičnika za neposredno pisanje v RabbitMQ. In takšna funkcionalnost, sodeč po objavi na njihovem githubu, ni predvidena za implementacijo. Obstaja vtičnik za Kafko, vendar ga iz določenih razlogov ne moremo uporabljati sami.
  2. V DMZ obstajajo zahteve za zbiranje hlodov. Na podlagi njih je treba dnevnike najprej postaviti v čakalno vrsto, nato pa LogStash prebere zapise iz čakalne vrste navzven.

Zato je treba posebej za primer strežnikov, ki se nahajajo v DMZ, uporabiti tako nekoliko zapleteno shemo. Primer konfiguracije izgleda takole:

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. Čakalna vrsta sporočil

Ta komponenta se uporablja za medpomnjenje dnevniških vnosov v DMZ. Snemanje poteka prek povezave Filebeat → LogStash. Branje poteka zunaj DMZ preko LogStash. Pri delovanju prek RabbitMQ se obdela približno 4 tisoč sporočil na sekundo.

Usmerjanje sporočil je konfigurirano z imenom sistema, tj. na podlagi konfiguracijskih podatkov FileBeat. Vsa sporočila gredo v eno čakalno vrsto. Če se iz nekega razloga storitev čakalne vrste ustavi, to ne bo povzročilo izgube sporočila: FileBeats bo prejel napake pri povezavi in ​​bo začasno ustavil pošiljanje. In LogStash, ki bere iz čakalne vrste, bo prav tako prejel omrežne napake in čakal, da se povezava obnovi. V tem primeru se podatki seveda ne bodo več zapisovali v bazo.

Za ustvarjanje in konfiguriranje čakalnih vrst se uporabljajo naslednja navodila:

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

Ta komponenta se uporablja za vizualizacijo podatkov spremljanja. V tem primeru morate namestiti vir podatkov ClickHouse za vtičnik Grafana 4.6+. Morali smo ga nekoliko spremeniti, da bi izboljšali učinkovitost obdelave filtrov SQL na nadzorni plošči.

Na primer, uporabljamo spremenljivke in če niso podane v polju filtra, potem želimo, da ne ustvari pogoja v WHERE obrazca ( uriStem = "AND uriStem != "). V tem primeru bo ClickHouse prebral stolpec uriStem. Tako smo preizkusili različne možnosti in končno popravili vtičnik (makro $valueIfEmpty), da vrne 1 v primeru prazne vrednosti, ne da bi omenil sam stolpec.

Zdaj lahko to poizvedbo uporabite za graf

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

ki se pretvori v SQL takole (upoštevajte, da so prazna polja uriStem pretvorjena v 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ček

Pojav baze podatkov ClickHouse je postal prelomni dogodek na trgu. Težko si je predstavljati, da smo v trenutku, popolnoma brezplačno, oboroženi z zmogljivim in praktičnim orodjem za delo z velikimi podatki. Seveda bo shema postala bolj zapletena, ko se bodo potrebe povečevale (na primer razdeljevanje in replikacija na več strežnikov). A po prvih vtisih je delo s to bazo zelo prijetno. Jasno je, da je izdelek narejen »za ljudi«.

V primerjavi z ElasticSearch se stroški shranjevanja in obdelave dnevnikov po predhodnih ocenah znižajo za pet do desetkrat. Z drugimi besedami, če bi morali za trenutno količino podatkov vzpostaviti gručo večih strojev, potem pri uporabi ClickHouse potrebujemo samo en nizkoenergijski stroj. Da, seveda ima ElasticSearch tudi mehanizme stiskanja podatkov na disku in druge funkcije, ki lahko znatno zmanjšajo porabo virov, vendar bo to v primerjavi s ClickHouse zahtevalo večje stroške.

Brez kakršnih koli posebnih optimizacij z naše strani, s privzetimi nastavitvami, nalaganje podatkov in pridobivanje podatkov iz baze deluje neverjetno hitro. Nimamo še veliko podatkov (približno 200 milijonov zapisov), sam strežnik pa je šibak. To orodje bomo morda v prihodnosti uporabljali za druge namene, ki niso povezani s shranjevanjem dnevnikov. Na primer za analitiko od konca do konca, na področju varnosti, strojnega učenja.

Na koncu še nekaj o prednostih in slabostih.

Proti

  1. Nalaganje zapisov v velikih serijah. Po eni strani je to funkcija, vendar morate še vedno uporabljati dodatne komponente za medpomnjenje zapisov. Ta naloga ni vedno enostavna, a vseeno rešljiva. In rad bi poenostavil shemo.
  2. Nekatere eksotične funkcije ali nove funkcije se v novih različicah pogosto pokvarijo. To vzbuja pomisleke in zmanjšuje željo po nadgradnji na novo različico. Na primer, mehanizem tabel Kafka je zelo uporabna funkcija, ki vam omogoča neposredno branje dogodkov iz Kafke, brez implementacije porabnikov. Toda sodeč po številu težav na Githubu smo še vedno previdni glede uporabe tega mehanizma v proizvodnji. Če pa ne delate nenadnih gibov vstran in uporabljate osnovno funkcionalnost, potem deluje stabilno.

Pros

  1. Ne upočasnjuje.
  2. Nizek prag vstopa.
  3. Odprtokodno.
  4. Prost.
  5. Razširljivo (sharding/replikacija izven škatle)
  6. Vključeno v register ruske programske opreme, ki jo priporoča Ministrstvo za komunikacije.
  7. Razpoložljivost uradne podpore Yandex.

Vir: www.habr.com

Dodaj komentar