ClickHouse Database for Humans, eller Alien Technologies

Aleksey Lizunov, chef för kompetenscentret för fjÀrrtjÀnstkanaler vid direktoratet för informationsteknologi vid MKB

ClickHouse Database for Humans, eller Alien Technologies

Som ett alternativ till ELK-stacken (ElasticSearch, Logstash, Kibana) forskar vi om att anvÀnda ClickHouse-databasen som ett datalager för loggar.

I den hÀr artikeln vill vi prata om vÄr erfarenhet av att anvÀnda ClickHouse-databasen och de preliminÀra resultaten av pilotoperationen. Det bör genast noteras att resultaten var imponerande.


ClickHouse Database for Humans, eller Alien Technologies

DĂ€refter kommer vi att beskriva mer i detalj hur vĂ„rt system Ă€r konfigurerat och vilka komponenter det bestĂ„r av. Men nu skulle jag vilja prata lite om denna databas som helhet, och varför det Ă€r vĂ€rt att uppmĂ€rksamma. ClickHouse-databasen Ă€r en högpresterande analytisk kolumndatabas frĂ„n Yandex. Det anvĂ€nds i Yandex-tjĂ€nster, initialt Ă€r det den huvudsakliga datalagringen för Yandex.Metrica. Öppen kĂ€llkodssystem, gratis. Ur en utvecklares synvinkel har jag alltid undrat hur de implementerade det, för det finns fantastiskt stor data. Och Metricas anvĂ€ndargrĂ€nssnitt i sig Ă€r vĂ€ldigt flexibelt och snabbt. Vid den första bekantskapen med denna databas Ă€r intrycket: ”Jaha, Ă€ntligen! Gjord för folket! Börjar frĂ„n installationsprocessen och slutar med att skicka förfrĂ„gningar.

Denna databas har en mycket lĂ„g ingĂ„ngströskel. Även en genomsnittlig skicklig utvecklare kan installera denna databas pĂ„ nĂ„gra minuter och börja anvĂ€nda den. Allt fungerar tydligt. Även personer som Ă€r nya i Linux kan snabbt hantera installationen och göra de enklaste operationerna. Om tidigare, med orden Big Data, Hadoop, Google BigTable, HDFS, en vanlig utvecklare hade idĂ©er om att det handlade om nĂ„gra terabyte, petabyte, att vissa övermĂ€nniskor Ă€r involverade i instĂ€llningar och utveckling för dessa system, dĂ„ med tillkomsten av ClickHouse databas, fick vi ett enkelt, begripligt verktyg med vilket du kan lösa ett tidigare ouppnĂ„eligt antal uppgifter. Det tar bara en ganska genomsnittlig maskin och fem minuter att installera. Det vill sĂ€ga, vi fick en sĂ„dan databas som till exempel MySql, men bara för att lagra miljarder poster! En viss superarkiverare med SQL-sprĂ„ket. Det Ă€r som att folk fick utomjordingars vapen.

Om vÄrt loggningssystem

För att samla in information anvÀnds IIS-loggfiler av webbapplikationer i standardformat (vi analyserar ocksÄ för nÀrvarande applikationsloggar, men huvudmÄlet i pilotstadiet Àr att samla in IIS-loggar).

Vi kunde inte helt överge ELK-stacken av olika anledningar, och vi fortsÀtter att anvÀnda LogStash- och Filebeat-komponenterna, som har visat sig vÀl och fungerar ganska tillförlitligt och förutsÀgbart.

Det allmÀnna loggningsschemat visas i figuren nedan:

ClickHouse Database for Humans, eller Alien Technologies

