ClickHouse Datumbazo por Homoj, aŭ Alien Technologies

Alexey Lizunov, estro de la kompetenteca centro por foraj servaj kanaloj de la Informa Teknologio-Direkto de la ICB

ClickHouse Datumbazo por Homoj, aŭ Alien Technologies

Kiel alternativo al la ELK-stako (ElasticSearch, Logstash, Kibana), ni faras esploradon pri uzado de la datumbazo ClickHouse kiel datumstokado por ŝtipoj.

En ĉi tiu artikolo ni ŝatus paroli pri nia sperto uzante la ClickHouse-datumbazon kaj antaŭajn rezultojn de pilota operacio. Indas tuj rimarki, ke la rezultoj estis imponaj.


ClickHouse Datumbazo por Homoj, aŭ Alien Technologies

Poste ni priskribos pli detale kiel nia sistemo estas agordita kaj el kiuj komponantoj ĝi konsistas. Sed nun mi ŝatus paroli iomete pri ĉi tiu datumbazo entute, kaj kial ĝi indas atenti. La ClickHouse-datumbazo estas alt-efikeca analiza kolumna datumbazo de Yandex. Uzita en Yandex-servoj, komence ĉi tio estas la ĉefa datumstokado por Yandex.Metrica. Malfermfonta sistemo, senpaga. El la vidpunkto de programisto, mi ĉiam scivolis, kiel ili efektivigis ĉi tion, ĉar ekzistas mirindaj datumoj. Kaj la uzantinterfaco de Metrica mem estas tre fleksebla kaj funkcias rapide. Kiam oni unue konatiĝas kun ĉi tiu datumbazo, oni ricevas la impreson: „Nu, finfine! Farita "por la homoj"! De la instala procezo ĝis sendado de petoj."

Ĉi tiu datumbazo havas tre malaltan enirbarieron. Eĉ averaĝa programisto povas instali ĉi tiun datumbazon en kelkaj minutoj kaj ekuzi ĝin. Ĉio funkcias glate. Eĉ homoj, kiuj estas novaj al Linukso, povas rapide elteni la instaladon kaj fari simplajn operaciojn. Se pli frue, aŭdinte la vortojn Big Data, Hadoop, Google BigTable, HDFS, la averaĝa programisto havis la ideon, ke ili parolas pri kelkaj terabajtoj, petabajtoj, ke iuj superhomoj okupiĝas pri starigo kaj disvolviĝo de ĉi tiuj sistemoj, tiam kun la alveno. de la datumbazo ClickHouse ni ricevis simplan, kompreneblan ilon, per kiu vi povas solvi antaŭe neatingeblan gamon da problemoj. Ĉio necesas estas unu sufiĉe averaĝa maŝino kaj kvin minutoj por instali. Tio estas, ni ricevis datumbazon kiel, ekzemple, MySql, sed nur por stoki miliardojn da rekordoj! Speco de superarkivilo kun SQL-lingvo. Estas kvazaŭ homoj ricevis eksterterajn armilojn.

Pri nia ŝtipkolekta sistemo

Por kolekti informojn, IIS-protokoloj de TTT-aplikoj de norma formato estas uzataj (ni ankaŭ nuntempe okupiĝas pri analizado de aplikaĵaj protokoloj, sed nia ĉefa celo en la pilota stadio estas kolekti IIS-protokolojn).

Ni ne povis tute forlasi la ELK-stakon pro diversaj kialoj, kaj ni daŭre uzas la komponantojn LogStash kaj Filebeat, kiuj pruvis sin bone kaj funkcias sufiĉe fidinde kaj antaŭvideble.

La ĝenerala registra skemo estas montrita en la figuro malsupre:

ClickHouse Datumbazo por Homoj, aŭ Alien Technologies

Karakterizaĵo de registrado de datumoj en la datumbazo ClickHouse estas la malofta (unufoje en sekundo) enmeto de rekordoj en grandaj aroj. Ĉi tio, ŝajne, estas la plej "problema" parto, kiun vi renkontas kiam vi laboras kun la datumbazo ClickHouse unuafoje: la skemo fariĝas iom pli komplika.
La kromaĵo por LogStash, kiu rekte enmetas datumojn en ClickHouse, multe helpis ĉi tie. Ĉi tiu komponanto estas deplojita sur la sama servilo kiel la datumbazo mem. Do, ĝenerale, oni ne rekomendas fari tion, sed el praktika vidpunkto, por ne krei apartajn servilojn dum ĝi estas deplojita sur la sama servilo. Ni ne observis malsukcesojn aŭ rimedkonfliktojn kun la datumbazo. Krome, oni devas rimarki, ke la kromaĵo havas retransmetan mekanismon en kazo de eraroj. Kaj en kazo de eraroj, la kromaĵo skribas al disko aron da datumoj, kiuj ne povus esti enmetitaj (la dosierformato estas oportuna: post redaktado, vi povas facile enmeti la korektitan aron per clickhouse-client).

Kompleta listo de programoj uzataj en la skemo estas prezentita en la tabelo:

Listo de uzataj programoj

nomo

Priskribo

Ligo al distribuo

NGINX

Inversa prokurilo por limigi aliron per haveno kaj organizi rajtigon

Nuntempe ne uzata en la skemo

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

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

FileBeat

Transdono de dosiero-protokoloj.

https://www.elastic.co/downloads/beats/filebeat (distribuo por Windows 64bit).

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

LogStash

Ŝtipkolektilo.

Uzita por kolekti protokolojn de FileBeat, kaj ankaŭ por kolekti protokolojn de la RabbitMQ-vico (por serviloj kiuj situas en la DMZ.)

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

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

Logstash- eligo- clickhouse

Aldonaĵo Loagstash por transloki protokolojn al la datumbazo ClickHouse en aroj

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

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

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

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

KlakuDomo

Ensalutu stokado 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

Notu. Ekde aŭgusto 2018, "normalaj" rpm-konstruoj por RHEL aperis en la Yandex-deponejo, do vi povas provi uzi ilin. En la momento de la instalado ni uzis pakaĵojn kompilitaj de Altinity.

grafana

Bildigo de ŝtipoj. Agordi panelojn

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 Bitoj) - plej nova versio

ClickHouse-datumfonto por Grafana 4.6+

Kromaĵo por Grafana kun datumfonto de ClickHouse

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

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

LogStash

Ensalutu enkursigilon de FileBeat al RabbitMQ-vico.

Notu. Bedaŭrinde FileBeat ne havas eligon rekte al RabbitMQ, do necesas meza ligilo en la formo de Logstash

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

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

KunikloMQ

Mesaĝovico. Ĉi tio estas bufro de protokolaj eniroj en la 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 Rultempo (Bezonata por RabbitMQ)

Erlang rultempo. Bezonata por ke RabbitMQ funkciu

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

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

La servila agordo kun la datumbazo ClickHouse estas prezentita en la sekva tabelo:

nomo

valoro

Примечание

Agordo

Diskodukto: 40 GB
RAM: 8GB
Procesoro: Kerno 2 2Ghz

Vi devus atenti la konsiletojn por uzi la datumbazon ClickHouse (https://clickhouse.yandex/docs/ru/operations/tips/)

Tutsistema programaro

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Kiel vi povas vidi, ĉi tio estas regula laborstacio.

La strukturo de la tabelo por stoki protokolojn estas kiel sekvas:

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;

Ni uzas defaŭltajn valorojn por dispartigo (monata) kaj indeksa granulareco. Ĉiuj kampoj praktike respondas al IIS-protokolo-enskriboj por registri http-petojn. Aparte, ni rimarkas, ke ekzistas apartaj kampoj por stoki utm-etikedojn (ili estas analizitaj en la stadio de enigo en la tabelon de la demanda ĉeno kampo).

Ankaŭ, pluraj sistemaj kampoj estis aldonitaj al la tabelo por stoki informojn pri sistemoj, komponentoj kaj serviloj. Por priskribo de ĉi tiuj kampoj, vidu la tabelon sube. En unu tabelo ni konservas protokolojn por pluraj sistemoj.

nomo

Priskribo

Ekzemplo:

fld_app_name

Apliko/sistema nomo
Validaj valoroj:

  • site1.domain.com Ekstera retejo 1
  • site2.domain.com Ekstera retejo 2
  • internal-site1.domain.local Interna retejo 1

retejo1.domajno.com

fld_app_module

Sistemmodulo
Validaj valoroj:

  • retejo - Retejo
  • svc — Reteja retservo
  • intgr — Reta integriga servo
  • bo — Administranto (BackOffice)

retejo

fld_retejo_nomo

Reteja nomo en IIS

Pluraj sistemoj povas esti deplojitaj sur unu servilo, aŭ eĉ pluraj kazoj de unu sistema modulo

retejo-ĉefa

fld_servilo_nomo

Servilonomo

retejo1.domajno.com

fld_log_dosiernomo

Vojo al la protokoldosiero sur la servilo

De:inetpublogsLogFiles
W3SVC1u_ex190711.log

Ĉi tio ebligas al vi efike konstrui grafikaĵojn en Grafana. Ekzemple, rigardu petojn de la antaŭa finaĵo de specifa sistemo. Ĉi tio similas al la reteja nombrilo en Yandex.Metrica.

Jen kelkaj statistikoj pri datumbaza uzado dum du monatoj.

Nombro de registroj laŭ sistemo kaj komponanto

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

Diska datumvolumo

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.

Kolumna datuma kunprema proporcio

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.

Priskribo de uzataj komponantoj

FileBeat. Transdono de dosierprotokoloj

Ĉi tiu komponanto monitoras ŝanĝojn al protokolaj dosieroj sur disko kaj pasas la informojn al LogStash. Instalita sur ĉiuj serviloj kie protokolaj dosieroj estas skribitaj (kutime IIS). Funkcias en vosta reĝimo (t.e., ĝi transdonas nur aldonitajn rekordojn al la dosiero). Sed vi povas aparte agordi ĝin por translokigi tutajn dosierojn. Ĉi tio estas oportuna kiam vi bezonas elŝuti datumojn de antaŭaj monatoj. Simple metu la protokoldosieron en dosierujon kaj ĝi legos ĝin tute.

Kiam la servo ĉesas, datumoj ĉesas esti transdonitaj plu al la stokado.

Ekzempla agordo aspektas jene:

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. Ŝtipkolektilo

Ĉi tiu komponanto estas desegnita por ricevi registrojn de FileBeat (aŭ per RabbitMQ-vico), analizi kaj enigi ilin en aroj en la datumbazon ClickHouse.

Por enmeti en ClickHouse, uzu la kromprogramon Logstash-output-clickhouse. La Logstash kromaĵo havas mekanismon por retrovi petojn, sed dum regula halto, estas pli bone ĉesigi la servon mem. Kiam ĉesigita, mesaĝoj akumuliĝos en la RabbitMQ-vico, do se la halto estas dum longa tempo, tiam estas pli bone ĉesigi Filebeats sur la serviloj. En skemo kie RabbitMQ ne estas uzata (en la loka reto Filebeat rekte sendas protokolojn al Logstash), Filebeats funkcias sufiĉe akceptebla kaj sekura, do por ili la malhavebleco de eligo ne havas konsekvencojn.

Ekzempla agordo aspektas jene:

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

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

KlakuDomo. Ensalutu stokado

Protokoloj por ĉiuj sistemoj estas konservitaj en unu tabelo (vidu komence de la artikolo). Ĝi estas desegnita por stoki informojn pri petoj: ĉiuj parametroj estas similaj por malsamaj formatoj, ekzemple protokoloj de IIS, apache kaj nginx. Por aplikaj protokoloj, en kiuj, ekzemple, eraroj, informaj mesaĝoj, avertoj estas registritaj, aparta tabelo estos provizita kun la taŭga strukturo (nuntempe en la desegna stadio).

Dum desegnado de tablo, estas tre grave decidi pri la ĉefa ŝlosilo (per kiu la datumoj estos ordigitaj dum stokado). De tio dependas la grado de datumkunpremo kaj demandorapideco. En nia ekzemplo, la ŝlosilo estas
MENDI DE (flag_app_name, fld_app_module, logdatetime)
Tio estas, laŭ la nomo de la sistemo, la nomo de la sistema komponanto kaj la dato de la evento. Komence, la dato de la evento venis unue. Post movi ĝin al la lasta loko, demandoj komencis funkcii proksimume duoble pli rapide. Ŝanĝi la ĉefan ŝlosilon postulos rekrei la tabelon kaj re-alŝuti la datumojn por ke ClickHouse reordigu la datumojn sur disko. Ĉi tio estas malfacila operacio, do estas konsilinde pripensi zorge antaŭe pri tio, kio devus esti inkluzivita en la ordiga ŝlosilo.

Oni devas ankaŭ rimarki, ke la datumtipo LowCardinality aperis en relative lastatempaj versioj. Kiam oni uzas ĝin, la grandeco de kunpremitaj datumoj estas akre reduktita por tiuj kampoj, kiuj havas malaltan kardinalecon (malmultaj opcioj).

Ni nuntempe uzas version 19.6 kaj ni planas provi ĝisdatigi al la plej nova versio. Ili havas tiajn mirindajn funkciojn kiel Adapta Granulareco, Skipping-indeksoj kaj la kodeko DoubleDelta, ekzemple.

Defaŭlte, dum instalado la agorda ensaluta nivelo estas agordita por spuri. Registroj estas rotaciitaj kaj arkivitaj, sed samtempe ili disetendiĝas ĝis gigabajto. Se ne necesas, tiam vi povas agordi la nivelon al averto, tiam la ŝtipo grandeco malpliiĝos akre. La registradaj agordoj estas specifitaj en la dosiero config.xml:

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

Kelkaj utilaj komandoj

Поскольку оригинальные пакеты установки собираются по 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. Ensalutu enkursigilon de FileBeat al RabbitMQ-vico

Ĉi tiu komponanto estas uzata por direkti protokolojn venantajn de FileBeat al la RabbitMQ-vico. Estas du punktoj ĉi tie:

  1. Bedaŭrinde, FileBeat ne havas eligaĵon por skribi rekte al RabbitMQ. Kaj tia funkcieco, se juĝante laŭ la afiŝo sur ilia github, ne estas planita por efektivigo. Estas kromaĵo por Kafka, sed pro certaj kialoj ni mem ne povas uzi ĝin.
  2. Estas postuloj por kolekti ŝtipojn en la DMZ. Surbaze de ili, la protokoloj unue devas esti vicigitaj kaj tiam LogStash legas rekordojn el la atendovico ekstere.

Tial, specife por la kazo de serviloj situantaj en DMZ, necesas uzi tian iomete komplikan skemon. Ekzempla agordo aspektas jene:

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

KunikloMQ. Mesaĝvico

Ĉi tiu komponanto estas uzata por bufri protokolojn en la DMZ. Registrado estas farita per la ligilo Filebeat → LogStash. Legado estas farita de ekster la DMZ per LogStash. Kiam funkcias per RabbitMQ, ĉirkaŭ 4 mil mesaĝoj je sekundo estas procesitaj.

Mesaĝvojigo estas agordita per sistemnomo, t.e., bazita sur FileBeat-agordaj datumoj. Ĉiuj mesaĝoj eniras en unu atendovico. Se ial la vicservo estas ĉesigita, tio ne kondukos al mesaĝperdo: FileBeats ricevos konekto-erarojn kaj provizore ĉesos sendi. Kaj LogStash, kiu legas el la atendovico, ankaŭ ricevos retajn erarojn kaj atendos ke la konekto estos restarigita. En ĉi tiu kazo, kompreneble, la datumoj ne plu estos skribitaj al la datumbazo.

La sekvaj instrukcioj estas uzataj por krei kaj agordi vostojn:

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

Ĉi tiu komponanto estas uzata por bildigi monitorajn datumojn. En ĉi tiu kazo, vi devas instali la datumfonton ClickHouse por Grafana 4.6+ kromaĵo. Ni devis iom ĝustigi ĝin por plibonigi la efikecon de prilaborado de SQL-filtriloj sur la panelo.

Ekzemple, ni uzas variablojn, kaj se ili ne estas specifitaj en la filtrila kampo, tiam ni ŝatus, ke ĝi ne generu kondiĉon en la KIE de la formo ( uriStem = "KAJ uriStem != "). En ĉi tiu kazo, ClickHouse legos la kolumnon uriStem. Do, ni provis malsamajn opciojn kaj finfine riparis la kromprogramon (la makroo $valueIfEmpty) por redoni 1 en kazo de malplena valoro, sen mencii la kolumnon mem.

Kaj nun vi povas uzi ĉi tiun demandon por la grafikaĵo

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

kiu estas konvertita al SQL tiel (notu, ke malplenaj uriStem-kampoj estas konvertitaj al nur 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

konkludo

La aspekto de la datumbazo ClickHouse fariĝis grava evento en la merkato. Estis malfacile imagi, ke tuj, tute senpage, ni estis armitaj per potenca kaj praktika ilo por labori kun grandaj datumoj. Kompreneble, kiel bezonoj pliiĝas (ekzemple, sharding kaj reproduktado al pluraj serviloj), la skemo fariĝos pli kompleksa. Sed laŭ unuaj impresoj, labori kun ĉi tiu datumbazo estas tre agrabla. Estas klare, ke la produkto estas farita "por homoj".

Kompare kun ElasticSearch, la kosto de stokado kaj prilaborado de ŝtipoj, laŭ antaŭtaksoj, estas reduktita je kvin ĝis dek fojojn. Alivorte, se por la nuna volumo de datumoj ni devus agordi areton de pluraj maŝinoj, tiam kiam vi uzas ClickHouse ni bezonas nur unu malfortan maŝinon. Jes, kompreneble, ElasticSearch ankaŭ havas surdiskajn datumajn kunpremajn mekanismojn kaj aliajn funkciojn, kiuj povas signife redukti la konsumon de rimedoj, sed kompare kun ClickHouse ĉi tio postulos pli grandajn kostojn.

Sen specialaj optimumigoj niaflanke, kun defaŭltaj agordoj, ŝarĝo de datumoj kaj reakiro de datumoj de la datumbazo funkcias kun mirinda rapideco. Ni ankoraŭ ne havas multajn datumojn (ĉirkaŭ 200 milionoj da registroj), sed la servilo mem estas malforta. Ni eble uzos ĉi tiun ilon estonte por aliaj celoj ne rilataj al stokado de protokoloj. Ekzemple, por fin-al-fina analizo, en la kampo de sekureco, maŝinlernado.

Al la fino, iom pri la avantaĝoj kaj malavantaĝoj.

Miksoj

  1. Ŝargante rekordojn en grandaj aroj. Unuflanke, ĉi tio estas trajto, sed vi ankoraŭ devas uzi pliajn komponantojn por bufrigi registrojn. Ĉi tiu tasko ne ĉiam estas simpla, sed tamen solvebla. Kaj mi ŝatus simpligi la skemon.
  2. Iuj ekzotikaj funkcioj aŭ novaj funkcioj ofte rompiĝas en novaj versioj. Ĉi tio vekas zorgojn, reduktante la deziron ĝisdatigi al nova versio. Ekzemple, la Kafka-tabelmotoro estas tre utila funkcio, kiu permesas vin rekte legi eventojn de Kafka, sen efektivigi konsumantojn. Sed juĝante laŭ la nombro da Problemoj sur Github, ni ankoraŭ zorgas pri uzado de ĉi tiu motoro en produktado. Tamen, se vi ne faras subitajn movojn flanken kaj uzas la bazan funkcion, tiam ĝi funkcias stabile.

Puloj

  1. Ne malrapidiĝas.
  2. Malalta enira sojlo.
  3. Malferma fonto.
  4. Senpaga.
  5. Skalebla (sharding/ekzempla reproduktado)
  6. Inkludita en la registro de rusa programaro rekomendita de la Ministerio de Komunikadoj.
  7. Havebleco de oficiala subteno de Yandex.

fonto: www.habr.com

Aldoni komenton