ClickHouse baza podataka za ljude, ili Alien Technologies

Aleksej Lizunov, rukovodilac Centra kompetencija za kanale daljinskog servisa Direkcije za informacione tehnologije MKB-a

ClickHouse baza podataka za ljude, ili Alien Technologies

Kao alternativu ELK steku (ElasticSearch, Logstash, Kibana), radimo istraživanje o korišćenju ClickHouse baze podataka kao skladišta podataka za logove.

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


ClickHouse baza podataka za ljude, ili Alien Technologies

Zatim ćemo detaljnije opisati kako je naš sistem konfigurisan i od kojih komponenti se sastoji. Ali sada bih želio malo govoriti o ovoj bazi podataka u cjelini i zašto je vrijedno obratiti pažnju. ClickHouse baza podataka je analitička stubna baza podataka visokih performansi iz Yandexa. Koristi se u Yandex servisima, u početku je to glavno skladište podataka za Yandex.Metrica. Sistem otvorenog koda, besplatan. Sa stanovišta programera, uvijek sam se pitao kako su to implementirali, jer postoje fantastično veliki podaci. I sam korisnički interfejs Metrice je veoma fleksibilan i brz. Prilikom prvog upoznavanja sa ovom bazom podataka, utisak je: „Pa, konačno! Stvoreno za ljude! Počevši od procesa instalacije i završavajući slanjem zahtjeva.

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

O našem sistemu evidentiranja

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

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

Opća šema evidentiranja prikazana je na donjoj slici:

ClickHouse baza podataka za ljude, ili Alien Technologies

Karakteristika pisanja podataka u ClickHouse bazu podataka je rijetko (jednom u sekundi) umetanje zapisa u velikim serijama. Ovo je, očigledno, najproblematičniji dio s kojim se susrećete kada prvi put iskusite rad s ClickHouse bazom podataka: shema postaje malo složenija.
Tu je mnogo pomogao dodatak za LogStash, koji direktno ubacuje podatke u ClickHouse. Ova komponenta je raspoređena na istom serveru kao i sama baza podataka. Dakle, generalno gledano, nije preporučljivo to raditi, ali sa praktične tačke gledišta, kako se ne bi proizvodili odvojeni serveri dok je raspoređen na istom serveru. Nismo uočili nikakve greške ili sukobe resursa s bazom podataka. Osim toga, treba napomenuti da dodatak ima mehanizam za ponovni pokušaj u slučaju grešaka. A u slučaju grešaka, dodatak zapisuje na disk seriju podataka koji se ne mogu umetnuti (format datoteke je zgodan: nakon uređivanja možete lako umetnuti ispravljenu seriju koristeći clickhouse-client).

Kompletna lista softvera koji se koristi u shemi prikazana je u tabeli:

Lista korištenog softvera

Naslov

Opis

Veza za distribuciju

NGINX

Reverse-proxy za ograničavanje pristupa po 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 evidencije datoteka.

https://www.elastic.co/downloads/beats/filebeat (distributivni 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 dnevnika iz FileBeat-a, kao i za prikupljanje dnevnika iz reda RabbitMQ (za servere koji se nalaze u DMZ-u.)

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

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

Logstash-output-clickhouse

Loagstash dodatak za prijenos logova u ClickHouse bazu podataka u serijama

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

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

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

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

clickhouse

Skladištenje 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 avgusta 2018., „normalne“ verzije rpm za RHEL pojavile su se u Yandex repozitorijumu, tako da možete pokušati da ih koristite. U vrijeme instalacije koristili smo pakete koje je napravio Altinity.

grafana

Vizualizacija dnevnika. Postavljanje kontrolne table

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos(64 Bit) - najnovija verzija

ClickHouse izvor podataka za Grafana 4.6+

Dodatak za Grafanu sa ClickHouse izvorom podataka

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

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

logstash

Ruter dnevnika od FileBeat do RabbitMQ reda.

Bilješka. Nažalost FileBeat ne izlazi direktno na RabbitMQ, tako da je potrebna posredna veza u obliku Logstash-a

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

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

Rabbit MQ

red poruka. Ovo je bafer 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. Potrebno za RabbitMQ za rad

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

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

Konfiguracija servera s ClickHouse bazom podataka prikazana je u sljedećoj tabeli:

Naslov

vrijednost

primjedba

Konfiguracija

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

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

Opšti sistemski softver

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

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

Struktura tabele 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 podrazumevano particionisanje (po mesecima) i granularnost indeksa. Sva polja praktično odgovaraju IIS log unosima za evidentiranje http zahtjeva. Odvojeno, napominjemo da postoje odvojena polja za pohranjivanje utm-tagova (ona se raščlanjuju u fazi umetanja u tabelu iz polja stringa upita).

