Baza e të dhënave ClickHouse për njerëzit, ose teknologji aliene

Aleksej Lizunov, drejtues i drejtimit të qendrës së kompetencës për kanalet në distancë të shërbimit pranë drejtorisë së teknologjive të informacionit të MKB

Baza e të dhënave ClickHouse për njerëzit, ose teknologji aliene

Si alternativë ndaj stack-ut ELK (ElasticSearch, Logstash, Kibana), ne po zhvillojmë punë kërkimore për përdorimin e bazës së të dhënave ClickHouse si depo të dhënash për log-et.

Në këtë artikull dëshirojmë të ndajmë përvojën tonë me përdorimin e bazës së të dhënave ClickHouse dhe rezultatet paraprake të fazës pilot të shfrytëzimit. Vlen të theksohet që në fillim se rezultatet dolën vërtet mbresëlënëse.


Baza e të dhënave ClickHouse për njerëzit, ose teknologji aliene

MĂ« poshtĂ« do tĂ« pĂ«rshkruajmĂ« mĂ« nĂ« detaje si Ă«shtĂ« konfiguruar sistemi ynĂ« dhe nga cilĂ«t komponentĂ« pĂ«rbĂ«het. Por tani do tĂ« donim tĂ« tregonim shkurtimisht pĂ«r kĂ«tĂ« bazĂ« tĂ« dhĂ«nash nĂ« tĂ«rĂ«si dhe pse ia vlen t’i kushtohet vĂ«mendje. Baza e tĂ« dhĂ«nave ClickHouse Ă«shtĂ« njĂ« DB analitike kolone me performancĂ« tĂ« lartĂ« nga Yandex. Ajo pĂ«rdoret nĂ« shĂ«rbimet e Yandex dhe fillimisht ka qenĂ« depoja kryesore e tĂ« dhĂ«nave pĂ«r Yandex.Metrica. Sistemi Ă«shtĂ« open-source dhe falas. Nga kĂ«ndvĂ«shtrimi i njĂ« zhvilluesi, mua mĂ« ka interesuar gjithmonĂ« si e kanĂ« realizuar kĂ«tĂ«, sepse atje bĂ«het fjalĂ« pĂ«r vĂ«llime fantastikisht tĂ« mĂ«dha tĂ« dhĂ«nash. Edhe vetĂ« ndĂ«rfaqja e pĂ«rdoruesit e Metrica Ă«shtĂ« shumĂ« fleksibile dhe punon shpejt. PĂ«rshtypja qĂ« nĂ« njohjen e parĂ« me kĂ«tĂ« DB ishte: «MĂ« nĂ« fund! ËshtĂ« bĂ«rĂ« “pĂ«r njerĂ«zit”! QĂ« nga procesi i instalimit e deri te dĂ«rgimi i kĂ«rkesave».

Kjo bazĂ« e tĂ« dhĂ«nave ka njĂ« prag shumĂ« tĂ« ulĂ«t hyrjeje. Edhe njĂ« zhvillues me kualifikim mesatar mund ta instalojĂ« kĂ«tĂ« DB pĂ«r pak minuta dhe tĂ« nisĂ« ta pĂ«rdorĂ«. Gjithçka funksionon saktĂ«. Edhe njerĂ«zit qĂ« nuk e njohin mirĂ« Linux mund ta pĂ«rballojnĂ« instalimin mjaft shpejt dhe tĂ« kryejnĂ« operacionet mĂ« tĂ« thjeshta. NĂ«se mĂ« parĂ«, kur pĂ«rmendeshin Big Data, Hadoop, Google BigTable, HDFS, zhvilluesi i zakonshĂ«m imagjinonte se bĂ«hej fjalĂ« pĂ«r terabajtĂ« e petabajtĂ« dhe se konfigurimi e zhvillimi pĂ«r kĂ«to sisteme i pĂ«rkisnin njĂ« lloj supernjerĂ«zish, me shfaqjen e bazĂ«s sĂ« tĂ« dhĂ«nave ClickHouse morĂ«m njĂ« mjet tĂ« thjeshtĂ« e tĂ« kuptueshĂ«m, me tĂ« cilin mund tĂ« zgjidhet njĂ« gamĂ« detyrash qĂ« mĂ« parĂ« ishte e paarritshme. Mjafton vetĂ«m njĂ« makinĂ« mjaft e zakonshme dhe pesĂ« minuta pĂ«r instalim. Pra, morĂ«m njĂ« bazĂ« tĂ« dhĂ«nash si, pĂ«r shembull, MySql, por pĂ«r ruajtjen e miliarda regjistrimeve! NjĂ« lloj superarkivuesi me gjuhĂ«n SQL. Sikur njerĂ«zimit t’i ishte dhĂ«nĂ« arma e alienĂ«ve.

Për sistemin tonë të mbledhjes së log-eve

Për mbledhjen e informacionit përdoren skedarët e logeve të aplikacioneve web IIS në format standard (aktualisht po punojmë edhe për parsimin e logeve të aplikacioneve, por qëllimi kryesor në fazën e pilotimit është mbledhja e logeve IIS).

Nuk arritëm të heqim dorë plotësisht nga stack-u ELK për arsye të ndryshme, ndaj vazhdojmë të përdorim komponentët LogStash dhe Filebeat, të cilët e kanë dëshmuar veten mirë dhe funksionojnë mjaftueshëm në mënyrë të qëndrueshme dhe të parashikueshme.

Skema e përgjithshme e logimit paraqitet në figurën më poshtë:

Baza e të dhënave ClickHouse për njerëzit, ose teknologji aliene

Veçoria e shkrimit tĂ« tĂ« dhĂ«nave nĂ« DB ClickHouse Ă«shtĂ« futja jo shumĂ« e shpeshtĂ« e regjistrimeve (njĂ« herĂ« nĂ« sekondĂ«) nĂ« blloqe tĂ« mĂ«dha. Me sa duket, kjo Ă«shtĂ« pjesa mĂ« “problematike” me tĂ« cilĂ«n pĂ«rballesh nĂ« pĂ«rvojĂ«n e parĂ« tĂ« punĂ«s me DB ClickHouse: skema bĂ«het disi mĂ« e ndĂ«rlikuar.
Këtu ndihmoi shumë plugin-i për LogStash, i cili fut të dhënat drejtpërdrejt në ClickHouse. Ky komponent vendoset në të njëjtin server ku ndodhet edhe vetë DB. Në përgjithësi kjo nuk rekomandohet, por nga pikëpamja praktike, për të mos shtuar serverë të veçantë, aktualisht është vendosur në të njëjtin server. Nuk kemi vërejtur as ndërprerje, as konflikte burimesh me DB. Gjithashtu duhet theksuar se plugin-i ka të parashikuar një mekanizëm retry në rast gabimesh. Në rast gabimesh, plugin-i shkruan në disk bllokun e të dhënave që nuk arriti ta fusë (formati i skedarit është i përshtatshëm: pas korrigjimit, blloku i rregulluar mund të insertohet lehtësisht me clickhouse-client).

Lista e plotë e softuerit që përdoret në këtë skemë paraqitet në tabelë:

Lista e softuerit të përdorur

Emri

Përshkrimi

Lidhja e shpërndarjes

NGINX

Reverse-proxy për kufizimin e aksesit sipas porteve dhe organizimin e autorizimit

Aktualisht nuk përdoret në këtë skemë

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

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

FileBeat

Transmetimi i logeve të skedarëve.

https://www.elastic.co/downloads/beats/filebeat (shpërndarje për Windows 64bit).

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

LogStash

Mbledhës logesh.

Përdoret për mbledhjen e logeve nga FileBeat, si edhe për mbledhjen e logeve nga radha RabbitMQ (për serverët që ndodhen në DMZ.)

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

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

Logstash- output- clickhouse

Plugin Logstash për dërgimin e logeve në DB ClickHouse në blloqe

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

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

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

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

ClickHouse

Ruajtja e logeve 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

ShĂ«nim. Duke filluar nga gushti 2018, nĂ« depozitĂ«n e Yandex u shfaqĂ«n paketa rpm “normale” pĂ«r RHEL, prandaj mund tĂ« provoni t’i pĂ«rdorni ato. NĂ« momentin e instalimit ne pĂ«rdornim paketat e ndĂ«rtuara nga Altinity.

Nëse tashmë e dini se çfarë është analiza e grupeve dhe se si ta bëni në SQL, kaloni menjëherë në seksionin e fundit.

Vizualizimi i logeve. Konfigurimi i dashboard-eve

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos(64 Bit) – versionin mĂ« tĂ« fundit

ClickHouse datasource for Grafana 4.6+

Plugin për Grafana me burim të dhënash ClickHouse

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

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

LogStash

Ruterimi i logeve nga FileBeat në radhën RabbitMQ.

Shënim. Fatkeqësisht, FileBeat nuk ka output të drejtpërdrejtë në RabbitMQ, prandaj nevojitet një hallkë ndërmjetëse në formën e Logstash

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

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

RabbitMQ

Radha e mesazheve. Ky është një buffer i regjistrimeve të logeve në 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 (I nevojshëm për RabbitMQ)

Mjedisi i ekzekutimit Erlang. Kërkohet për funksionimin e RabbitMQ

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

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

Konfigurimi i serverit me DB ClickHouse paraqitet në tabelën e mëposhtme:

Emri

Vlera

Shënim

Konfigurimi

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

Duhet t'u kushtohet vëmendje këshillave për përdorimin e DB ClickHouse (https://clickhouse.yandex/docs/ru/operations/tips/)

Softuer i përgjithshëm i sistemit

OS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Siç shihet, kjo është një stacion pune i zakonshëm.

Struktura e tabelës për ruajtjen e logeve duket si më poshtë:

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;

Ne përdorim vlerat e parazgjedhura për particionimin (sipas muajve) dhe granularitetin e indeksit. Pothuajse të gjitha fushat përputhen me regjistrimet e logut IIS për regjistrimin e kërkesave HTTP. Veçmas theksojmë fushat e posaçme për ruajtjen e etiketave UTM (ato parsohen në fazën e futjes në tabelë nga fusha e query string).

Gjithashtu, në tabelë janë shtuar disa fusha sistemore për ruajtjen e informacionit rreth sistemeve, komponentëve dhe serverëve. Përshkrimi i këtyre fushave jepet më poshtë në tabelë. Në një tabelë ruajmë loget e disa sistemeve.

Emri

Përshkrimi

Shembulli

fld_app_name

Emri i aplikacionit/sistemit
Vlerat e lejuara:

  • site1.domain.com Sajti i jashtĂ«m 1
  • site2.domain.com Sajti i jashtĂ«m 2
  • internal-site1.domain.local Sajti i brendshĂ«m 1

site1.domain.com

fld_app_module

Moduli i sistemit
Vlerat e lejuara:

  • web — Uebsajt
  • svc — ShĂ«rbimi ueb i sajtit
  • intgr — ShĂ«rbimi ueb i integrimit
  • bo — Paneli i administrimit (BackOffice)

web

fld_website_name

Emri i sajtit në IIS

Në një server mund të jenë vendosur disa sisteme, ose edhe disa instanca të të njëjtit modul të sistemit

web-main

fld_server_name

Emri i serverit

web1.domain.com

fld_log_file_name

Rruga drejt skedarit të logut në server

ĐĄ:inetpublogsLogFiles
W3SVC1u_ex190711.log

Kjo ju lejon të ndërtoni grafikë në mënyrë efikase në Grafana. Për shembull, të shihni kërkesat nga frontend-i i një sistemi të caktuar. Kjo është e ngjashme me numëruesin e faqes në Yandex.Metrica.

Ja disa statistika mbi përdorimin e DB gjatë dy muajve.

Numri i regjistrimeve sipas sistemeve dhe komponentëve të tyre

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 │
└──────────────────┮────────────────┮────────────┘
 
Totali:
┌─fld_app_name─┬─fld_app_module─┬─rows_count─┐
│              │                │  210522593 │
└──────────────┮────────────────┮────────────┘
 
11 rreshta në rezultat. Koha e ekzekutimit: 4.874 sek. U përpunuan 210.52 milionë rreshta, 421.67 MB (43.19 milionë rreshta/s., 86.51 MB/s.)

Vëllimi i të dhënave në 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 rresht në rezultat. Koha e ekzekutimit: 0.035 sek.

Shkalla e kompresimit të të dhënave në kolona

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 rreshta në grup. Koha e ekzekutimit: 0.005 sek.

Përshkrimi i komponentëve të përdorur

FileBeat. Transferimi i log-eve nga skedarët

Ky komponent monitoron ndryshimet në skedarët e log-eve në disk dhe i dërgon të dhënat te LogStash. Instalohet në të gjithë serverët ku shkruhen skedarët e log-eve (zakonisht IIS). Punon në modalitetin tail (domethënë transmeton vetëm hyrjet e shtuara në skedar). Por mund të konfigurohet veçmas edhe për dërgimin e skedarëve të plotë. Kjo është e përshtatshme kur duhet të ngarkohen të dhëna për muajt e mëparshëm. Mjafton të vendosni skedarin e log-ut në dosje dhe ai do ta lexojë automatikisht të plotin.

Kur shërbimi ndalet, të dhënat nuk vazhdojnë më të transmetohen në storage.

Shembulli i konfigurimit duket si më poshtë:

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. Mbledhësi i logeve

Ky komponent Ă«shtĂ« krijuar pĂ«r tĂ« marrĂ« regjistrimet e logeve nga FileBeat (ose pĂ«rmes radhĂ«s RabbitMQ), pĂ«r t’i parsuar dhe pĂ«r t’i futur nĂ« grupe nĂ« bazĂ«n e tĂ« dhĂ«nave ClickHouse.

Për futjen në ClickHouse përdoret plugin-i Logstash-output-clickhouse. Plugin-i i Logstash ka një mekanizëm retry për kërkesat, por gjatë një ndalese normale është gjithsesi më mirë të ndalet vetë shërbimi. Gjatë ndalimit, mesazhet do të grumbullohen në radhën RabbitMQ, prandaj nëse ndalimi zgjat më shumë, atëherë është më mirë të ndalen edhe Filebeat-et në serverë. Në skemën ku RabbitMQ nuk përdoret (në rrjetin lokal Filebeat i dërgon loget direkt në Logstash), Filebeat-et funksionojnë mjaft mirë dhe në mënyrë të sigurt, ndaj mosdisponueshmëria e output-it për to kalon pa pasoja.

Shembulli i konfigurimit duket si më poshtë:

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. Depoja e logeve

Loget nga të gjitha sistemet ruhen në një tabelë të vetme (shihni në fillim të artikullit). Ajo është menduar për ruajtjen e informacionit mbi kërkesat: të gjithë parametrat janë të ngjashëm për formate të ndryshme, për shembull loget IIS, loget apache dhe nginx. Për loget e aplikacioneve, ku regjistrohen, për shembull, gabime, mesazhe informative, paralajmërime, do të parashikohet një tabelë e veçantë me strukturën përkatëse (aktualisht është në fazën e projektimit).

Gjatë projektimit të tabelës, është shumë e rëndësishme të përcaktohet çelësi primar (sipas të cilit të dhënat do të renditen gjatë ruajtjes). Nga kjo varet shkalla e kompresimit të të dhënave dhe shpejtësia e kërkesave. Në shembullin tonë, çelësi është
ORDER BY (fld_app_name, fld_app_module, logdatetime)
Pra, sipas emrit tĂ« sistemit, emrit tĂ« komponentit tĂ« sistemit dhe datĂ«s sĂ« ngjarjes. Fillimisht data e ngjarjes ishte nĂ« vendin e parĂ«. Pasi u zhvendos nĂ« vendin e fundit, kĂ«rkesat filluan tĂ« punojnĂ« afĂ«rsisht dy herĂ« mĂ« shpejt. Ndryshimi i çelĂ«sit primar do tĂ« kĂ«rkojĂ« rikrijimin e tabelĂ«s dhe ringarkimin e tĂ« dhĂ«nave, nĂ« mĂ«nyrĂ« qĂ« ClickHouse t’i rirenditĂ« tĂ« dhĂ«nat nĂ« disk. Kjo Ă«shtĂ« njĂ« procedurĂ« e rĂ«ndĂ«, ndaj Ă«shtĂ« e dĂ«shirueshme tĂ« mendohet shumĂ« herĂ«t se çfarĂ« duhet tĂ« pĂ«rfshihet nĂ« çelĂ«sin e renditjes.

Gjithashtu duhet theksuar se në versionet e fundit është shfaqur tipi i të dhënave LowCardinality. Kur përdoret, zvogëlohet ndjeshëm madhësia e të dhënave të kompresuara për ato fusha që kanë kardinalitet të ulët (pak variante).

Aktualisht përdoret versioni 19.6 dhe ne planifikojmë të provojmë përditësimin në versionin më të fundit. Në të janë shfaqur veçori shumë të dobishme si Adaptive Granularity, Skipping indices dhe kodeku DoubleDelta, për shembull.

Si parazgjedhje, gjatë instalimit në konfigurim vendoset niveli i logimit trace. Loget rrotullohen dhe arkivohen, por megjithatë rriten deri në një gigabajt. Nëse kjo nuk është e nevojshme, mund të vendoset niveli warning; atëherë madhësia e logut zvogëlohet ndjeshëm. Konfigurimi i logimit përcaktohet në skedarin config.xml:


warning

Disa komanda të dobishme

Meqenëse paketat origjinale të instalimit ndërtohen për Debian, për versionet e tjera të Linux duhet të përdoren paketat e ndërtuara nga Altinity.
 
Në këtë lidhje ka udhëzime dhe lidhje për në repository-n e tyre: https://www.altinity.com/blog/2017/12/18/logstash-with-clickhouse
sudo yum search clickhouse-server
sudo yum install clickhouse-server.noarch
  
1. kontrolli i statusit
sudo systemctl status clickhouse-server
 
2. ndalimi i serverit
sudo systemctl stop clickhouse-server
 
3. nisja e serverit
sudo systemctl start clickhouse-server
 
Nisja për ekzekutimin e kërkesave në modalitet me shumë rreshta (ekzekutimi bëhet pas shenjës ";")
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
 
Plugin-i i ClickHouse për Logstash, në rast gabimi në një rresht, e ruan të gjithë paketën në skedarin /tmp/log_web_failed.json
Mund ta korrigjoni manualisht këtë skedar dhe të provoni ta ngarkoni në DB manualisht:
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
 
dalja nga rreshti i komandës
quit;
## Konfigurimi i TLS
https://www.altinity.com/blog/2019/3/5/clickhouse-networking-part-2
 
openssl s_client -connect log.domain.com:9440 < /dev/null

LogStash. Ruter i logeve nga FileBeat në radhën RabbitMQ

Ky komponent përdoret për të rutuar loget që vijnë nga FileBeat drejt radhës RabbitMQ. Këtu ka dy pika kryesore:

  1. Fatkeqësisht, FileBeat nuk ka plugin output për të shkruar drejtpërdrejt në RabbitMQ. Dhe, duke gjykuar nga issue në GitHub-in e tyre, një funksionalitet i tillë nuk pritet të implementohet. Ekziston një plugin për Kafka, por për disa arsye ne nuk mund ta përdorim atë në infrastrukturën tonë.
  2. Ka kërkesa për mbledhjen e logeve në DMZ. Bazuar në to, loget fillimisht duhet të dërgohen në radhë dhe më pas LogStash i lexon regjistrimet nga radha nga jashtë.

Prandaj, pikërisht në rastin kur serverët ndodhen në DMZ, duhet përdorur kjo skemë disi më e ndërlikuar. Një shembull konfigurimi duket si më poshtë:

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. Radha e mesazheve

Ky komponent pĂ«rdoret pĂ«r buferimin e regjistrimeve tĂ« logeve nĂ« DMZ. Shkrimi kryhet pĂ«rmes zinxhirit Filebeat → LogStash. Leximi bĂ«het nga jashtĂ« DMZ-sĂ« pĂ«rmes LogStash. GjatĂ« punĂ«s me RabbitMQ pĂ«rpunohen rreth 4 mijĂ« mesazhe nĂ« sekondĂ«.

Rrugëzimi i mesazheve është konfiguruar sipas emrit të sistemit, pra në bazë të të dhënave të konfigurimit të FileBeat. Të gjitha mesazhet dërgohen në një radhë të vetme. Nëse për çfarëdo arsye ndalet shërbimi i radhës, kjo nuk do të çojë në humbje mesazhesh: FileBeat-et do të marrin gabime lidhjeje dhe do ta pezullojnë përkohësisht dërgimin. Edhe LogStash, i cili lexon nga radha, do të marrë gabime rrjeti dhe do të presë derisa lidhja të rikthehet. Natyrisht, në këtë kohë të dhënat nuk do të shkruhen më në DB.

Udhëzimet e mëposhtme përdoren për krijimin dhe konfigurimin e radhëve:

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. Panele kontrolli

Ky komponent përdoret për vizualizimin e të dhënave të monitorimit. Për këtë duhet të instalohet plugini ClickHouse datasource for Grafana 4.6+. Na u desh ta përshtatnim pak për të rritur efikasitetin e përpunimit të filtrave SQL në panelin e kontrollit.

Për shembull, ne përdorim variabla dhe, nëse ato nuk janë vendosur në fushën e filtrit, do të donim që ai të mos gjeneronte një kusht në WHERE të formës ( uriStem = » AND uriStem != » ). Në këtë rast, ClickHouse do të lexojë kolonën uriStem. Në përgjithësi, provuam variante të ndryshme dhe në fund e modifikuam pluginin (makroja $valueIfEmpty) që, në rast të një vlere bosh, të kthejë 1 pa përmendur vetë kolonën.

Dhe tani mund të përdorni një kërkesë të tillë për grafikun

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

i cili shndërrohet në këtë SQL (vini re se fushat bosh uriStem u shndërruan thjesht në 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

Përfundim

Shfaqja e DB ClickHouse u bë një ngjarje domethënëse në treg. Ishte e vështirë të imagjinohej se krejt falas, brenda një çasti, morëm në dorë një mjet të fuqishëm dhe praktik për punë me Big Data. Natyrisht, me rritjen e kërkesave, për shembull shardimi dhe replikimi në disa serverë, skema do të bëhet më komplekse. Por nga përshtypjet e para, puna me këtë DB është shumë e këndshme. Duket qartë se produkti është krijuar «për njerëzit».

Krahasuar me ElasticSearch, kostot për ruajtjen dhe përpunimin e logeve, sipas vlerësimeve paraprake, ulen nga pesë deri në dhjetë herë. Me fjalë të tjera, nëse për vëllimin aktual të të dhënave do të na duhej të konfiguronim një cluster me disa makina, me ClickHouse na mjafton një makinë e vetme me fuqi të ulët. Po, sigurisht, edhe ElasticSearch ka mekanizma për kompresimin e të dhënave në disk dhe funksione të tjera që lejojnë ulje të ndjeshme të konsumit të burimeve, por krahasuar me ClickHouse kjo do të kërkojë kosto më të larta.

Pa asnjë optimizim të veçantë nga ana jonë dhe me cilësimet default, ngarkimi i të dhënave dhe query-t nga DB funksionojnë me shpejtësi mbresëlënëse. Për momentin kemi ende pak të dhëna, rreth 200 milion regjistrime, por vetë serveri është i dobët. Në të ardhmen, këtë mjet mund ta përdorim edhe për qëllime të tjera që nuk lidhen me ruajtjen e logeve. Për shembull, për analitikë end-to-end, në fushën e sigurisë dhe në machine learning.

Në fund, pak për të metat dhe përparësitë.

Disavantazhet

  1. Ngarkimi i regjistrimeve në paketa të mëdha. Nga njëra anë, kjo është një veçori, por gjithsesi duhet të përdoren komponentë shtesë për buferimin e regjistrimeve. Kjo detyrë nuk është gjithmonë e thjeshtë, por megjithatë është e zgjidhshme. Dhe do të ishte mirë të thjeshtohej skema.
  2. Disa funksione ekzotike ose veçori të reja shpesh prishen në versionet e reja. Kjo krijon hezitim dhe ul dëshirën për të kaluar te një version i ri. Për shembull, motori i tabelave Kafka është një veçori shumë e dobishme që lejon leximin e drejtpërdrejtë të eventeve nga Kafka, pa implementuar consumers. Por, duke gjykuar nga numri i Issue në GitHub, për momentin ende hezitojmë ta përdorim këtë motor në production. Megjithatë, nëse nuk bëhen ndryshime të menjëhershme anash dhe përdoret funksionaliteti bazë, ai punon në mënyrë të qëndrueshme.

Pikat pozitive

  1. Nuk ngadalësohet.
  2. Prag i ulët hyrjeje.
  3. Open-source.
  4. Falas.
  5. Shkallëzohet mirë (sharding/replication "out of the box")
  6. ËshtĂ« pjesĂ« e regjistrit tĂ« softuerit rus tĂ« rekomanduar nga Ministria e Komunikimeve.
  7. Mbështetje zyrtare nga Yandex.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster