ClickHouse Database for Humans eller Alien Technologies

Aleksey Lizunov, leder af kompetencecentret for fjernservicekanaler i direktoratet for informationsteknologier i MKB

ClickHouse Database for Humans eller Alien Technologies

Som et alternativ til ELK-stakken (ElasticSearch, Logstash, Kibana) forsker vi i at bruge ClickHouse-databasen som et datalager for logfiler.

I denne artikel vil vi gerne fortælle om vores erfaring med at bruge ClickHouse-databasen og de foreløbige resultater af pilotoperationen. Det skal straks bemærkes, at resultaterne var imponerende.


ClickHouse Database for Humans eller Alien Technologies

Dernæst vil vi beskrive mere detaljeret, hvordan vores system er konfigureret, og hvilke komponenter det består af. Men nu vil jeg gerne fortælle lidt om denne database som helhed, og hvorfor den er værd at være opmærksom på. ClickHouse-databasen er en højtydende analytisk kolonnebaseret database fra Yandex. Det bruges i Yandex-tjenester, i første omgang er det den vigtigste datalagring for Yandex.Metrica. Open source-system, gratis. Fra en udviklers synspunkt har jeg altid undret mig over, hvordan de implementerede det, for der er fantastisk store data. Og selve Metricas brugergrænseflade er meget fleksibel og hurtig. Ved det første bekendtskab med denne database er indtrykket: ”Nå, endelig! Lavet til folket! Starter fra installationsprocessen og slutter med at sende anmodninger.

Denne database har en meget lav indgangstærskel. Selv en gennemsnitlig dygtig udvikler kan installere denne database på få minutter og begynde at bruge den. Alt fungerer klart. Selv folk, der er nye til Linux, kan hurtigt håndtere installationen og udføre de enkleste handlinger. Hvis en almindelig udvikler tidligere, med ordene Big Data, Hadoop, Google BigTable, HDFS, havde ideer om, at det handlede om nogle terabyte, petabytes, at nogle supermennesker er engageret i indstillinger og udvikling af disse systemer, så med fremkomsten af ​​ClickHouse database, har vi fået et enkelt, forståeligt værktøj, hvormed du kan løse en hidtil uopnåelig række opgaver. Det tager kun en ganske gennemsnitlig maskine og fem minutter at installere. Det vil sige, at vi fik sådan en database som for eksempel MySql, men kun til lagring af milliarder af poster! En bestemt super-arkiver med SQL-sproget. Det er som om, folk fik udleveret rumvæseners våben.

Om vores logningssystem

For at indsamle information bruges IIS-logfiler af standardformat-webapplikationer (vi parser også i øjeblikket applikationslogfiler, men hovedmålet på pilotstadiet er at indsamle IIS-logfiler).

Af forskellige årsager kunne vi ikke helt opgive ELK-stakken, og vi fortsætter med at bruge LogStash- og Filebeat-komponenterne, som har vist sig godt og fungerer ganske pålideligt og forudsigeligt.

Det generelle logningsskema er vist i nedenstående figur:

ClickHouse Database for Humans eller Alien Technologies

En funktion ved at skrive data til ClickHouse-databasen er sjælden (én gang i sekundet) indsættelse af poster i store partier. Dette er tilsyneladende den mest "problematiske" del, du støder på, når du første gang oplever at arbejde med ClickHouse-databasen: ordningen bliver lidt mere kompliceret.
Pluginnet til LogStash, som direkte indsætter data i ClickHouse, hjalp meget her. Denne komponent er installeret på den samme server som selve databasen. Så generelt anbefales det ikke at gøre det, men fra et praktisk synspunkt, for ikke at producere separate servere, mens det er installeret på den samme server. Vi har ikke observeret nogen fejl eller ressourcekonflikter med databasen. Derudover skal det bemærkes, at plugin'et har en genforsøgsmekanisme i tilfælde af fejl. Og i tilfælde af fejl, skriver plugin til disken en batch af data, der ikke kunne indsættes (filformatet er praktisk: efter redigering kan du nemt indsætte den rettede batch ved hjælp af clickhouse-klient).

En komplet liste over software brugt i ordningen er præsenteret i tabellen:

Liste over anvendt software

Navn

beskrivelse

Distributionslink

Nginx

Omvendt proxy for at begrænse adgangen til porte og organisere autorisation

I øjeblikket ikke brugt i ordningen

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

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

FileBeat

Overførsel af fillogfiler.

https://www.elastic.co/downloads/beats/filebeat (distributionssæt til Windows 64bit).

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

logstash

Træ samler.

Bruges til at indsamle logfiler fra FileBeat, samt til at indsamle logfiler fra RabbitMQ-køen (for servere, der er i DMZ.)

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

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

Logstash-output-klikhus

Loagstash-plugin til overførsel af logfiler til ClickHouse-databasen i batches

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

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

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

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

klikhus

Logopbevaring 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

Bemærk. Fra august 2018 dukkede "normale" rpm-builds til RHEL op i Yandex-depotet, så du kan prøve at bruge dem. På installationstidspunktet brugte vi pakker bygget af Altinity.

grafana

Log visualisering. Opsætning af dashboards

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos(64 Bit) - seneste version

ClickHouse-datakilde for Grafana 4.6+

Plugin til Grafana med ClickHouse datakilde

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

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

logstash

Log router fra FileBeat til RabbitMQ-kø.

Bemærk. Desværre har FileBeat ikke output direkte til RabbitMQ, så et mellemled i form af Logstash er påkrævet

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

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

RabbitMQ

beskedkø. Dette er logbufferen 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 (påkrævet for RabbitMQ)

Erlang køretid. Påkrævet for at RabbitMQ kan fungere

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-databasen er præsenteret i følgende tabel:

Navn

Value

Bemærk

Konfiguration

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

Det er nødvendigt at være opmærksom på tips til betjening af ClickHouse-databasen (https://clickhouse.yandex/docs/ru/operations/tips/)

Generel systemsoftware

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Som du kan se, er dette en almindelig arbejdsstation.

Strukturen af ​​tabellen til opbevaring af logfiler er som følger:

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 standardpartitionering (efter måned) og indeksgranularitet. Alle felter svarer praktisk talt til IIS-logposter til logning af http-anmodninger. Separat bemærker vi, at der er separate felter til lagring af utm-tags (de parses på tidspunktet for indsættelse i tabellen fra forespørgselsstrengfeltet).

Der er også tilføjet flere systemfelter til tabellen for at gemme information om systemer, komponenter, servere. Se tabellen nedenfor for en beskrivelse af disse felter. I én tabel gemmer vi logfiler for flere systemer.

Navn

beskrivelse

Eksempel

fld_app_name

Navn på applikation/system
Gyldige værdier:

  • site1.domain.com Eksternt websted 1
  • site2.domain.com Eksternt websted 2
  • intern-site1.domain.local Intern side 1

site1.domain.com

fld_app_modul

System modul
Gyldige værdier:

  • web - Hjemmeside
  • svc - webstedstjeneste
  • intgr - Integration Web Service
  • bo - Admin (BackOffice)

web

fld_website_name

Webstedsnavn i IIS

Flere systemer kan installeres på én server, eller endda flere forekomster af ét systemmodul

web hoved

fld_server_name

Server navn

web1.domæne.com

fld_log_file_name

Sti til logfilen på serveren

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

Dette giver dig mulighed for effektivt at bygge grafer i Grafana. Se for eksempel anmodninger fra frontend af et bestemt system. Dette svarer til webstedstælleren i Yandex.Metrica.

Her er nogle statistikker over brugen af ​​databasen i to måneder.

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

Mængden af ​​data 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.

Grad af datakomprimering i kolonner

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.

Beskrivelse af brugte komponenter

FileBeat. Overførsel af fillogfiler

Denne komponent sporer ændringer til logfiler på disken og sender oplysningerne til LogStash. Installeret på alle servere, hvor logfiler er skrevet (normalt IIS). Fungerer i hale-tilstand (dvs. overfører kun de tilføjede poster til filen). Men separat kan den konfigureres til at overføre hele filer. Dette er nyttigt, når du skal downloade data fra tidligere måneder. Bare læg logfilen i en mappe, og den vil læse den i sin helhed.

Når tjenesten stoppes, overføres dataene ikke længere videre til lageret.

Et eksempel på konfiguration ser sådan 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 logposter fra FileBeat (eller gennem RabbitMQ-køen), parse og indsætte batches i ClickHouse-databasen.

Til indsættelse i ClickHouse bruges Logstash-output-clickhouse plugin. Logstash-plugin'et har en mekanisme for genforsøg, men med en regelmæssig nedlukning er det bedre at stoppe selve tjenesten. Når stoppet, vil beskeder blive akkumuleret i RabbitMQ-køen, så hvis stoppet er i lang tid, så er det bedre at stoppe Filebeats på serverne. I et skema, hvor RabbitMQ ikke bruges (på det lokale netværk sender Filebeat logfiler direkte til Logstash), fungerer Filebeats ganske acceptabelt og sikkert, så for dem går utilgængeligheden af ​​output uden konsekvenser.

Et eksempel på konfiguration ser sådan 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"

klikhus. Logopbevaring

Logfiler for alle systemer er gemt i én tabel (se i begyndelsen af ​​artiklen). Det er beregnet til at gemme information om anmodninger: alle parametre er ens for forskellige formater, såsom IIS-logfiler, apache- og nginx-logfiler. For applikationslogfiler, hvori f.eks. fejl, informationsmeddelelser, advarsler registreres, vil en separat tabel blive forsynet med den passende struktur (i øjeblikket på designstadiet).

Når du designer en tabel, er det meget vigtigt at beslutte sig for den primære nøgle (som dataene vil blive sorteret efter under lagring). Graden af ​​datakomprimering og forespørgselshastighed afhænger af dette. I vores eksempel er nøglen
BESTIL EFTER (fld_app_name, fld_app_module, logdatetime)
Det vil sige ved navnet på systemet, navnet på systemkomponenten og datoen for hændelsen. I første omgang kom datoen for begivenheden først. Efter at have flyttet det til det sidste sted, begyndte forespørgsler at arbejde omkring dobbelt så hurtigt. Ændring af den primære nøgle vil kræve genskabelse af tabellen og genindlæsning af data, så ClickHouse omsorterer dataene på disken. Det er en tung operation, så det er en god idé at tænke meget over, hvad der skal med i sorteringsnøglen.

Det skal også bemærkes, at LowCardinality-datatypen har optrådt relativt i nyere versioner. Når du bruger det, reduceres størrelsen af ​​komprimerede data drastisk for de felter, der har lav kardinalitet (få muligheder).

Version 19.6 er i brug i øjeblikket, og vi planlægger at prøve at opdatere til den nyeste version. De har så vidunderlige funktioner som Adaptive Granularity, Skipping-indekser og DoubleDelta codec, for eksempel.

Som standard er logningsniveauet indstillet til sporing under installationen. Loggene roteres og arkiveres, men de udvides samtidig op til en gigabyte. Hvis der ikke er behov, så kan du indstille advarselsniveauet, så er størrelsen på loggen drastisk reduceret. Indstillingen for logning er angivet i filen config.xml:

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

Nogle nyttige kommandoer

Поскольку оригинальные пакеты установки собираются по 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. Log router fra FileBeat til RabbitMQ-kø

Denne komponent bruges til at dirigere logfiler, der kommer fra FileBeat, til RabbitMQ-køen. Der er to punkter her:

  1. Desværre har FileBeat ikke et output-plugin til at skrive direkte til RabbitMQ. Og sådan funktionalitet, at dømme efter problemet på deres github, er ikke planlagt til implementering. Der er et plugin til Kafka, men af ​​en eller anden grund kan vi ikke bruge det derhjemme.
  2. Der er krav til indsamling af logfiler i DMZ. Baseret på dem skal loggene først tilføjes til køen og derefter læser LogStash indtastningerne fra køen udefra.

Derfor er det for det tilfælde, hvor servere er placeret i DMZ'en, at man skal bruge sådan en lidt kompliceret ordning. Et eksempel på konfiguration ser sådan 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. beskedkø

Denne komponent bruges til at buffere logindtastninger i DMZ. Optagelse sker gennem en masse Filebeat → LogStash. Aflæsning sker uden for DMZ via LogStash. Når du opererer gennem RabboitMQ, behandles omkring 4 tusinde beskeder i sekundet.

Meddelelsesrouting er konfigureret efter systemnavn, dvs. baseret på FileBeat-konfigurationsdata. Alle beskeder går til én kø. Hvis køtjenesten af ​​en eller anden grund stoppes, vil dette ikke føre til tab af meddelelser: FileBeats vil modtage forbindelsesfejl og midlertidigt suspendere afsendelsen. Og LogStash, der læser fra køen, vil også modtage netværksfejl og vente på, at forbindelsen bliver genoprettet. I dette tilfælde vil dataene naturligvis ikke længere 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. I dette tilfælde skal du installere ClickHouse-datakilden til Grafana 4.6+ plugin. Vi var nødt til at justere det lidt for at forbedre effektiviteten af ​​behandlingen af ​​SQL-filtre på dashboardet.

For eksempel bruger vi variable, og hvis de ikke er sat i filterfeltet, så vil vi gerne have, at det ikke genererer en betingelse i formularens WHERE ( uriStem = » AND uriStem != » ). I dette tilfælde vil ClickHouse læse uriStem-kolonnen. Generelt prøvede vi forskellige muligheder og korrigerede til sidst pluginnet ($valueIfEmpty-makroen), så det i tilfælde af en tom værdi returnerer 1, uden at nævne selve kolonnen.

Og nu kan du bruge denne 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 oversættes til denne SQL (bemærk, at de tomme uriStem-felter er blevet konverteret til kun 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

Udseendet af ClickHouse-databasen er blevet en skelsættende begivenhed på markedet. Det var svært at forestille sig, at vi helt gratis på et øjeblik var bevæbnet med et kraftfuldt og praktisk værktøj til at arbejde med big data. Selvfølgelig, med stigende behov (for eksempel sharding og replikering til flere servere), vil ordningen blive mere kompliceret. Men ved første indtryk er det meget behageligt at arbejde med denne database. Det kan ses, at produktet er lavet "til mennesker."

Sammenlignet med ElasticSearch anslås omkostningerne til opbevaring og behandling af logfiler at blive reduceret med fem til ti gange. Med andre ord, hvis vi for den nuværende mængde data skulle opsætte en klynge af flere maskiner, så er en laveffektmaskine nok for os, når vi bruger ClickHouse. Ja, selvfølgelig har ElasticSearch også datakomprimeringsmekanismer på disken og andre funktioner, der kan reducere ressourceforbruget markant, men sammenlignet med ClickHouse vil dette være dyrere.

Uden nogen særlige optimeringer fra vores side, på standardindstillinger, fungerer indlæsning af data og valg fra databasen med en fantastisk hastighed. Vi har ikke meget data endnu (ca. 200 millioner poster), men selve serveren er svag. Vi kan bruge dette værktøj i fremtiden til andre formål, der ikke er relateret til lagring af logfiler. For eksempel til end-to-end-analyse inden for sikkerhed, maskinlæring.

Til sidst lidt om fordele og ulemper.

Cons

  1. Indlæser poster i store partier. På den ene side er dette en funktion, men du skal stadig bruge yderligere komponenter til buffering af poster. Denne opgave er ikke altid let, men stadig løselig. Og jeg vil gerne forenkle ordningen.
  2. Nogle eksotiske funktioner eller nye funktioner går ofte i stykker i nye versioner. Dette giver anledning til bekymring, hvilket reducerer ønsket om at opgradere til en ny version. For eksempel er Kafka-bordmotoren en meget nyttig funktion, der giver dig mulighed for direkte at læse begivenheder fra Kafka, uden at implementere forbrugere. Men at dømme efter antallet af Issues på github, er vi stadig forsigtige med ikke at bruge denne motor i produktionen. Men hvis du ikke laver pludselige bevægelser til siden og bruger hovedfunktionaliteten, så fungerer det stabilt.

Pros

  1. Sænker ikke farten.
  2. Lav indgangstærskel.
  3. Open source.
  4. Gratis.
  5. Skalerer godt (skæring/replikering ud af æsken)
  6. Inkluderet i registret over russisk software anbefalet af kommunikationsministeriet.
  7. Tilstedeværelsen af ​​officiel støtte fra Yandex.

Kilde: www.habr.com

Tilføj en kommentar