Takođe, nekoliko sistemskih polja je dodato u tabelu za skladištenje informacija o sistemima, komponentama, serverima. Pogledajte donju tabelu za opis ovih polja. U jednoj tabeli čuvamo evidencije za nekoliko sistema.

Naslov

Opis

Primjer:

fld_app_name

Naziv aplikacije/sistema
Važeće vrijednosti:

  • site1.domain.com Eksterna lokacija 1
  • site2.domain.com Eksterna lokacija 2
  • interna-stranica1.domain.local Interna stranica 1

site1.domain.com

fld_app_module

Sistemski modul
Važeće vrijednosti:

  • web - Web stranica
  • svc - Usluga web stranice
  • intgr - Web servis integracije
  • bo - Admin (BackOffice)

veb

fld_website_name

Naziv lokacije u IIS-u

Nekoliko sistema može biti raspoređeno na jednom serveru, ili čak nekoliko instanci jednog sistemskog modula

web main

fld_server_name

Ime servera

web1.domain.com

fld_log_file_name

Putanja do datoteke evidencije na serveru

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

Ovo vam omogućava da efikasno gradite grafikone u Grafani. Na primjer, pogledajte zahtjeve sa frontenda određenog sistema. Ovo je slično brojaču stranice u Yandex.Metrici.

Evo neke statistike o korištenju baze podataka za dva mjeseca.

Broj zapisa raščlanjenih po sistemima 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.

Stepen kompresije podataka u kolonama

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 evidencije datoteka

Ova komponenta prati promjene u datotekama evidencije na disku i prosljeđuje informacije u LogStash. Instaliran na svim serverima na kojima se pišu log fajlovi (obično IIS). Radi u rep modu (tj. prenosi samo dodane zapise u datoteku). Ali odvojeno se može konfigurirati za prijenos cijelih datoteka. Ovo je korisno kada trebate preuzeti podatke iz prethodnih mjeseci. Samo stavite datoteku dnevnika u mapu i ona će je pročitati u cijelosti.

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

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č trupaca

Ova komponenta je dizajnirana da prima unose dnevnika iz FileBeat-a (ili preko reda RabbitMQ), analizira i ubacuje grupe u ClickHouse bazu podataka.

Za umetanje u ClickHouse koristi se dodatak Logstash-output-clickhouse. Dodatak Logstash ima mehanizam za ponovni pokušaj, ali uz redovno gašenje, bolje je zaustaviti samu uslugu. Kada se zaustavi, poruke će se akumulirati u RabbitMQ redu, tako da ako je zaustavljanje na duže vrijeme, onda je bolje zaustaviti Filebeats na serverima. U šemi u kojoj se RabbitMQ ne koristi (na lokalnoj mreži Filebeat direktno šalje logove u Logstash), Filebeats rade sasvim prihvatljivo i sigurno, tako da 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"
        }
    }
 
}

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. Skladištenje dnevnika

Dnevnici za sve sisteme su pohranjeni u jednoj tabeli (pogledajte na početku članka). Namijenjen je za pohranjivanje informacija o zahtjevima: svi parametri su slični za različite formate, kao što su IIS logovi, apache i nginx dnevniki. Za dnevnike aplikacija, u kojima se, na primjer, evidentiraju greške, informativne poruke, upozorenja, bit će osigurana posebna tabela s odgovarajućom strukturom (trenutno u fazi dizajna).

Prilikom dizajniranja tabele veoma je važno odlučiti se za primarni ključ (po kojem će se podaci sortirati tokom skladištenja). Stepen kompresije podataka i brzina upita zavise od toga. U našem primjeru, ključ je
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Odnosno, po imenu sistema, imenu komponente sistema i datumu događaja. U početku je datum događaja bio prvi. Nakon premještanja na posljednje mjesto, upiti su počeli raditi otprilike dvostruko brže. Promjena primarnog ključa će zahtijevati ponovno kreiranje tablice i ponovno učitavanje podataka tako da ClickHouse ponovo sortira podatke na disku. Ovo je teška operacija, pa je dobra ideja mnogo razmišljati o tome šta bi trebalo uključiti u ključ za sortiranje.

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

Verzija 19.6 je trenutno u upotrebi i planiramo da pokušamo ažurirati na najnoviju verziju. Imaju tako divne karakteristike kao što su prilagodljiva granularnost, indeksi preskakanja i DoubleDelta kodek, na primjer.

Podrazumevano, tokom instalacije, nivo evidentiranja je postavljen na praćenje. Dnevnici se rotiraju i arhiviraju, ali se u isto vrijeme proširuju do gigabajta. Ako nema potrebe, tada možete postaviti nivo upozorenja, tada se veličina dnevnika drastično smanjuje. Postavka evidentiranja je postavljena u datoteci config.xml:

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

Neke korisne komande

Поскольку оригинальные пакеты установки собираются по 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. Ruter dnevnika od FileBeat do RabbitMQ reda

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

  1. Nažalost, FileBeat nema izlazni dodatak za pisanje direktno u RabbitMQ. A takva funkcionalnost, sudeći po izdanju 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-u. Na osnovu njih, evidencije se prvo moraju dodati u red, a zatim LogStash čita unose iz reda izvana.

Stoga je u slučaju kada se serveri nalaze u DMZ-u potrebno koristiti ovako malo komplikovanu šemu. 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 komponenta se koristi za baferovanje unosa dnevnika u DMZ. Snimanje se vrši preko gomile Filebeat → LogStash. Čitanje se vrši izvan DMZ-a preko LogStash-a. Kada se radi preko RabboitMQ-a, obrađuje se oko 4 hiljade poruka u sekundi.

Usmjeravanje poruka je konfigurirano po imenu sistema, tj. na osnovu FileBeat konfiguracijskih podataka. Sve poruke idu u jedan red čekanja. Ako je iz nekog razloga usluga čekanja zaustavljena, to neće dovesti do gubitka poruka: FileBeats će primiti greške u vezi i privremeno obustaviti slanje. I LogStash koji čita iz reda će također primati mrežne greške i čekati da se veza vrati. U tom slučaju podaci, naravno, više neće biti upisani u bazu podataka.

Sljedeća uputstva se koriste za kreiranje i konfiguraciju redova čekanja:

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

Ova komponenta se koristi za vizualizaciju podataka praćenja. U ovom slučaju, morate instalirati ClickHouse izvor podataka za Grafana 4.6+ dodatak. Morali smo ga malo podesiti da poboljšamo efikasnost obrade SQL filtera na kontrolnoj tabli.

Na primjer, koristimo varijable, a ako nisu postavljene u polju filtera, željeli bismo da ne generiše uslov u WHERE obrasca ( uriStem = » AND uriStem != » ). U ovom slučaju, ClickHouse će pročitati kolonu uriStem. Općenito, isprobali smo različite opcije i na kraju ispravili dodatak (makro $valueIfEmpty) tako da u slučaju prazne vrijednosti vraća 1, bez pominjanja same kolone.

I sada možete koristiti ovaj upit 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')

što se prevodi u ovaj SQL (imajte na umu da su prazna polja uriStem 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 ClickHouse baze podataka postala je značajan događaj na tržištu. Bilo je teško zamisliti da smo, potpuno besplatno, u trenu bili naoružani moćnim i praktičnim alatom za rad s velikim podacima. Naravno, sa povećanjem potreba (na primjer, sharding i replikacija na više servera), shema će postati složenija. Ali na prvi utisak, rad sa ovom bazom podataka je veoma prijatan. Vidi se da je proizvod napravljen "za ljude".

U poređenju sa ElasticSearch-om, procjenjuje se da će troškovi skladištenja i obrade dnevnika biti smanjeni za pet do deset puta. Drugim riječima, ako bismo za trenutnu količinu podataka morali postaviti klaster od nekoliko mašina, onda nam je, kada koristimo ClickHouse, dovoljna jedna mašina 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 poređenju sa ClickHouse, ovo će biti skuplje.

Bez ikakvih posebnih optimizacija s naše strane, na zadanim postavkama, učitavanje podataka i odabir iz baze podataka radi neverovatnom brzinom. Još nemamo mnogo podataka (oko 200 miliona zapisa), ali sam server je slab. Ovaj alat možemo koristiti u budućnosti u druge svrhe koje nisu vezane za pohranjivanje dnevnika. Na primjer, za end-to-end analitiku, u području sigurnosti, mašinsko učenje.

Na kraju, malo o prednostima i nedostacima.

Minusy

  1. Učitavanje zapisa u velikim serijama. S jedne strane, ovo je karakteristika, ali i dalje morate koristiti dodatne komponente za baferovanje zapisa. Ovaj zadatak nije uvijek lak, ali ipak rješiv. I želio bih pojednostaviti shemu.
  2. Neke egzotične funkcionalnosti ili nove funkcije često se prekidaju u novim verzijama. To izaziva zabrinutost, smanjujući želju za nadogradnjom na novu verziju. Na primjer, mašina za tablice Kafka je vrlo korisna karakteristika koja vam omogućava da direktno čitate događaje iz Kafke, bez implementacije potrošača. Ali sudeći po broju izdanja na githubu, i dalje pazimo da ovaj motor ne koristimo u proizvodnji. Međutim, ako ne napravite iznenadne pokrete u stranu i ne koristite glavnu funkcionalnost, tada radi stabilno.

Plûsy

  1. Ne usporava.
  2. Nizak ulazni prag.
  3. Otvorenog koda.
  4. Besplatno.
  5. Dobro se skalira (sharding/replikacija izvan kutije)
  6. Uključen u registar ruskog softvera koji je preporučilo Ministarstvo komunikacija.
  7. Prisustvo službene podrške Yandexa.

izvor: www.habr.com

Dodajte komentar