En funktion för att skriva data till ClickHouse-databasen Àr sÀllsynta (en gÄng per sekund) infogning av poster i stora partier. Detta Àr tydligen den mest "problematiska" delen som du stöter pÄ nÀr du först upplever att arbeta med ClickHouse-databasen: schemat blir lite mer komplicerat.
Plugin för LogStash, som direkt infogar data i ClickHouse, hjÀlpte mycket hÀr. Denna komponent distribueras pÄ samma server som sjÀlva databasen. SÄ generellt sett rekommenderas det inte att göra det, utan ur en praktisk synvinkel, för att inte skapa separata servrar medan den Àr utplacerad pÄ samma server. Vi har inte observerat nÄgra fel eller resurskonflikter med databasen. Dessutom bör det noteras att plugin har en mekanism för att försöka igen vid fel. Och i hÀndelse av fel skriver plugin till disken en sats med data som inte kunde infogas (filformatet Àr bekvÀmt: efter redigering kan du enkelt infoga den korrigerade batchen med clickhouse-klient).

En komplett lista över programvara som anvÀnds i schemat presenteras i tabellen:

Lista över anvÀnda programvara

namn

beskrivning

LĂ€nk till distribution

nginx

OmvÀnd proxy för att begrÀnsa Ätkomst av portar och organisera auktorisering

AnvÀnds för nÀrvarande inte i schemat

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

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

FileBeat

Överföring av filloggar.

https://www.elastic.co/downloads/beats/filebeat (distributionssats för Windows 64bit).

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

LogStash

Loggsamlare.

AnvÀnds för att samla in loggar frÄn FileBeat, samt för att samla in loggar frÄn RabbitMQ-kön (för servrar som finns i DMZ.)

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

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

Logstash-output-clickhouse

Loagstash-plugin för att överföra loggar till ClickHouse-databasen i omgÄngar

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

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

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

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

klickhus

Logglagring 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

Notera. FrÄn och med augusti 2018 dök "normala" rpm-byggen för RHEL upp i Yandex-förvaret, sÄ du kan försöka anvÀnda dem. Vid tidpunkten för installationen anvÀnde vi paket byggda av Altinity.

grafana

Loggvisualisering. Konfigurera instrumentpaneler

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos(64 Bit) - senaste versionen

ClickHouse-datakÀlla för Grafana 4.6+

Plugin för Grafana med ClickHouse datakÀlla

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

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

LogStash

Logga router frÄn FileBeat till RabbitMQ-kön.

Notera. TyvÀrr skickar FileBeat inte ut direkt till RabbitMQ, sÄ en mellanlÀnk i form av Logstash krÀvs

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

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

RabbitMQ

Meddelandekö. Detta Àr en buffert av loggposter 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 (krÀvs för RabbitMQ)

Erlang körtid. KrÀvs för att RabbitMQ ska fungera

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 presenteras i följande tabell:

namn

VĂ€rde

Notera

konfiguration

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

Du bör vara uppmÀrksam pÄ tipsen för att anvÀnda ClickHouse-databasen (https://clickhouse.yandex/docs/ru/operations/tips/)

AllmÀn systemprogramvara

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Som du kan se Àr detta en vanlig arbetsstation.

Strukturen för tabellen för att lagra loggar Àr som följer:

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 anvÀnder standardpartitionering (efter mÄnad) och indexgranularitet. Alla fÀlt motsvarar praktiskt taget IIS-loggposter för att logga http-förfrÄgningar. Separat noterar vi att det finns separata fÀlt för att lagra utm-taggar (de tolkas vid insÀttningsstadiet i tabellen frÄn frÄgestrÀngsfÀltet).

Dessutom har flera systemfÀlt lagts till i tabellen för att lagra information om system, komponenter, servrar. För en beskrivning av dessa fÀlt, se tabellen nedan. I en tabell lagrar vi loggar för flera system.

namn

beskrivning

Exempel

fld_app_name

Applikations-/systemnamn
Giltiga vÀrden:

  • site1.domain.com Extern webbplats 1
  • site2.domain.com Extern webbplats 2
  • internal-site1.domain.local Intern webbplats 1

site1.domain.com

fld_app_module

Systemmodul
Giltiga vÀrden:

  • webb - Webbplats
  • svc - WebbplatstjĂ€nst
  • intgr - Integration Web Service
  • bo - Admin (BackOffice)

webb

fld_website_name

Webbplatsnamn i IIS

Flera system kan distribueras pÄ en server, eller till och med flera instanser av en systemmodul

webbhuvud

fld_server_name

Server namn

web1.domain.com

fld_log_file_name

SökvÀg till loggfilen pÄ servern

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

Detta gör att du effektivt kan bygga grafer i Grafana. Visa till exempel förfrÄgningar frÄn frontend av ett visst system. Detta liknar webbplatsrÀknaren i Yandex.Metrica.

HÀr Àr lite statistik om anvÀndningen av databasen under tvÄ mÄnader.

Antal poster uppdelade efter system och deras 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 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 av datakomprimering i kolumner

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.

Beskrivning av anvÀnda komponenter

FileBeat. Överföra filloggar

Den hÀr komponenten spÄrar Àndringar av loggfiler pÄ disken och skickar informationen till LogStash. Installerad pÄ alla servrar dÀr loggfiler skrivs (vanligtvis IIS). Fungerar i svanslÀge (dvs. överför endast de tillagda posterna till filen). Men separat kan den konfigureras för att överföra hela filer. Detta Àr anvÀndbart nÀr du behöver ladda ner data frÄn tidigare mÄnader. LÀgg bara loggfilen i en mapp sÄ kommer den att lÀsa den i sin helhet.

NÀr tjÀnsten stoppas överförs inte data lÀngre vidare till lagringen.

Ett exempel pÄ en konfiguration ser ut sÄ hÀr:

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

Den hÀr komponenten Àr designad för att ta emot loggposter frÄn FileBeat (eller genom RabbitMQ-kön), analysera och infoga batcher i ClickHouse-databasen.

För att infogas i ClickHouse anvÀnds plugin-programmet Logstash-output-clickhouse. Logstash-pluginet har en begÀran om försök, men med en vanlig avstÀngning Àr det bÀttre att stoppa sjÀlva tjÀnsten. NÀr det stoppas kommer meddelanden att samlas i RabbitMQ-kön, sÄ om stoppet Àr under en lÄng tid Àr det bÀttre att stoppa Filebeats pÄ servrarna. I ett schema dÀr RabbitMQ inte anvÀnds (pÄ det lokala nÀtverket skickar Filebeat loggar direkt till Logstash), fungerar Filebeats ganska acceptabelt och sÀkert, sÄ för dem gÄr otillgÀngligheten av utdata utan konsekvenser.

Ett exempel pÄ en konfiguration ser ut sÄ hÀr:

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"

klickhus. Logglagring

Loggar för alla system sparas i en tabell (se i början av artikeln). Den Àr utformad för att lagra information om förfrÄgningar: alla parametrar Àr lika för olika format, till exempel IIS-loggar, apache- och nginx-loggar. För applikationsloggar dÀr till exempel fel, informationsmeddelanden, varningar registreras, kommer en separat tabell att tillhandahÄllas med lÀmplig struktur (för nÀrvarande pÄ designstadiet).

NÀr du designar en tabell Àr det mycket viktigt att bestÀmma primÀrnyckeln (med vilken data kommer att sorteras under lagring). Graden av datakomprimering och frÄgehastighet beror pÄ detta. I vÄrt exempel Àr nyckeln
BESTÄLL EFTER (fld_app_name, fld_app_module, logdatetime)
Det vill sÀga genom namnet pÄ systemet, namnet pÄ systemkomponenten och datumet för hÀndelsen. Till en början kom datumet för evenemanget först. Efter att ha flyttat den till den sista platsen började frÄgorna fungera ungefÀr dubbelt sÄ snabbt. Att Àndra primÀrnyckeln krÀver att tabellen Äterskapas och data laddas upp igen sÄ att ClickHouse sorterar om data pÄ disken. Detta Àr en svÄr operation, sÄ det Àr lÀmpligt att i förvÀg tÀnka noga pÄ vad som ska ingÄ i sorteringsnyckeln.

Det bör ocksÄ noteras att datatypen LowCardinality har förekommit i relativt nya versioner. NÀr du anvÀnder den reduceras storleken pÄ komprimerad data drastiskt för de fÀlt som har lÄg kardinalitet (fÄ alternativ).

Vi anvÀnder för nÀrvarande version 19.6 och vi planerar att försöka uppdatera till den senaste versionen. De har sÄ underbara funktioner som Adaptive Granularity, Skipping-index och DoubleDelta-codec, till exempel.

Som standard Àr loggningsnivÄn instÀlld pÄ spÄrning under installationen. Loggarna roteras och arkiveras, men de expanderar samtidigt upp till en gigabyte. Om det inte finns nÄgot behov kan du stÀlla in varningsnivÄn, dÄ minskas storleken pÄ stocken drastiskt. LoggningsinstÀllningen stÀlls in i filen config.xml:

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

NÄgra anvÀndbara kommandon

ĐŸĐŸŃĐșĐŸĐ»ŃŒĐșу ĐŸŃ€ĐžĐłĐžĐœĐ°Đ»ŃŒĐœŃ‹Đ” паĐșДты ŃƒŃŃ‚Đ°ĐœĐŸĐČĐșĐž ŃĐŸĐ±ĐžŃ€Đ°ŃŽŃ‚ŃŃ ĐżĐŸ 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. Logga router frÄn FileBeat till RabbitMQ-kö

Denna komponent anvÀnds för att dirigera loggar som kommer frÄn FileBeat till RabbitMQ-kön. Det finns tvÄ punkter hÀr:

  1. TyvÀrr har FileBeat inget utdataplugin för att skriva direkt till RabbitMQ. Och sÄdan funktionalitet, att döma av problemet pÄ deras github, Àr inte planerad för implementering. Det finns ett plugin för Kafka, men av nÄgon anledning kan vi inte anvÀnda det hemma.
  2. Det finns krav för att samla in loggar i DMZ. Baserat pÄ dem mÄste loggarna först lÀggas till i kön och sedan lÀser LogStash in posterna frÄn kön utifrÄn.

DÀrför, speciellt för servrar som finns i en DMZ, Àr det nödvÀndigt att anvÀnda ett sÄ lite komplicerat schema. Ett exempel pÄ en konfiguration ser ut sÄ hÀr:

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. meddelandekö

Den hĂ€r komponenten anvĂ€nds för att buffra loggposter i DMZ. Inspelning görs genom ett gĂ€ng Filebeat → LogStash. AvlĂ€sning görs utanför DMZ via LogStash. NĂ€r man anvĂ€nder RabboitMQ behandlas cirka 4 tusen meddelanden per sekund.

Meddelandedirigering konfigureras med systemnamn, dvs baserat pÄ FileBeat-konfigurationsdata. Alla meddelanden gÄr till en kö. Om kötjÀnsten av nÄgon anledning stoppas, kommer detta inte att leda till förlust av meddelanden: FileBeats kommer att ta emot anslutningsfel och tillfÀlligt avbryta sÀndningen. Och LogStash som lÀser frÄn kön kommer ocksÄ att ta emot nÀtverksfel och vÀnta pÄ att anslutningen ska ÄterstÀllas. I det hÀr fallet kommer data naturligtvis inte lÀngre att skrivas till databasen.

Följande instruktioner anvÀnds för att skapa och konfigurera 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. InstrumentbrÀdor

Denna komponent anvÀnds för att visualisera övervakningsdata. I det hÀr fallet mÄste du installera ClickHouse-datakÀllan för Grafana 4.6+ plugin. Vi var tvungna att finjustera det lite för att förbÀttra effektiviteten för bearbetning av SQL-filter pÄ instrumentpanelen.

Till exempel anvÀnder vi variabler, och om de inte Àr instÀllda i filterfÀltet, sÄ vill vi att det inte genererar ett villkor i formulÀrets WHERE ( uriStem = » AND uriStem != » ). I det hÀr fallet kommer ClickHouse att lÀsa kolumnen uriStem. I allmÀnhet provade vi olika alternativ och korrigerade sÄ smÄningom pluginet (makrot $valueIfEmpty) sÄ att det i fallet med ett tomt vÀrde returnerar 1, utan att nÀmna sjÀlva kolumnen.

Och nu kan du anvÀnda den hÀr frÄgan för 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 översÀtts till denna SQL (observera att de tomma uriStem-fÀlten har konverterats till bara 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

Slutsats

Utseendet pÄ ClickHouse-databasen har blivit en milstolpe pÄ marknaden. Det var svÄrt att förestÀlla sig att vi, helt gratis, pÄ ett ögonblick var bevÀpnade med ett kraftfullt och praktiskt verktyg för att arbeta med big data. Naturligtvis, med ökande behov (till exempel skÀrning och replikering till flera servrar), kommer systemet att bli mer komplicerat. Men vid första intryck Àr det mycket trevligt att arbeta med den hÀr databasen. Det kan ses att produkten Àr gjord "för mÀnniskor".

JÀmfört med ElasticSearch berÀknas kostnaden för lagring och bearbetning av loggar minska med fem till tio gÄnger. Med andra ord, om vi för den aktuella datamÀngden skulle behöva sÀtta upp ett kluster med flera maskiner, dÄ nÀr vi anvÀnder ClickHouse rÀcker det med en lÄgeffektsmaskin för oss. Ja, sjÀlvklart har ElasticSearch Àven datakomprimeringsmekanismer pÄ disk och andra funktioner som avsevÀrt kan minska resursförbrukningen, men jÀmfört med ClickHouse blir detta dyrare.

Utan nÄgra speciella optimeringar frÄn vÄr sida, med standardinstÀllningar, fungerar laddning av data och hÀmtning frÄn databasen med otrolig hastighet. Vi har inte mycket data Ànnu (cirka 200 miljoner poster), men sjÀlva servern Àr svag. Vi kan komma att anvÀnda det hÀr verktyget i framtiden för andra ÀndamÄl som inte Àr relaterade till lagring av loggar. Till exempel för end-to-end-analys, inom omrÄdet sÀkerhet, maskininlÀrning.

I slutet lite om för- och nackdelar.

Nackdelar

  1. Laddar poster i stora partier. Å ena sidan Ă€r detta en funktion, men du mĂ„ste fortfarande anvĂ€nda ytterligare komponenter för att buffra poster. Denna uppgift Ă€r inte alltid lĂ€tt, men Ă€ndĂ„ lösbar. Och jag skulle vilja förenkla schemat.
  2. Vissa exotiska funktioner eller nya funktioner gÄr ofta sönder i nya versioner. Detta skapar oro, vilket minskar lusten att uppgradera till en ny version. Till exempel Àr Kafka-bordmotorn en mycket anvÀndbar funktion som lÄter dig lÀsa hÀndelser frÄn Kafka direkt, utan att implementera konsumenter. Men att döma av antalet Issues pÄ github, Àr vi fortfarande noga med att inte anvÀnda denna motor i produktionen. Men om du inte gör plötsliga gester Ät sidan och anvÀnder huvudfunktionaliteten sÄ fungerar det stabilt.

Fördelar

  1. Saknar inte farten.
  2. LÄg instegströskel.
  3. Öppen kĂ€lla.
  4. Fri.
  5. Skalar bra (skÀrning/replikering ur lÄdan)
  6. IngÄr i registret över rysk programvara som rekommenderas av kommunikationsministeriet.
  7. NÀrvaron av officiellt stöd frÄn Yandex.

KĂ€lla: will.com

LĂ€gg en kommentar