ClickHouse-database for folk, eller teknologier fra rummet

Alexey Lizunov, leder af kompetencecentret for fjernkanaler i it-direktoratet hos MKB

ClickHouse-database for folk, eller teknologier fra rummet

Som et alternativ til ELK-stakken (ElasticSearch, Logstash, Kibana) udfþrer vi forskningsarbejde om anvendelsen af ​​ClickHouse-database som et datalager til logs.

I denne artikel vil vi gerne dele vores erfaringer med at bruge ClickHouse-database og de forelĂžbige resultater fra pilotdriften. Det bĂžr nĂŠvnes straks, at resultaterne har vĂŠret imponerende.


ClickHouse-database for folk, eller teknologier fra rummet

Vi vil yderligere beskrive, hvordan vores system er konfigureret, og hvilke komponenter det bestÄr af. Men lige nu vil vi gerne tale lidt om denne database generelt, og hvorfor den er vÊrd at overveje. ClickHouse-database er en hÞjtydende kolonneorienteret database fra Yandex. Den bruges i Yandex-tjenesterne, og den var oprindeligt det primÊre datalager for Yandex.Metrica. Systemet er open-source og gratis. Fra en udviklers synspunkt har jeg altid vÊret interesseret i, hvordan de har implementeret det, da de har fantastiske store data. Og selve brugergrÊnsefladen i Metrica er meget fleksibel og fungerer hurtigt. Ved fÞrste mÞde med denne database er indtrykket: 'NÄ, endelig! Lavet 'til mennesker'! Fra installationsprocessen til sending af forespÞrgsler.

Denne database har en meget lav indgangsbarriere. Selv en mellemklasseudvikler kan pĂ„ fĂ„ minutter installere denne database og begynde at bruge den. Alt fungerer prĂŠcist. Selv folk, der er dĂ„rligt bekendt med Linux, kan hurtigt klare installationen og udfĂžre de enkleste operationer. Tidligere, nĂ„r ordet Big Data nĂŠvntes, havde almindelige udviklere ofte forestillinger om, at det handlede om terabyte, petabyte, at opsĂŠtningen og udviklingen til disse systemer blev udfĂžrt af supermennesker, men med fremkomsten af ​​ClickHouse-database har vi fĂ„et et simpelt, forstĂ„eligt vĂŠrktĂžj, der gĂžr det muligt at lĂžse tidligere uopnĂ„elige opgaver. Man skal blot have en rimeligt gennemsnitlig maskine og fem minutter til installation. Det vil sige, vi har fĂ„et en database som eksempelvis MySql, men kun til opbevaring af milliarder af poster! En slags superkomprimator med SQL-sprog. Det er som om, at mennesker er blevet givet et rumvĂŠsens vĂ„ben.

Om vores logindsamlingssystem

For collecting information, standard format IIS web application log files are used (we are also currently working on parsing application logs, but our main goal at the pilot stage is to collect IIS logs).

We have not completely abandoned the ELK stack for various reasons, and we continue to use the LogStash and Filebeat components, which have proven reliable and work quite predictably.

The overall logging scheme is presented in the figure below:

ClickHouse-database for folk, eller teknologier fra rummet

A feature of writing data to the ClickHouse DB is infrequent (once per second) batch inserts. This seems to be the most 'problematic' part encountered when working with ClickHouse for the first time: the scheme becomes slightly more complicated.
The LogStash plugin, which inserts data directly into ClickHouse, helped significantly here. This component is deployed on the same server as the DB itself. Generally, this is not recommended, but from a practical point of view, to avoid creating separate servers, it is currently deployed on the same server. We have not observed any failures or resource conflicts with the DB. It is also worth noting that the plugin has a retry mechanism in case of errors. In case of errors, the plugin writes a batch of data that could not be inserted to disk (the file format is convenient: after editing, the corrected batch can be easily inserted using clickhouse-client).

The full list of software used in the scheme is presented in the table:

List of software used

Navn

Description

Link to the distribution

NGINX

Reverse-proxy to restrict access by ports and organize authentication

Currently not used in the scheme

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

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

