ClickHouse-databasis vir mense, of uitheemse tegnologieë

Aleksey Lizunov, hoof van die bevoegdheidsentrum vir afgeleë dienskanale van die Direktoraat Inligtingstegnologie van die MKB

ClickHouse-databasis vir mense, of uitheemse tegnologieë

As 'n alternatief vir die ELK-stapel (ElasticSearch, Logstash, Kibana), doen ons navorsing oor die gebruik van die ClickHouse-databasis as 'n datastoor vir logs.

In hierdie artikel wil ons graag praat oor ons ervaring met die gebruik van die ClickHouse-databasis en die voorlopige resultate van die loodsoperasie. Daar moet dadelik op gelet word dat die resultate indrukwekkend was.


ClickHouse-databasis vir mense, of uitheemse tegnologieë

Vervolgens sal ons in meer besonderhede beskryf hoe ons stelsel opgestel is, en uit watter komponente dit bestaan. Maar nou wil ek 'n bietjie praat oor hierdie databasis as 'n geheel, en waarom dit die moeite werd is om aandag aan te gee. Die ClickHouse-databasis is 'n hoëprestasie analitiese kolomdatabasis van Yandex. Dit word gebruik in Yandex-dienste, aanvanklik is dit die hoofdataberging vir Yandex.Metrica. Oopbronstelsel, gratis. Uit 'n ontwikkelaar se oogpunt het ek nog altyd gewonder hoe hulle dit geïmplementeer het, want daar is fantasties groot data. En Metrica se gebruikerskoppelvlak self is baie buigsaam en vinnig. By die eerste kennismaking met hierdie databasis is die indruk: “Wel, uiteindelik! Gemaak vir die mense! Begin by die installasieproses en eindig met die stuur van versoeke.

Hierdie databasis het 'n baie lae toegangsdrempel. Selfs 'n gemiddelde vaardige ontwikkelaar kan hierdie databasis binne 'n paar minute installeer en dit begin gebruik. Alles werk duidelik. Selfs mense wat nuut is met Linux, kan die installasie vinnig hanteer en die eenvoudigste bewerkings doen. As 'n gewone ontwikkelaar vroeër, met die woorde Big Data, Hadoop, Google BigTable, HDFS, idees gehad het dat dit oor sommige teragrepe, petagrepe, gaan dat sommige supermense betrokke is by instellings en ontwikkeling vir hierdie stelsels, dan met die koms van die ClickHouse databasis, het ons 'n eenvoudige, verstaanbare hulpmiddel waarmee jy 'n voorheen onbereikbare reeks take kan oplos. Dit neem net een redelik gemiddelde masjien en vyf minute om te installeer. Dit wil sê, ons het so 'n databasis soos byvoorbeeld MySql gekry, maar net vir die stoor van miljarde rekords! 'n Sekere superargiveerder met die SQL-taal. Dit is asof mense die wapens van aliens oorhandig is.

Oor ons logstelsel

Om inligting in te samel, word IIS-loglêers van standaardformaat-webtoepassings gebruik (ons is ook tans besig om toepassingslogboeke te ontleed, maar die hoofdoel op die proefstadium is om IIS-logboeke in te samel).

Om verskeie redes kon ons nie die ELK-stapel heeltemal laat vaar nie, en ons gaan voort om die LogStash- en Filebeat-komponente te gebruik, wat hulself goed bewys het en redelik betroubaar en voorspelbaar werk.

Die algemene aantekenskema word in die onderstaande figuur getoon:

ClickHouse-databasis vir mense, of uitheemse tegnologieë

'n Kenmerk van die skryf van data na die ClickHouse-databasis is ongereelde (een keer per sekonde) invoeging van rekords in groot bondels. Dit is blykbaar die mees "problematiese" deel wat u teëkom wanneer u die eerste keer met die ClickHouse-databasis werk: die skema word 'n bietjie meer ingewikkeld.
Die inprop vir LogStash, wat data direk in ClickHouse invoeg, het hier baie gehelp. Hierdie komponent word op dieselfde bediener as die databasis self ontplooi. So, oor die algemeen, word dit nie aanbeveel om dit te doen nie, maar vanuit 'n praktiese oogpunt, om nie aparte bedieners te produseer terwyl dit op dieselfde bediener ontplooi word nie. Ons het geen foute of hulpbronkonflik met die databasis waargeneem nie. Daarbenewens moet daarop gelet word dat die inprop 'n herprobeermeganisme het in geval van foute. En in die geval van foute, skryf die inprop 'n bondel data wat nie ingevoeg kon word nie (die lêerformaat is gerieflik: na redigering kan u die gekorrigeerde bondel maklik invoeg met behulp van clickhouse-kliënt).

'n Volledige lys van sagteware wat in die skema gebruik word, word in die tabel aangebied:

Lys van sagteware wat gebruik word

Naam

Beskrywing

Verspreiding skakel

Nginx

Omgekeerde proxy om toegang deur poorte te beperk en magtiging te organiseer

Tans nie in die skema gebruik nie

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

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

FileBeat

Oordrag van lêerlogboeke.

https://www.elastic.co/downloads/beats/filebeat (verspreidingstel vir Windows 64bit).

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

logstash

Log versamelaar.

Word gebruik om logs van FileBeat in te samel, sowel as om logs van die RabbitMQ-ry te versamel (vir bedieners wat in die DMZ is.)

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

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

Logstash-uitvoer-klikhuis

Loagstash-inprop vir die oordrag van logs na die ClickHouse-databasis in groepe

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

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

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

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

klikhuis

Log stoor 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

Let wel. Vanaf Augustus 2018 het "normale" rpm-bouwerk vir RHEL in die Yandex-bewaarplek verskyn, sodat u dit kan probeer gebruik. Ten tyde van die installasie het ons pakkette gebruik wat deur Altinity gebou is.

grafana

Log visualisering. Die opstel van dashboards

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 Bit) - nuutste weergawe

ClickHouse-databron vir Grafana 4.6+

Inprop vir Grafana met ClickHouse-databron

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

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

logstash

Teken router van FileBeat na RabbitMQ-tou aan.

Let wel. Ongelukkig het FileBeat nie uitset direk na RabbitMQ nie, so 'n tussenskakel in die vorm van Logstash word vereis

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

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

Konyn MQ

boodskap tou. Dit is die log buffer in die 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 (Vereis vir RabbitMQ)

Erlang looptyd. Vereis vir RabbitMQ om te werk

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

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

Die bedienerkonfigurasie met die ClickHouse-databasis word in die volgende tabel aangebied:

Naam

Waarde

Let daarop

opset

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

Dit is nodig om aandag te skenk aan die wenke vir die bestuur van die ClickHouse-databasis (https://clickhouse.yandex/docs/ru/operations/tips/)

Algemene stelsel sagteware

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Soos u kan sien, is dit 'n gewone werkstasie.

Die struktuur van die tabel vir die stoor van logs is soos volg:

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;

Ons gebruik verstekpartisionering (per maand) en indeksgranulariteit. Alle velde stem feitlik ooreen met IIS-loginskrywings vir die aanteken van http-versoeke. Afsonderlik let ons daarop dat daar afsonderlike velde is vir die stoor van utm-tags (hulle word ontleed op die stadium van invoeging in die tabel vanaf die navraagstringveld).

Verskeie stelselvelde is ook by die tabel gevoeg om inligting oor stelsels, komponente, bedieners te stoor. Sien die tabel hieronder vir 'n beskrywing van hierdie velde. In een tabel stoor ons logs vir verskeie stelsels.

Naam

Beskrywing

Voorbeeld

fld_app_naam

Toepassing/stelselnaam
Geldige waardes:

  • site1.domain.com Eksterne webwerf 1
  • site2.domain.com Eksterne webwerf 2
  • internal-site1.domain.local Interne werf 1

site1.domain.com

fld_app_module

Stelsel module
Geldige waardes:

  • web - webwerf
  • svc - webwerf diens
  • intgr - Integrasie Webdiens
  • bo - Admin (BackOffice)

web

fld_webwerf_naam

Werfnaam in IIS

Verskeie stelsels kan op een bediener ontplooi word, of selfs verskeie gevalle van een stelselmodule

web hoof

fld_bediener_naam

Bediener naam

web1.domain.com

fld_log_file_name

Pad na die loglêer op die bediener

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

Dit laat jou toe om doeltreffend grafieke in Grafana te bou. Bekyk byvoorbeeld versoeke vanaf die voorkant van 'n spesifieke stelsel. Dit is soortgelyk aan die werfteller in Yandex.Metrica.

Hier is 'n paar statistieke oor die gebruik van die databasis vir twee maande.

Aantal rekords opgedeel volgens stelsels en hul komponente

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

Die hoeveelheid data op die skyf

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.

Mate van datakompressie in kolomme

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.

Beskrywing van gebruikte komponente

filebeat. Dra lêerlogboeke oor

Hierdie komponent volg veranderinge aan loglêers op skyf en gee die inligting aan LogStash deur. Geïnstalleer op alle bedieners waar loglêers geskryf word (gewoonlik IIS). Werk in stertmodus (d.w.s. dra slegs die bygevoegde rekords na die lêer oor). Maar afsonderlik kan dit gekonfigureer word om hele lêers oor te dra. Dit is nuttig wanneer jy data van vorige maande moet aflaai. Plaas net die loglêer in 'n gids en dit sal dit in sy geheel lees.

Wanneer die diens gestop word, word die data nie meer verder na die berging oorgedra nie.

'n Voorbeeldkonfigurasie lyk soos volg:

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 versamelaar

Hierdie komponent is ontwerp om loginskrywings vanaf FileBeat (of deur die RabbitMQ-tou) te ontvang, om bondels te ontleed en in die ClickHouse-databasis in te voeg.

Vir invoeging in ClickHouse, word die Logstash-output-clickhouse-inprop gebruik. Die Logstash-inprop het 'n versoekherprobeermeganisme, maar met 'n gereelde afsluiting is dit beter om die diens self te stop. Wanneer dit gestop word, sal boodskappe in die RabbitMQ-ry opgehoop word, so as die stop vir 'n lang tyd is, is dit beter om Filebeats op die bedieners te stop. In 'n skema waar RabbitMQ nie gebruik word nie (op die plaaslike netwerk stuur Filebeat logs direk na Logstash), werk Filebeats redelik aanvaarbaar en veilig, so vir hulle gaan die onbeskikbaarheid van uitvoer sonder gevolge verby.

'n Voorbeeldkonfigurasie lyk soos volg:

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

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

klikhuis. Log stoor

Logs vir alle stelsels word in een tabel gestoor (sien aan die begin van die artikel). Dit is bedoel om inligting oor versoeke te stoor: alle parameters is soortgelyk vir verskillende formate, soos IIS-logs, apache en nginx-logs. Vir toepassingslogboeke, waarin byvoorbeeld foute, inligtingsboodskappe, waarskuwings aangeteken word, sal 'n aparte tabel voorsien word met die toepaslike struktuur (tans in die ontwerpstadium).

Wanneer 'n tabel ontwerp word, is dit baie belangrik om op die primêre sleutel te besluit (waarmee die data tydens berging gesorteer sal word). Die mate van datakompressie en navraagspoed hang hiervan af. In ons voorbeeld is die sleutel
BESTEL DEUR (fld_app_name, fld_app_module, logdatetime)
Dit wil sê, deur die naam van die stelsel, die naam van die stelselkomponent en die datum van die gebeurtenis. Aanvanklik het die datum van die geleentheid eerste gekom. Nadat dit na die laaste plek geskuif is, het navrae omtrent twee keer so vinnig begin werk. Die verandering van die primêre sleutel sal vereis dat die tabel herskep en die data herlaai word sodat ClickHouse die data op skyf hersorteer. Dit is 'n swaar operasie, so dit is 'n goeie idee om baie na te dink oor wat in die sorteersleutel ingesluit moet word.

Daar moet ook kennis geneem word dat die LowCardinality-datatipe relatief in onlangse weergawes verskyn het. Wanneer dit gebruik word, word die grootte van saamgeperste data drasties verminder vir daardie velde wat lae kardinaliteit het (min opsies).

Weergawe 19.6 is tans in gebruik en ons beplan om te probeer opdateer na die nuutste weergawe. Hulle het sulke wonderlike kenmerke soos Adaptive Granularity, Skipping-indekse en die DoubleDelta-kodek, byvoorbeeld.

By verstek, tydens installasie, is die logvlak ingestel om na te spoor. Die logs word geroteer en geargiveer, maar terselfdertyd brei hulle uit tot 'n gigagreep. As dit nie nodig is nie, kan u die waarskuwingsvlak instel, dan word die grootte van die log drasties verminder. Die aantekeninstelling word in die config.xml-lêer gestel:

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

'n Paar nuttige opdragte

Поскольку оригинальные пакеты установки собираются по 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. Teken router van FileBeat na RabbitMQ-tou aan

Hierdie komponent word gebruik om logs wat van FileBeat af kom na die RabbitMQ-ry te stuur. Daar is twee punte hier:

  1. Ongelukkig het FileBeat nie 'n uitvoerinprop om direk na RabbitMQ te skryf nie. En sulke funksionaliteit, te oordeel aan die probleem op hul github, word nie vir implementering beplan nie. Daar is 'n inprop vir Kafka, maar om een ​​of ander rede kan ons dit nie tuis gebruik nie.
  2. Daar is vereistes vir die versameling van logs in die DMZ. Op grond daarvan moet die logs eers by die tou gevoeg word en dan lees LogStash die inskrywings van die tou van buite af.

Daarom is dit vir die geval waar bedieners in die DMZ geleë is dat 'n mens so 'n effens ingewikkelde skema moet gebruik. 'n Voorbeeldkonfigurasie lyk soos volg:

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. boodskap tou

Hierdie komponent word gebruik om loginskrywings in die DMZ te buffer. Opname word gedoen deur 'n klomp Filebeat → LogStash. Lees word van buite die DMZ via LogStash gedoen. As u deur RabboitMQ werk, word ongeveer 4 duisend boodskappe per sekonde verwerk.

Boodskaproetering word gekonfigureer deur stelselnaam, dit wil sê gebaseer op FileBeat-konfigurasiedata. Alle boodskappe gaan na een tou. As die toustaandiens om een ​​of ander rede gestop word, sal dit nie lei tot die verlies van boodskappe nie: FileBeats sal verbindingsfoute ontvang en die versending tydelik opskort. En LogStash wat uit die tou lees, sal ook netwerkfoute ontvang en wag vir die verbinding om herstel te word. In hierdie geval sal die data natuurlik nie meer na die databasis geskryf word nie.

Die volgende instruksies word gebruik om toue te skep en op te stel:

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

Hierdie komponent word gebruik om moniteringsdata te visualiseer. In hierdie geval moet jy die ClickHouse-databron vir Grafana 4.6+-inprop installeer. Ons moes dit 'n bietjie aanpas om die doeltreffendheid van die verwerking van SQL-filters op die dashboard te verbeter.

Ons gebruik byvoorbeeld veranderlikes, en as hulle nie in die filterveld gestel is nie, dan wil ons hê dat dit nie 'n voorwaarde in die WHERE van die vorm genereer nie ( uriStem = » EN uriStem != » ). In hierdie geval sal ClickHouse die uriStem-kolom lees. Oor die algemeen het ons verskillende opsies probeer en uiteindelik die inprop (die $valueIfEmpty-makro) reggestel sodat dit in die geval van 'n leë waarde 1 gee, sonder om die kolom self te noem.

En nou kan jy hierdie navraag vir die grafiek gebruik

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

wat so na SQL vertaal word (let op dat die leë uriStem-velde na net 1 omgeskakel is)

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

Gevolgtrekking

Die voorkoms van die ClickHouse-databasis het 'n landmerkgebeurtenis in die mark geword. Dit was moeilik om te dink dat ons, heeltemal gratis, in 'n oomblik gewapen was met 'n kragtige en praktiese hulpmiddel om met groot data te werk. Natuurlik, met toenemende behoeftes (byvoorbeeld versplintering en replikasie na verskeie bedieners), sal die skema meer ingewikkeld raak. Maar by eerste indrukke is dit baie aangenaam om met hierdie databasis te werk. Dit kan gesien word dat die produk "vir mense" gemaak is.

In vergelyking met ElasticSearch, word die koste van die stoor en verwerking van logs na raming met vyf tot tien keer verminder. Met ander woorde, as ons vir die huidige hoeveelheid data 'n groep van verskeie masjiene moet opstel, dan is een laekragmasjien genoeg vir ons wanneer ons ClickHouse gebruik. Ja, natuurlik, ElasticSearch het ook datakompressiemeganismes op die skyf en ander kenmerke wat hulpbronverbruik aansienlik kan verminder, maar in vergelyking met ClickHouse sal dit duurder wees.

Sonder enige spesiale optimalisering van ons kant, op verstekinstellings, werk die laai van data en kies uit die databasis teen 'n ongelooflike spoed. Ons het nog nie veel data nie (ongeveer 200 miljoen rekords), maar die bediener self is swak. Ons kan hierdie instrument in die toekoms gebruik vir ander doeleindes wat nie verband hou met die stoor van logs nie. Byvoorbeeld, vir end-tot-end-analise, op die gebied van sekuriteit, masjienleer.

Aan die einde, 'n bietjie oor die voor- en nadele.

Nadele

  1. Laai rekords in groot groepe. Aan die een kant is dit 'n kenmerk, maar jy moet steeds bykomende komponente gebruik om rekords te buffer. Hierdie taak is nie altyd maklik nie, maar steeds oplosbaar. En ek wil graag die skema vereenvoudig.
  2. Sommige eksotiese funksies of nuwe kenmerke breek dikwels in nuwe weergawes. Dit wek kommer, wat die begeerte verminder om na 'n nuwe weergawe op te gradeer. Byvoorbeeld, die Kafka-tafelenjin is 'n baie nuttige kenmerk wat jou toelaat om gebeure van Kafka direk te lees, sonder om verbruikers te implementeer. Maar te oordeel aan die aantal kwessies op die github, is ons steeds versigtig om nie hierdie enjin in produksie te gebruik nie. As jy egter nie skielike gebare na die kant toe maak en die hooffunksies gebruik nie, dan werk dit stabiel.

Pros

  1. Vertraag nie.
  2. Lae toegangsdrempel.
  3. Oop bron.
  4. Vry.
  5. Skaal goed (skerp/replisering uit die boks)
  6. Ingesluit in die register van Russiese sagteware wat deur die Ministerie van Kommunikasie aanbeveel word.
  7. Die teenwoordigheid van amptelike ondersteuning van Yandex.

Bron: will.com

Voeg 'n opmerking