ClickHouse Database para sa mga Tao, o Alien Technologies

Aleksey Lizunov, Pinuno ng Competence Center para sa Remote Service Channels ng Directorate of Information Technologies ng MKB

ClickHouse Database para sa mga Tao, o Alien Technologies

Bilang alternatibo sa ELK stack (ElasticSearch, Logstash, Kibana), kami ay gumagawa ng pananaliksik sa paggamit ng ClickHouse database bilang isang data store para sa mga log.

Sa artikulong ito, nais naming pag-usapan ang aming karanasan sa paggamit ng database ng ClickHouse at ang mga paunang resulta ng pilot operation. Dapat pansinin kaagad na ang mga resulta ay kahanga-hanga.


ClickHouse Database para sa mga Tao, o Alien Technologies

Susunod, ilalarawan namin nang mas detalyado kung paano na-configure ang aming system, at kung anong mga bahagi ang binubuo nito. Ngunit ngayon nais kong pag-usapan ang kaunti tungkol sa database na ito sa kabuuan, at kung bakit ito ay nagkakahalaga ng pagbibigay pansin. Ang ClickHouse database ay isang high-performance analytical columnar database mula sa Yandex. Ginagamit ito sa mga serbisyo ng Yandex, sa una ito ang pangunahing imbakan ng data para sa Yandex.Metrica. Open-source system, libre. Mula sa pananaw ng isang developer, lagi kong iniisip kung paano nila ito ipinatupad, dahil may napakalaking data. At ang user interface mismo ng Metrica ay napaka-flexible at mabilis. Sa unang pagkakakilala sa database na ito, ang impresyon ay: "Buweno, sa wakas! Ginawa para sa bayan! Simula sa proseso ng pag-install at nagtatapos sa pagpapadala ng mga kahilingan.

Ang database na ito ay may napakababang entry threshold. Kahit na ang isang average-skilled na developer ay maaaring i-install ang database na ito sa loob ng ilang minuto at simulang gamitin ito. Ang lahat ay gumagana nang malinaw. Kahit na ang mga taong bago sa Linux ay maaaring mabilis na mahawakan ang pag-install at gawin ang mga pinakasimpleng operasyon. Kung mas maaga, sa mga salitang Big Data, Hadoop, Google BigTable, HDFS, isang ordinaryong developer ay may mga ideya na ito ay tungkol sa ilang terabytes, petabytes, na ang ilang mga superhuman ay nakikibahagi sa mga setting at pag-unlad para sa mga system na ito, pagkatapos ay sa pagdating ng ClickHouse database, nakakuha kami ng simple, nauunawaan na tool kung saan maaari mong lutasin ang isang dating hindi maabot na hanay ng mga gawain. Ito ay tumatagal lamang ng isang medyo average na makina at limang minuto upang mai-install. Iyon ay, nakakuha kami ng isang database tulad ng, halimbawa, MySql, ngunit para lamang sa pag-iimbak ng bilyun-bilyong mga tala! Isang tiyak na super-archiver na may wikang SQL. Parang inabot sa mga tao ang mga armas ng mga dayuhan.

Tungkol sa aming sistema ng pag-log

Upang mangolekta ng impormasyon, ang mga IIS log file ng karaniwang format na mga web application ay ginagamit (kasalukuyan din kaming nag-parse ng mga log ng application, ngunit ang pangunahing layunin sa yugto ng pilot ay upang mangolekta ng mga log ng IIS).

Para sa iba't ibang mga kadahilanan, hindi namin ganap na abandunahin ang ELK stack, at patuloy naming ginagamit ang mga bahagi ng LogStash at Filebeat, na napatunayang mabuti ang kanilang mga sarili at gumagana nang lubos na maaasahan at predictably.

Ang pangkalahatang scheme ng pag-log ay ipinapakita sa figure sa ibaba:

ClickHouse Database para sa mga Tao, o Alien Technologies

Ang isang tampok ng pagsulat ng data sa database ng ClickHouse ay madalang (isang beses bawat segundo) na pagpasok ng mga tala sa malalaking batch. Ito, tila, ay ang pinaka "problema" na bahagi na iyong naranasan noong una mong naranasan ang pagtatrabaho sa database ng ClickHouse: ang pamamaraan ay nagiging mas kumplikado.
Ang plugin para sa LogStash, na direktang naglalagay ng data sa ClickHouse, ay nakatulong ng malaki dito. Ang bahaging ito ay naka-deploy sa parehong server bilang ang database mismo. Kaya, sa pangkalahatan, hindi inirerekomenda na gawin ito, ngunit mula sa isang praktikal na punto ng view, upang hindi makagawa ng hiwalay na mga server habang ito ay naka-deploy sa parehong server. Wala kaming nakitang anumang mga pagkabigo o salungatan sa mapagkukunan sa database. Bilang karagdagan, dapat tandaan na ang plugin ay may mekanismong muling subukan kung sakaling magkaroon ng mga error. At sa kaso ng mga error, ang plugin ay nagsusulat sa disk ng isang batch ng data na hindi maipasok (ang format ng file ay maginhawa: pagkatapos ng pag-edit, madali mong maipasok ang naitama na batch gamit ang clickhouse-client).

Ang isang kumpletong listahan ng software na ginamit sa scheme ay ipinakita sa talahanayan:

Listahan ng software na ginamit

Pangalan

Описание

Link sa pamamahagi

nginx

Reverse-proxy upang paghigpitan ang pag-access ng mga port at ayusin ang pahintulot

Kasalukuyang hindi ginagamit sa scheme

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

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

FileBeat

Paglipat ng mga tala ng file.

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

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

logstash

Tagakolekta ng log.

Ginagamit upang mangolekta ng mga log mula sa FileBeat, pati na rin upang mangolekta ng mga log mula sa RabbitMQ queue (para sa mga server na nasa DMZ.)

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

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

Logstash-output-clickhouse

Loagstash plugin para sa paglilipat ng mga log sa ClickHouse database sa mga batch

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

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

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

/usr/share/logstash/bin/logstash-plugin i-install ang logstash-filter-multiline

clickhouse

Imbakan ng log 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

Tandaan. Simula Agosto 2018, lumabas ang "normal" na rpm para sa RHEL sa imbakan ng Yandex, kaya maaari mong subukang gamitin ang mga ito. Sa oras ng pag-install, gumagamit kami ng mga pakete na binuo ng Altinity.

grafana

Visualization ng log. Pagse-set up ng mga dashboard

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos(64 Bit) - pinakabagong bersyon

ClickHouse datasource para sa Grafana 4.6+

Plugin para sa Grafana na may pinagmumulan ng data ng ClickHouse

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

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

logstash

Mag-log router mula sa FileBeat hanggang sa RabbitMQ queue.

Tandaan. Sa kasamaang palad, ang FileBeat ay walang direktang output sa RabbitMQ, kaya ang isang intermediate na link sa anyo ng Logstash ay kinakailangan

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

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

Kuneho MQ

pila ng mensahe. Ito ang log buffer sa 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 (Kinakailangan para sa RabbitMQ)

Erlang runtime. Kinakailangan para gumana ang RabbitMQ

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

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

Ang configuration ng server na may database ng ClickHouse ay ipinakita sa sumusunod na talahanayan:

Pangalan

Halaga

Nota

Configuration

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

Kinakailangang bigyang pansin ang mga tip para sa pagpapatakbo ng database ng ClickHouse (https://clickhouse.yandex/docs/ru/operations/tips/)

Pangkalahatang software ng system

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Tulad ng nakikita mo, ito ay isang ordinaryong workstation.

Ang istraktura ng talahanayan para sa pag-iimbak ng mga log ay ang mga sumusunod:

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;

Gumagamit kami ng default na partitioning (ayon sa buwan) at index granularity. Ang lahat ng mga patlang ay halos tumutugma sa mga entry ng log ng IIS para sa pag-log ng mga kahilingan sa http. Hiwalay, tandaan namin na mayroong magkahiwalay na mga patlang para sa pag-iimbak ng mga utm-tag (na-parse ang mga ito sa yugto ng pagpasok sa talahanayan mula sa field ng string ng query).

Gayundin, maraming mga patlang ng system ang naidagdag sa talahanayan upang mag-imbak ng impormasyon tungkol sa mga system, mga bahagi, mga server. Tingnan ang talahanayan sa ibaba para sa paglalarawan ng mga field na ito. Sa isang table, nag-iimbak kami ng mga log para sa ilang system.

Pangalan

Описание

Halimbawa

fld_app_name

Pangalan ng application/system
Mga wastong halaga:

  • site1.domain.com Panlabas na site 1
  • site2.domain.com Panlabas na site 2
  • internal-site1.domain.local Panloob na site 1

site1.domain.com

fld_app_module

Module ng system
Mga wastong halaga:

  • web - Website
  • svc - Serbisyo sa web site
  • intgr - Integration Web Service
  • bo - Admin (BackOffice)

web

fld_website_name

Pangalan ng site sa IIS

Maraming mga sistema ang maaaring i-deploy sa isang server, o kahit na ilang mga pagkakataon ng isang module ng system

web main

fld_server_name

Pangalan ng server

web1.domain.com

fld_log_file_name

Path sa log file sa server

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

Nagbibigay-daan ito sa iyo na mahusay na bumuo ng mga graph sa Grafana. Halimbawa, tingnan ang mga kahilingan mula sa frontend ng isang partikular na system. Ito ay katulad ng site counter sa Yandex.Metrica.

Narito ang ilang mga istatistika sa paggamit ng database sa loob ng dalawang buwan.

Bilang ng mga tala na pinaghiwa-hiwalay ayon sa mga system at mga bahagi ng mga ito

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

Ang dami ng data sa disk

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.

Degree ng data compression sa mga column

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.

Paglalarawan ng mga ginamit na bahagi

FileBeat. Paglilipat ng mga tala ng file

Sinusubaybayan ng component na ito ang mga pagbabago sa mga log file sa disk at ipinapasa ang impormasyon sa LogStash. Naka-install sa lahat ng mga server kung saan nakasulat ang mga log file (karaniwan ay IIS). Gumagana sa tail mode (ibig sabihin, inililipat lamang ang mga idinagdag na tala sa file). Ngunit hiwalay na maaari itong i-configure upang ilipat ang buong mga file. Ito ay kapaki-pakinabang kapag kailangan mong mag-download ng data mula sa mga nakaraang buwan. Ilagay lamang ang log file sa isang folder at babasahin ito nang buo.

Kapag itinigil ang serbisyo, hindi na maililipat pa ang data sa storage.

Ang isang halimbawang pagsasaayos ay ganito ang hitsura:

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. Kolektor ng Log

Ang bahaging ito ay idinisenyo upang makatanggap ng mga log entries mula sa FileBeat (o sa pamamagitan ng RabbitMQ queue), pag-parse at pagpasok ng mga batch sa ClickHouse database.

Para sa pagpasok sa ClickHouse, ginagamit ang Logstash-output-clickhouse plugin. Ang Logstash plugin ay may mekanismo ng paghiling na muling subukan, ngunit sa isang regular na pagsasara, mas mahusay na ihinto ang serbisyo mismo. Kapag huminto, maiipon ang mga mensahe sa queue ng RabbitMQ, kaya kung matagal ang paghinto, mas mabuting ihinto ang Filebeats sa mga server. Sa isang pamamaraan kung saan ang RabbitMQ ay hindi ginagamit (sa lokal na network, ang Filebeat ay direktang nagpapadala ng mga log sa Logstash), ang Filebeats ay gumagana nang lubos na katanggap-tanggap at ligtas, kaya para sa kanila ang hindi pagkakaroon ng output ay pumasa nang walang mga kahihinatnan.

Ang isang halimbawang pagsasaayos ay ganito ang hitsura:

log_web__filebeat_clickhouse.conf

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

pipelines.yml

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

clickhouse. Imbakan ng log

Ang mga log para sa lahat ng mga sistema ay naka-imbak sa isang talahanayan (tingnan sa simula ng artikulo). Ito ay inilaan upang mag-imbak ng impormasyon tungkol sa mga kahilingan: ang lahat ng mga parameter ay magkatulad para sa iba't ibang mga format, tulad ng IIS logs, apache at nginx logs. Para sa mga log ng application, kung saan, halimbawa, ang mga error, mga mensahe ng impormasyon, mga babala ay naitala, ang isang hiwalay na talahanayan ay ipagkakaloob sa naaangkop na istraktura (kasalukuyang nasa yugto ng disenyo).

Kapag nagdidisenyo ng isang talahanayan, napakahalaga na magpasya sa pangunahing susi (kung saan ang data ay pag-uuri-uriin sa panahon ng imbakan). Ang antas ng compression ng data at bilis ng query ay nakasalalay dito. Sa aming halimbawa, ang susi ay
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Iyon ay, sa pamamagitan ng pangalan ng system, ang pangalan ng bahagi ng system at ang petsa ng kaganapan. Sa una, ang petsa ng kaganapan ay nauna. Matapos itong ilipat sa huling lugar, nagsimulang gumana nang dalawang beses nang mas mabilis ang mga query. Ang pagpapalit ng pangunahing susi ay mangangailangan ng muling paggawa ng talahanayan at pag-reload ng data upang muling ayusin ng ClickHouse ang data sa disk. Ito ay isang mabigat na operasyon, kaya magandang ideya na mag-isip nang husto tungkol sa kung ano ang dapat isama sa sort key.

Dapat ding tandaan na ang uri ng data ng LowCardinality ay medyo lumitaw sa mga kamakailang bersyon. Kapag ginagamit ito, ang laki ng naka-compress na data ay lubhang nababawasan para sa mga field na may mababang cardinality (kaunting mga pagpipilian).

Ang bersyon 19.6 ay kasalukuyang ginagamit at plano naming subukang mag-update sa pinakabagong bersyon. Mayroon silang napakagandang feature gaya ng Adaptive Granularity, Skipping index at DoubleDelta codec, halimbawa.

Bilang default, sa panahon ng pag-install, ang antas ng pag-log ay nakatakda upang masubaybayan. Ang mga log ay pinaikot at naka-archive, ngunit sa parehong oras sila ay lumalawak hanggang sa isang gigabyte. Kung walang pangangailangan, maaari mong itakda ang antas ng babala, kung gayon ang laki ng log ay lubhang nabawasan. Ang setting ng pag-log ay nakatakda sa config.xml file:

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

Ilang kapaki-pakinabang na utos

Поскольку оригинальные пакеты установки собираются по 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. Mag-log router mula sa FileBeat hanggang sa RabbitMQ queue

Ginagamit ang bahaging ito upang iruta ang mga log na nagmumula sa FileBeat patungo sa queue ng RabbitMQ. Mayroong dalawang puntos dito:

  1. Sa kasamaang palad, ang FileBeat ay walang output na plugin upang direktang sumulat sa RabbitMQ. At ang gayong pag-andar, na hinuhusgahan ng isyu sa kanilang github, ay hindi binalak para sa pagpapatupad. Mayroong isang plugin para sa Kafka, ngunit sa ilang kadahilanan hindi namin ito magagamit sa bahay.
  2. May mga kinakailangan para sa pagkolekta ng mga log sa DMZ. Batay sa kanila, dapat munang idagdag ang mga log sa pila at pagkatapos ay babasahin ng LogStash ang mga entry mula sa pila mula sa labas.

Samakatuwid, ito ay para sa kaso kung saan ang mga server ay matatagpuan sa DMZ na ang isa ay kailangang gumamit ng isang bahagyang kumplikadong pamamaraan. Ang isang halimbawang pagsasaayos ay ganito ang hitsura:

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. pila ng mensahe

Ang bahaging ito ay ginagamit upang i-buffer ang mga entry sa log sa DMZ. Ang pagre-record ay ginagawa sa pamamagitan ng isang grupo ng Filebeat → LogStash. Ang pagbabasa ay ginagawa mula sa labas ng DMZ sa pamamagitan ng LogStash. Kapag nagpapatakbo sa pamamagitan ng RabboitMQ, humigit-kumulang 4 na libong mensahe bawat segundo ang pinoproseso.

Ang pagruruta ng mensahe ay na-configure ayon sa pangalan ng system, ibig sabihin, batay sa data ng pagsasaayos ng FileBeat. Napupunta ang lahat ng mensahe sa isang pila. Kung sa ilang kadahilanan ay huminto ang serbisyo sa pagpila, hindi ito hahantong sa pagkawala ng mga mensahe: Makakatanggap ang FileBeats ng mga error sa koneksyon at pansamantalang sususpindihin ang pagpapadala. At ang LogStash na nagbabasa mula sa pila ay makakatanggap din ng mga error sa network at maghihintay na maibalik ang koneksyon. Sa kasong ito, ang data, siyempre, ay hindi na isusulat sa database.

Ang mga sumusunod na tagubilin ay ginagamit upang lumikha at mag-configure ng mga pila:

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. Mga dashboard

Ang bahaging ito ay ginagamit upang mailarawan ang data ng pagsubaybay. Sa kasong ito, kailangan mong i-install ang ClickHouse datasource para sa Grafana 4.6+ plugin. Kinailangan naming i-tweak ito nang kaunti upang mapabuti ang kahusayan ng pagproseso ng mga filter ng SQL sa dashboard.

Halimbawa, gumagamit kami ng mga variable, at kung hindi nakatakda ang mga ito sa field ng filter, gusto naming huwag itong bumuo ng kundisyon sa WHERE ng form ( uriStem = » AND uriStem != » ). Sa kasong ito, babasahin ng ClickHouse ang column ng uriStem. Sa pangkalahatan, sinubukan namin ang iba't ibang mga opsyon at kalaunan ay naitama ang plugin (ang $valueIfEmpty macro) upang sa kaso ng isang walang laman na halaga, ito ay nagbabalik ng 1, nang hindi binabanggit ang mismong column.

At ngayon ay maaari mong gamitin ang query na ito para sa graph

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

na isinasalin sa SQL na ito (tandaan na ang mga walang laman na field ng uriStem ay na-convert sa 1 lang)

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

Konklusyon

Ang hitsura ng database ng ClickHouse ay naging isang landmark na kaganapan sa merkado. Mahirap isipin na, ganap na walang bayad, sa isang iglap ay armado kami ng isang malakas at praktikal na tool para sa pagtatrabaho sa malaking data. Siyempre, sa pagtaas ng mga pangangailangan (halimbawa, sharding at pagtitiklop sa maramihang mga server), ang scheme ay magiging mas kumplikado. Ngunit sa mga unang impression, ang pagtatrabaho sa database na ito ay napaka-kaaya-aya. Ito ay makikita na ang produkto ay ginawa "para sa mga tao."

Kung ikukumpara sa ElasticSearch, ang halaga ng pag-iimbak at pagproseso ng mga log ay tinatayang mababawasan ng lima hanggang sampung beses. Sa madaling salita, kung para sa kasalukuyang dami ng data ay kailangan naming mag-set up ng isang kumpol ng ilang mga makina, kung gayon kapag gumagamit ng ClickHouse, isang mababang-kapangyarihan na makina ay sapat na para sa amin. Oo, siyempre, ang ElasticSearch ay mayroon ding on-disk data compression na mekanismo at iba pang mga tampok na maaaring makabuluhang bawasan ang pagkonsumo ng mapagkukunan, ngunit kumpara sa ClickHouse, ito ay magiging mas mahal.

Nang walang anumang mga espesyal na pag-optimize sa aming bahagi, sa mga default na setting, ang paglo-load ng data at pagpili mula sa database ay gumagana sa isang kamangha-manghang bilis. Wala pa kaming gaanong data (mga 200 milyong record), ngunit ang server mismo ay mahina. Magagamit namin ang tool na ito sa hinaharap para sa iba pang layuning hindi nauugnay sa pag-iimbak ng mga log. Halimbawa, para sa end-to-end analytics, sa larangan ng seguridad, machine learning.

Sa dulo, kaunti tungkol sa mga kalamangan at kahinaan.

Cons

  1. Naglo-load ng mga tala sa malalaking batch. Sa isang banda, ito ay isang tampok, ngunit kailangan mo pa ring gumamit ng mga karagdagang bahagi para sa mga buffering record. Ang gawaing ito ay hindi laging madali, ngunit nalulusaw pa rin. At gusto kong gawing simple ang scheme.
  2. Ang ilang kakaibang functionality o mga bagong feature ay madalas na masira sa mga bagong bersyon. Nagdudulot ito ng pag-aalala, na binabawasan ang pagnanais na mag-upgrade sa isang bagong bersyon. Halimbawa, ang Kafka table engine ay isang napaka-kapaki-pakinabang na feature na nagbibigay-daan sa iyong direktang basahin ang mga kaganapan mula sa Kafka, nang hindi nagpapatupad ng mga consumer. Ngunit sa paghusga sa bilang ng mga Isyu sa github, nag-iingat pa rin kami na huwag gamitin ang makinang ito sa produksyon. Gayunpaman, kung hindi ka gumawa ng biglaang mga galaw sa gilid at gamitin ang pangunahing pag-andar, pagkatapos ay gumagana ito nang matatag.

Pros

  1. Hindi bumabagal.
  2. Mababang threshold ng entry.
  3. open source.
  4. Libre ito.
  5. Mahusay ang pag-scale (pag-sharding/pagtitiklop sa labas ng kahon)
  6. Kasama sa rehistro ng Russian software na inirerekomenda ng Ministry of Communications.
  7. Ang pagkakaroon ng opisyal na suporta mula sa Yandex.

Pinagmulan: www.habr.com

Magdagdag ng komento