FileBeat

File log transfer.

https://www.elastic.co/downloads/beats/filebeat (distribution for Windows 64bit).

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

LogStash

Log collector.

Used to collect logs from FileBeat, as well as to collect logs from the RabbitMQ queue (for servers located in the DMZ).

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

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

Logstash-output-clickhouse

Logstash plugin for batch sending logs to the ClickHouse DB

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 install logstash-filter-multiline

ClickHouse

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

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

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

Note. Starting from August 2018, 'normal' rpm builds for RHEL appeared in the Yandex repository, so they can be tried. At the time of installation, we used packages built by Altinity.

Grafana

Log visualization. Dashboard setup

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 Bit) – the latest version

ClickHouse datasource for Grafana 4.6+

Grafana plugin with ClickHouse data source

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

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

LogStash

Logrouteren fra FileBeat til RabbitMQ-kĂž.

BemÊrk. DesvÊrre har FileBeat ikke output direkte til RabbitMQ, sÄ der krÊves et mellemliggende link i form af Logstash.

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

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

RabbitMQ

MeddelelseskĂž. Dette er en buffer af logposter i 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 (NĂždvendig for RabbitMQ).

Erlang-kĂžrselsmiljĂž. KrĂŠves for at kĂžre RabbitMQ.

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

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

Serverkonfigurationen med ClickHouse-database er prĂŠsenteret i fĂžlgende tabel:

Navn

VĂŠrdi

BemĂŠrk

Konfiguration

HDD: 40GB.
RAM: 8GB.
Processor: Core 2 2Ghz.

Det er vigtigt at vÊre opmÊrksom pÄ rÄd om brugen af ClickHouse-databasen (https://clickhouse.yandex/docs/ru/operations/tips/)

Generelt systemsoftware.

OS: Red Hat Enterprise Linux Server (Maipo).

JRE (Java 8).

 

Som det fremgÄr, er dette en almindelig arbejdsstation.

Strukturen af tabellen til opbevaring af logs ser sÄledes ud:

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;

Vi bruger standardvÊrdier for partitionering (mÄnedligt) og indeksgranularitet. Alle felter svarer nÊsten til logposter fra IIS til registrering af http-forespÞrgsler. Vi bemÊrker specielt de separate felter til opbevaring af UTM-tags (de parses under indsÊttelse i tabellen fra forespÞrgselsstrengens felt).

I tabellen er der ogsÄ tilfÞjet flere systemfelter til opbevaring af information om systemer, komponenter og servere. Beskrivelsen af disse felter findes nedenfor i tabellen. I én tabel opbevarer vi logs fra flere systemer.

Navn

Description

Eksempel

fld_app_name.

Navnet pÄ applikationen/systemet.
Tilladte vĂŠrdier:

  • site1.domain.com Ekstern hjemmeside 1.
  • site2.domain.com Ekstern hjemmeside 2.
  • internal-site1.domain.local Intern hjemmeside 1.

site1.domain.com.

fld_app_module.

Systemmodul.
Tilladte vĂŠrdier:

  • web — Hjemmeside.
  • svc — Webservice for hjemmesiden.
  • intgr — Integrationswebservice.
  • bo — Admin (BackOffice).

web

fld_website_name.

Navnet pÄ hjemmesiden i IIS.

PÄ én server kan der vÊre implementeret flere systemer, eller endda flere instanser af én systems modul.

web-main.

fld_server_name.

Servernavn

web1.domain.com.

fld_log_file_name.

Stien til logfilen pÄ serveren.

C:inetpublogsLogFiles.
W3SVC1u_ex190711.log.

Dette giver mulighed for effektivt at opbygge grafer i Grafana. For eksempel at se anmodninger fra frontend af et specifikt system. Det ligner en besĂžgsstatistik i Yandex.Metrica.

Her er nogle statistikker om DB-brug over de sidste to mÄneder.

Antallet af poster opdelt efter systemer og deres komponenter

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

Data volume pÄ disken

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.

Graden af komprimering af data i kolonner

VÆLG
    navn,
    formatérLÊsbarStÞrrelse(data_uncompressed_bytes) SOM ukomprimeret,
    formatérLÊsbarStÞrrelse(data_compressed_bytes) SOM komprimeret,
    data_uncompressed_bytes / data_compressed_bytes SOM komprimeringsforhold
FRA system.columns
HVOR tabel = 'log_web'
 
┌─navn───────────────────┬─ukomprimeret─┬─komprimeret─┬─────komprimeringsforhold─┐
│ logdato                │ 401,53 MiB   │ 1,80 MiB   │ 223,16665968777315 │
│ logdato_tid            │ 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 │
│ metode                 │ 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 │
│ brugernavn             │ 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 │
│ respons               │ 803,06 MiB   │ 83,81 MiB  │  9,582334090987247 │
│ subrespons            │ 399,87 MiB   │ 1,83 MiB   │  218,4831068635027 │
│ win32respons          │ 407,86 MiB   │ 7,41 MiB   │ 55,050315514606815 │
│ tid_brugt              │ 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 rĂŠkker i sĂŠttet. ForlĂžbet: 0,005 sek.

Beskrivelse af anvendte komponenter

FileBeat. OverfĂžrsel af fil-logging

Denne komponent overvÄger Êndringer i logfiler pÄ disken og videresender information til LogStash. Den installeres pÄ alle servere, hvor der skrives logfiler (normalt IIS). Den fungerer i tail-tilstand (dvs. sender kun de tilfÞjede poster til filen). Men den kan ogsÄ indstilles til at overfÞre filerne i sin helhed. Dette er praktisk, nÄr man skal uploade data fra de foregÄende mÄneder. LÊg blot logfilen i mappen, og den lÊser den helt selv.

NÄr tjenesten stoppes, stopper dataerne med at blive overfÞrt til lagringen.

Eksemplet pÄ konfiguration ser sÄledes ud:

filebeat.yml

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - C:/inetpub/logs/LogFiles/W3SVC1/*.log
  exclude_files: ['.gz$','.zip$']
  tail_files: true
  ignore_older: 24h
  fields:
    fld_server_name: "site1.domain.ru"
    fld_app_name: "site1.domain.ru"
    fld_app_module: "web"
    fld_website_name: "web-main"
 
- type: log
  enabled: true
  paths:
    - C:/inetpub/logs/LogFiles/__Import/access_log-*
  exclude_files: ['.gz$','.zip$']
  tail_files: false
  fields:
    fld_server_name: "site2.domain.ru"
    fld_app_name: "site2.domain.ru"
    fld_app_module: "web"
    fld_website_name: "web-main"
    fld_logformat: "logformat__apache"
 
 
filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false
  reload.period: 2s
 
output.logstash:
  hosts: ["log.domain.com:5044"]
 
  ssl.enabled: true
  ssl.certificate_authorities: ["C:/filebeat/certs/ca.pem", "C:/filebeat/certs/ca-issuing.pem"]
  ssl.certificate: "C:/filebeat/certs/site1.domain.ru.cer"
  ssl.key: "C:/filebeat/certs/site1.domain.ru.key"
 
#================================ Processors =====================================
 
processors:
  - add_host_metadata: ~
  - add_cloud_metadata: ~

LogStash. Log-samler

Denne komponent er designet til at modtage logoptegnelser fra FileBeat (enten via en RabbitMQ-kĂž) og parse dem og indsĂŠtte dem i batches i ClickHouse.

Til indsÊttelse i ClickHouse bruges Logstash-output-clickhouse-plugin. Logstash har en mekanisme til at genprÞve forespÞrgsler, men ved en normal stoppet, er det bedre at stoppe selve tjenesten. Ved stoppet vil der ophobes beskeder i RabbitMQ-kÞen, sÄ hvis stoppet strÊkker sig over lÊngere tid, er det bedst at stoppe Filebeat'erne pÄ serverne. I et setup, hvor RabbitMQ ikke bruges (i det lokale netvÊrk sender Filebeat loggene direkte til Logstash), fungerer Filebeat'erne tilfredsstillende og sikkert, sÄ for dem vil output-manglende ikke have konsekvenser.

Eksemplet pÄ konfiguration ser sÄledes ud:

log_web__filebeat_clickhouse.conf

input {
 
    beats {
        port => 5044
        type => 'iis'
        ssl => true
        ssl_certificate_authorities => ["/etc/logstash/certs/ca.cer", "/etc/logstash/certs/ca-issuing.cer"]
        ssl_certificate => "/etc/logstash/certs/server.cer"
        ssl_key => "/etc/logstash/certs/server-pkcs8.key"
        ssl_verify_mode => "peer"
 
            add_field => {
                "fld_server_name" => "%{[fields][fld_server_name]}"
                "fld_app_name" => "%{[fields][fld_app_name]}"
                "fld_app_module" => "%{[fields][fld_app_module]}"
                "fld_website_name" => "%{[fields][fld_website_name]}"
                "fld_log_file_name" => "%{source}"
                "fld_logformat" => "%{[fields][fld_logformat]}"
            }
    }
 
    rabbitmq {
        host => "queue.domain.com"
        port => 5671
        user => "q-reader"
        password => "password"
        queue => "web_log"
        heartbeat => 30
        durable => true
        ssl => true
        #ssl_certificate_path => "/etc/logstash/certs/server.p12"
        #ssl_certificate_password => "password"
 
        add_field => {
            "fld_server_name" => "%{[fields][fld_server_name]}"
            "fld_app_name" => "%{[fields][fld_app_name]}"
            "fld_app_module" => "%{[fields][fld_app_module]}"
            "fld_website_name" => "%{[fields][fld_website_name]}"
            "fld_log_file_name" => "%{source}"
            "fld_logformat" => "%{[fields][fld_logformat]}"
        }
    }
 
}
 
filter { 
 
      if [message] =~ "^#" {
        drop {}
      }
 
      if [fld_logformat] == "logformat__iis_with_xrealip" {
     
          grok {
            match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{IP:serverIP} %{WORD:method} %{NOTSPACE:uriStem} %{NOTSPACE:uriQuery} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:clientIP} %{NOTSPACE:userAgent} %{NOTSPACE:referer} %{NUMBER:response} %{NUMBER:subresponse} %{NUMBER:win32response} %{NUMBER:timetaken} %{NOTSPACE:xrealIP} %{NOTSPACE:xforwarderfor}"]
          }
      } else {
   
          grok {
             match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{IP:serverIP} %{WORD:method} %{NOTSPACE:uriStem} %{NOTSPACE:uriQuery} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:clientIP} %{NOTSPACE:userAgent} %{NOTSPACE:referer} %{NUMBER:response} %{NUMBER:subresponse} %{NUMBER:win32response} %{NUMBER:timetaken}"]
          }
 
      }
 
      date {
        match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss" ]
          timezone => "Etc/UTC"
        remove_field => [ "log_timestamp", "@timestamp" ]
        target => [ "log_timestamp2" ]
      }
 
        ruby {
            code => "tstamp = event.get('log_timestamp2').to_i
                        event.set('logdatetime', Time.at(tstamp).strftime('%Y-%m-%d %H:%M:%S'))
                        event.set('logdate', Time.at(tstamp).strftime('%Y-%m-%d'))"
        }
 
      if [bytesSent] {
        ruby {
          code => "event['kilobytesSent'] = event['bytesSent'].to_i / 1024.0"
        }
      }
 
 
      if [bytesReceived] {
        ruby {
          code => "event['kilobytesReceived'] = event['bytesReceived'].to_i / 1024.0"
        }
      }
 
   
        ruby {
            code => "event.set('clientRealIP', event.get('clientIP'))"
        }
        if [xrealIP] {
            ruby {
                code => "event.set('clientRealIP', event.get('xrealIP'))"
            }
        }
        if [xforwarderfor] {
            ruby {
                code => "event.set('clientRealIP', event.get('xforwarderfor'))"
            }
        }
 
      mutate {
        convert => ["bytesSent", "integer"]
        convert => ["bytesReceived", "integer"]
        convert => ["timetaken", "integer"] 
        convert => ["port", "integer"]
 
        add_field => {
            "clientHostname" => "%{clientIP}"
        }
      }
 
        useragent {
            source=> "useragent"
            prefix=> "browser"
        }
 
        kv {
            source => "uriQuery"
            prefix => "uriQuery__"
            allow_duplicate_values => false
            field_split => "&"
            include_keys => [ "utm_medium", "utm_source", "utm_campaign", "utm_term", "utm_content", "yclid", "region" ]
        }
 
        mutate {
            join => { "uriQuery__utm_source" => "," }
            join => { "uriQuery__utm_medium" => "," }
            join => { "uriQuery__utm_campaign" => "," }
            join => { "uriQuery__utm_term" => "," }
            join => { "uriQuery__utm_content" => "," }
            join => { "uriQuery__yclid" => "," }
            join => { "uriQuery__region" => "," }
        }
 
}
 
output { 
  #stdout {codec => rubydebug}
    clickhouse {
      headers => ["Authorization", "Basic abcdsfks..."]
      http_hosts => ["http://127.0.0.1:8123"]
      save_dir => "/etc/logstash/tmp"
      table => "log_web"
      request_tolerance => 1
      flush_size => 10000
      idle_flush_time => 1
        mutations => {
            "fld_log_file_name" => "fld_log_file_name"
            "fld_server_name" => "fld_server_name"
            "fld_app_name" => "fld_app_name"
            "fld_app_module" => "fld_app_module"
            "fld_website_name" => "fld_website_name"
 
            "logdatetime" => "logdatetime"
            "logdate" => "logdate"
            "serverIP" => "serverIP"
            "method" => "method"
            "uriStem" => "uriStem"
            "uriQuery" => "uriQuery"
            "port" => "port"
            "username" => "username"
            "clientIP" => "clientIP"
            "clientRealIP" => "clientRealIP"
            "userAgent" => "userAgent"
            "referer" => "referer"
            "response" => "response"
            "subresponse" => "subresponse"
            "win32response" => "win32response"
            "timetaken" => "timetaken"
             
            "uriQuery__utm_medium" => "uriQuery__utm_medium"
            "uriQuery__utm_source" => "uriQuery__utm_source"
            "uriQuery__utm_campaign" => "uriQuery__utm_campaign"
            "uriQuery__utm_term" => "uriQuery__utm_term"
            "uriQuery__utm_content" => "uriQuery__utm_content"
            "uriQuery__yclid" => "uriQuery__yclid"
            "uriQuery__region" => "uriQuery__region"
        }
    }
 
}

pipelines.yml

# This file is where you define your pipelines. You can define multiple.
# For more information on multiple pipelines, see the documentation:
#   https://www.elastic.co/guide/en/logstash/current/multiple-pipelines.html
 
- pipeline.id: log_web__filebeat_clickhouse
  path.config: "/etc/logstash/log_web__filebeat_clickhouse.conf"

ClickHouse. Log opbevaringssystem

Logs for alle systemer gemmes i én tabel (se i starten af artiklen). Den er designet til at gemme information om anmodninger: alle parametre er ens for forskellige formater, eksempelvis logs fra IIS, logs fra Apache og Nginx. For applikationslogs, hvor der registreres fejl, informationsbeskeder, advarsler osv., vil der blive taget hÞjde for en separat tabel med en passende struktur (i Þjeblikket under design).

NÄr man designer tabellen, er det meget vigtigt at fastlÊgge den primÊre nÞgle (hvor dataene vil blive sorteret under opbevaring). Dette pÄvirker graden af datakompression og forespÞrgsels hastighed. I vores eksempel er nÞglen
ORDER BY (fld_app_name, fld_app_module, logdatetime)
D.v.s. efter systemnavn, komponentnavn og begivenheds dato. Oprindeligt var begivenheds datoen fĂžrst. Efter at have flyttet den til sidste sted, blev forespĂžrgslerne betydeligt hurtigere. Ændring af den primĂŠre nĂžgle krĂŠver genoprettelse af tabellen og genindlĂŠsning af data, sĂ„ ClickHouse kan sortere dataene pĂ„ disken. Dette er en ressourcekrĂŠvende operation, sĂ„ det er bedst at tĂŠnke nĂžje over, hvad der skal indgĂ„ i sorteringsnĂžglen pĂ„ forhĂ„nd.

Det er ogsÄ vigtigt at bemÊrke, at den seneste version har introduceret datatypen LowCardinality. Ved brug heraf reduceres stÞrrelsen pÄ de komprimerede data betydeligt for de felter, der har lav kardinalitet (fÄ variationer).

I Þjeblikket bruges version 19.6, og vi planlÊgger at opdatere til den seneste version. Den indeholder fantastiske funktioner sÄsom Adaptive Granularity, Skipping indices og codec DoubleDelta, f.eks.

Som standard er logningsniveauet trace indstillet ved installation. Logs roteres og arkiveres, men udvides til en gigabyte. Hvis det ikke er nÞdvendigt, kan man sÊtte logningsniveauet til warning, sÄ loggens stÞrrelse reduceres drastisk. Logningsindstillingerne angives i filen config.xml:

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

Nogle nyttige kommandoer

Da de oprindelige installationspakker er sammensat til Debian, skal der bruges pakker, der er samlet af Altinity til andre versioner af Linux.
 
Her er der instruktioner med links til deres repository: https://www.altinity.com/blog/2017/12/18/logstash-with-clickhouse
sudo yum search clickhouse-server
sudo yum install clickhouse-server.noarch
  
1. tjek status
sudo systemctl status clickhouse-server
 
2. stop serveren
sudo systemctl stop clickhouse-server
 
3. start serveren
sudo systemctl start clickhouse-server
 
Start for at udfĂžre forespĂžrgsler i multiline-tilstand (udfĂžrelse efter semikolon ";")
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
 
Clickhouse-plugin til Logstash gemmer, i tilfÊlde af en fejl i én linje, hele pakken i filen /tmp/log_web_failed.json.
Du kan manuelt rette denne fil og forsĂžge at uploade den til databasen manuelt:
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
 
forlad kommandolinjen
quit;
## TLS konfiguration
https://www.altinity.com/blog/2019/3/5/clickhouse-networking-part-2
 
openssl s_client -connect log.domain.com:9440 < /dev/null

LogStash. Log-ruter fra FileBeat til RabbitMQ-kĂž.

Denne komponent bruges til at route logs, der kommer fra FileBeat til RabbitMQ-kĂžen. Der er to aspekter:

  1. DesvĂŠrre har FileBeat ikke en output-plugin til at skrive direkte til RabbitMQ. Og sĂ„dan en funktionalitet er, ifĂžlge problemerne pĂ„ deres GitHub, ikke planlagt til implementering. Der er et plugin til Kafka, men af ​​visse Ă„rsager kan vi ikke bruge det hos os.
  2. Der er krav til logindsamling i DMZ. I henhold til dem skal loggene fĂžrst opbevares i en kĂž, hvorefter LogStash lĂŠser posterne udefra.

Derfor, i tilfÊlde af at serverne er placeret i DMZ, mÄ vi bruge en lidt mere kompliceret ordning. Et eksempel pÄ konfiguration ser sÄledes ud:

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. MeddelelseskĂž

Denne komponent bruges til at buffere logposter i DMZ. Optagelse sker gennem forbindelsen Filebeat → LogStash. Lésning finder sted udefra DMZ via LogStash. Ved brug af RabbitMQ behandles cirka 4.000 meddelelser i sekundet.

Meddelelsesrouting er konfigureret efter systemnavn, dvs. baseret pÄ FileBeat konfigurationsdata. Alle meddelelser havner i én kÞ. Hvis kÞservicen stoppes af en eller anden grund, vil det ikke fÞre til tab af meddelelser: FileBeat vil modtage forbindelsesfejl og midlertidigt stoppe afsendelsen. LogStash, som lÊser fra kÞen, vil ogsÄ modtage netvÊrksfejl og vente pÄ, at forbindelsen genoprettes. Dataene vil selvfÞlgelig stoppe med at blive skrevet til databasen.

FĂžlgende instruktioner bruges til at oprette og konfigurere kĂžer:

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

Denne komponent bruges til at visualisere overvÄgningsdata. Det er nÞdvendigt at installere ClickHouse-datasource plugin til Grafana 4.6+. Vi mÄtte justere det lidt for at forbedre effektiviteten ved behandling af SQL-filtre pÄ dashboardet.

For eksempel bruger vi variabler, og hvis de ikke er angivet i filterfeltet, sÄ Þnsker vi, at det ikke skal generere et WHERE-betingelse af typen (uriStem = » AND uriStem != »). I sÄ fald vil ClickHouse lÊse kolonnen uriStem. Generelt prÞvede vi forskellige muligheder, og til sidst justerede vi plugin'et (makroen $valueIfEmpty), sÄ i tilfÊlde af en tom vÊrdi returnerer det 1, uden at nÊvne selve kolonnen.

Og nu kan vi bruge en sÄdan forespÞrgsel til grafen

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

som der omdannes til denne SQL (bemĂŠrk, at tomme uriStem-felter er blevet til blot 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

Konklusion

Fremkomsten af ClickHouse-databasen var en markant begivenhed pÄ markedet. Det var svÊrt at forestille sig, at vi pludselig, helt gratis, fik et kraftfuldt og praktisk vÊrktÞj til arbejde med store data. Uden tvivl vil skemaet blive mere kompliceret med stigende behov (f.eks. sharding og replikation pÄ flere servere). Men efter de fÞrste indtryk er det meget behageligt at arbejde med denne database. Man kan se, at produktet er lavet 'til mennesker'.

Sammenlignet med ElasticSearch skÞnnes omkostningerne til opbevaring og behandling af logfiler at blive fem til ti gange lavere. Med andre ord, hvis vi skulle opsÊtte et cluster af flere maskiner til den nuvÊrende datamÊngde, ville én lavtkapacitetsmaskine vÊre tilstrÊkkelig ved brug af ClickHouse. Ja, ElasticSearch har ogsÄ mekanismer til komprimering af data pÄ disken og andre funktioner, der reducerer ressourceforbruget betydeligt, men det vil krÊve stÞrre investeringer sammenlignet med ClickHouse.

Uden nogle sÊrlige optimeringer fra vores side, med standardindstillingerne, arbejder dataindlÊsning og forespÞrgsler fra databasen med imponerende hastighed. Vi har kun lidt data (ca. 200 millioner poster), men selve serveren er svag. Dette vÊrktÞj kan vi i fremtiden bruge til andre formÄl, ikke kun til opbevaring af logfiler. For eksempel til end-to-end analyse, inden for sikkerhed og maskinlÊring.

Til sidst lidt om fordele og ulemper.

Ulemper

  1. IndlÊsning af poster i store batches. PÄ den ene side er det en funktion, men man mÄ stadig bruge ekstra komponenter til buffring af poster. Denne opgave er ikke altid let, men den er stadig lÞselig. Og vi Þnsker at forenkle skemaet.
  2. Nogle eksotiske funktioner eller nye funktioner gÄr ofte i stykker i de nye versioner. Dette skaber bekymringer og mindsker Þnsket om at opdatere til den nye version. For eksempel er Kafka-tabellerne en meget nyttig funktion, der gÞr det muligt direkte at lÊse begivenheder fra Kafka uden at implementere forbrugere. Men i betragtning af antallet af problemer pÄ GitHub er vi stadig forsigtige med at bruge denne motor i produktionen. Men hvis man undgÄr pludselige bevÊgelser og bruger den grundlÊggende funktionalitet, fungerer den stabilt.

Fordele

  1. Bremser ikke.
  2. Lav adgangsbarriere.
  3. Open-source.
  4. Gratis.
  5. Godt skalerbar (sharding/replicering "out of the box")
  6. Inkluderet i registret over russisk software anbefalet af Ministeriet for Kommunikation.
  7. Officiel support fra Yandex.

Kilde: habr.com

KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster