İnsanlar və ya Yadplanetli Texnologiyalar üçün ClickHouse Database

Aleksey Lizunov, MKB İnformasiya Texnologiyaları Direktorluğunun Uzaqdan Xidmət Kanalları üzrə Səlahiyyət Mərkəzinin rəhbəri

İnsanlar və ya Yadplanetli Texnologiyalar üçün ClickHouse Database

ELK yığınına (ElasticSearch, Logstash, Kibana) alternativ olaraq, biz ClickHouse verilənlər bazasından loglar üçün məlumat anbarı kimi istifadə üzərində araşdırma aparırıq.

Bu yazıda biz ClickHouse verilənlər bazasından istifadə təcrübəmizdən və pilot əməliyyatın ilkin nəticələrindən danışmaq istərdik. Dərhal qeyd etmək lazımdır ki, nəticələr təsir edici idi.


İnsanlar və ya Yadplanetli Texnologiyalar üçün ClickHouse Database

Sonra, sistemimizin necə konfiqurasiya edildiyini və onun hansı komponentlərdən ibarət olduğunu daha ətraflı təsvir edəcəyik. Amma indi bütövlükdə bu verilənlər bazası haqqında bir az danışmaq istərdim və niyə buna diqqət yetirməyə dəyər. ClickHouse verilənlər bazası Yandex-in yüksək performanslı analitik sütunlu verilənlər bazasıdır. Yandex xidmətlərində istifadə olunur, əvvəlcə Yandex.Metrica üçün əsas məlumat saxlama yeridir. Açıq mənbə sistemi, pulsuz. Bir tərtibatçının nöqteyi-nəzərindən mən həmişə onların bunu necə həyata keçirdikləri ilə maraqlanmışam, çünki fantastik dərəcədə böyük məlumatlar var. Metrica-nın istifadəçi interfeysi özü də çox çevik və sürətlidir. Bu verilənlər bazası ilə ilk tanışlıqda belə bir təəssürat yaranır: “Yaxşı, nəhayət! İnsanlar üçün yaradılmışdır! Quraşdırma prosesindən başlayaraq sorğuların göndərilməsi ilə bitir.

Bu verilənlər bazası çox aşağı giriş həddinə malikdir. Hətta orta səviyyəli bir tərtibatçı belə bir neçə dəqiqə ərzində bu verilənlər bazasını quraşdıra və ondan istifadə etməyə başlaya bilər. Hər şey aydın işləyir. Hətta Linux-da yeni olan insanlar quraşdırmanı tez bir zamanda idarə edə və ən sadə əməliyyatları edə bilərlər. Əgər əvvəllər Big Data, Hadoop, Google BigTable, HDFS sözləri ilə adi bir tərtibatçı söhbətin bəzi terabaytlar, petabaytlar haqqında olduğunu, bəzi fövqəlbəşərlərin bu sistemlərin parametrlərini və inkişaf etdirilməsində iştirak etdiyini düşünürdüsə, ClickHouse-un meydana çıxması ilə. verilənlər bazası, biz sadə, başa düşülən bir alət əldə etdik, onun köməyi ilə əvvəllər əlçatmaz bir sıra vəzifələri həll edə bilərsiniz. Quraşdırmaq üçün yalnız bir kifayət qədər orta maşın və beş dəqiqə çəkir. Yəni, məsələn, MySql kimi bir verilənlər bazası əldə etdik, ancaq milyardlarla qeydləri saxlamaq üçün! SQL dili ilə müəyyən bir super arxivçi. Sanki insanlara yadplanetlilərin silahları verilirdi.

Giriş sistemimiz haqqında

Məlumat toplamaq üçün standart formatlı veb proqramların IIS log fayllarından istifadə olunur (biz hazırda tətbiq jurnallarını təhlil edirik, lakin pilot mərhələdə əsas məqsəd IIS qeydlərini toplamaqdır).

Müxtəlif səbəblərə görə biz ELK yığınından tamamilə imtina edə bilmədik və biz özlərini yaxşı sübut etmiş və kifayət qədər etibarlı və proqnozlaşdırıla bilən şəkildə işləyən LogStash və Filebeat komponentlərindən istifadə etməyə davam edirik.

Ümumi giriş sxemi aşağıdakı şəkildə göstərilmişdir:

İnsanlar və ya Yadplanetli Texnologiyalar üçün ClickHouse Database

ClickHouse verilənlər bazasına məlumatların yazılmasının bir xüsusiyyəti, böyük partiyalarda qeydlərin nadir hallarda (saniyədə bir dəfə) daxil edilməsidir. Görünür, bu, ClickHouse verilənlər bazası ilə ilk dəfə işlədiyiniz zaman qarşılaşdığınız ən “problemli” hissədir: sxem bir az daha mürəkkəbləşir.
Məlumatları birbaşa ClickHouse-a daxil edən LogStash üçün plagin burada çox kömək etdi. Bu komponent verilənlər bazası ilə eyni serverdə yerləşdirilir. Beləliklə, ümumiyyətlə desək, bunu etmək tövsiyə edilmir, amma praktiki baxımdan, eyni serverdə yerləşdirilərkən ayrıca serverlər istehsal etməmək üçün. Verilənlər bazası ilə heç bir nasazlıq və ya resurs münaqişəsi müşahidə etmədik. Əlavə olaraq qeyd etmək lazımdır ki, plagində səhvlər zamanı təkrar cəhd mexanizmi var. Səhvlər olduqda, plagin diskə daxil edilə bilməyən bir məlumat toplusunu yazır (fayl formatı rahatdır: redaktə etdikdən sonra clickhouse-client istifadə edərək düzəldilmiş partiyanı asanlıqla daxil edə bilərsiniz).

Sxemdə istifadə olunan proqram təminatının tam siyahısı cədvəldə təqdim olunur:

İstifadə olunan proqramların siyahısı

Ad

Təsvir

Paylama linki

NGINX

Portlarla girişi məhdudlaşdırmaq və avtorizasiyanı təşkil etmək üçün əks-proksi

Hal-hazırda sxemdə istifadə edilmir

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

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

FileBeat

Fayl qeydlərinin ötürülməsi.

https://www.elastic.co/downloads/beats/filebeat (Windows 64bit üçün paylama dəsti).

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

logstash

Günlük toplayıcı.

FileBeat-dən qeydləri toplamaq, həmçinin RabbitMQ növbəsindən qeydləri toplamaq üçün istifadə olunur (DMZ-də olan serverlər üçün).

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

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

Logstash-output-clickhouse

Loagstash plaqini, logları toplu olaraq ClickHouse verilənlər bazasına köçürmək üçün

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

/usr/share/logstash/bin/logstash-plugin quraşdırma logstash-output-clickhouse

/usr/share/logstash/bin/logstash-plugin quraşdırma logstash-filter-prune

/usr/share/logstash/bin/logstash-plugin quraşdırma logstash-filter-multiline

Basın Evi

Giriş saxlama 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

Qeyd. 2018-ci ilin avqust ayından etibarən, RHEL üçün "normal" rpm qurmaları Yandex repozitoriyasında göründü, buna görə də onlardan istifadə etməyə cəhd edə bilərsiniz. Quraşdırma zamanı biz Altinity tərəfindən hazırlanmış paketlərdən istifadə edirdik.

Qrafana

Girişin vizuallaşdırılması. Tabloların qurulması

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos(64 Bit) - son versiya

Grafana 4.6+ üçün ClickHouse məlumat mənbəyi

ClickHouse məlumat mənbəyi ilə Grafana üçün plagin

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

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

logstash

Routeri FileBeat-dən RabbitMQ növbəsinə daxil edin.

Qeyd. Təəssüf ki, FileBeat-in birbaşa RabbitMQ-a çıxışı yoxdur, buna görə də Logstash şəklində ara keçid tələb olunur.

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

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

RabbitMQ

mesaj növbəsi. Bu, DMZ-dəki log buferidir

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 (RabitMQ üçün tələb olunur)

Erlang icra müddəti. RabbitMQ-nun işləməsi üçün tələb olunur

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

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

ClickHouse verilənlər bazası ilə server konfiqurasiyası aşağıdakı cədvəldə təqdim olunur:

Ad

Dəyər

Qeyd

Konfiqurasiya

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

ClickHouse verilənlər bazasını idarə etmək üçün məsləhətlərə diqqət yetirmək lazımdır (https://clickhouse.yandex/docs/ru/operations/tips/)

Ümumi sistem proqram təminatı

ƏS: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Gördüyünüz kimi, bu adi bir iş stansiyasıdır.

Günlüklərin saxlanması üçün cədvəlin quruluşu aşağıdakı kimidir:

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;

Biz standart bölmədən (aylara görə) və indeks qranulyarlığından istifadə edirik. Bütün sahələr praktiki olaraq http sorğularını qeyd etmək üçün IIS jurnal qeydlərinə uyğun gəlir. Ayrı-ayrılıqda qeyd edirik ki, utm etiketlərinin saxlanması üçün ayrıca sahələr mövcuddur (onlar sorğu sətri sahəsindən cədvələ daxil edilmə mərhələsində təhlil edilir).

Həmçinin sistemlər, komponentlər, serverlər haqqında məlumatları saxlamaq üçün cədvələ bir neçə sistem sahələri əlavə edilmişdir. Bu sahələrin təsviri üçün aşağıdakı cədvələ baxın. Bir cədvəldə bir neçə sistem üçün qeydləri saxlayırıq.

Ad

Təsvir

Misal

fld_app_name

Proqram/sistem adı
Etibarlı dəyərlər:

  • site1.domain.com Xarici sayt 1
  • site2.domain.com Xarici sayt 2
  • daxili-site1.domain.local Daxili sayt 1

site1.domain.com

fld_app_modulu

Sistem modulu
Etibarlı dəyərlər:

  • web - Veb sayt
  • svc - Veb sayt xidməti
  • intgr - İnteqrasiya Veb Xidməti
  • bo - Admin (BackOffice)

web

fld_website_name

IIS-də sayt adı

Bir serverdə bir neçə sistem və ya hətta bir sistem modulunun bir neçə nümunəsi yerləşdirilə bilər

veb əsas

fld_server_name

Server adı

web1.domain.com

fld_log_fayl_name

Serverdəki günlük faylına gedən yol

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

Bu, Grafana-da qrafikləri səmərəli şəkildə qurmağa imkan verir. Məsələn, müəyyən bir sistemin ön hissəsindən sorğulara baxın. Bu, Yandex.Metrica-da sayt sayğacına bənzəyir.

İki ay ərzində verilənlər bazasının istifadəsinə dair bəzi statistik məlumatları təqdim edirik.

Sistemlər və onların komponentləri üzrə bölünmüş qeydlərin sayı

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

Diskdəki məlumatların miqdarı

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.

Sütunlarda verilənlərin sıxılma dərəcəsi

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.

İstifadə olunan komponentlərin təsviri

FileBeat. Fayl qeydlərinin ötürülməsi

Bu komponent diskdəki log fayllarına edilən dəyişiklikləri izləyir və məlumatları LogStash-a ötürür. Log fayllarının yazıldığı bütün serverlərdə quraşdırılır (adətən IIS). Quyruq rejimində işləyir (yəni yalnız əlavə edilmiş qeydləri fayla köçürür). Ancaq ayrıca bütün faylları ötürmək üçün konfiqurasiya edilə bilər. Bu, əvvəlki aylardan məlumatları endirmək lazım olduqda faydalıdır. Sadəcə log faylını qovluğa qoyun və o, onu tam oxuyacaq.

Xidmət dayandırıldıqda, məlumatlar daha sonra yaddaşa ötürülmür.

Konfiqurasiya nümunəsi belə görünür:

filebeat.yml

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - C:/inetpub/logs/LogFiles/W3SVC1/*.log
  exclude_files: ['.gz$','.zip$']
  tail_files: true
  ignore_older: 24h
  fields:
    fld_server_name: "site1.domain.ru"
    fld_app_name: "site1.domain.ru"
    fld_app_module: "web"
    fld_website_name: "web-main"
 
- type: log
  enabled: true
  paths:
    - C:/inetpub/logs/LogFiles/__Import/access_log-*
  exclude_files: ['.gz$','.zip$']
  tail_files: false
  fields:
    fld_server_name: "site2.domain.ru"
    fld_app_name: "site2.domain.ru"
    fld_app_module: "web"
    fld_website_name: "web-main"
    fld_logformat: "logformat__apache"
 
 
filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false
  reload.period: 2s
 
output.logstash:
  hosts: ["log.domain.com:5044"]
 
  ssl.enabled: true
  ssl.certificate_authorities: ["C:/filebeat/certs/ca.pem", "C:/filebeat/certs/ca-issuing.pem"]
  ssl.certificate: "C:/filebeat/certs/site1.domain.ru.cer"
  ssl.key: "C:/filebeat/certs/site1.domain.ru.key"
 
#================================ Processors =====================================
 
processors:
  - add_host_metadata: ~
  - add_cloud_metadata: ~

logstash. Günlük Kollektoru

Bu komponent FileBeat-dən (və ya RabbitMQ növbəsi vasitəsilə) log girişlərini qəbul etmək, partiyaları təhlil etmək və ClickHouse verilənlər bazasına daxil etmək üçün nəzərdə tutulmuşdur.

ClickHouse-a daxil etmək üçün Logstash-output-clickhouse plaginindən istifadə olunur. Logstash plaginində sorğunun təkrar cəhd mexanizmi var, lakin müntəzəm bağlanma ilə xidmətin özünü dayandırmaq daha yaxşıdır. Dayandırıldıqda mesajlar RabbitMQ növbəsində toplanacaq, buna görə də dayanma uzun müddətdirsə, o zaman serverlərdə Filebeats-i dayandırmaq daha yaxşıdır. RabbitMQ-nin istifadə edilmədiyi bir sxemdə (yerli şəbəkədə Filebeat logları birbaşa Logstash-a göndərir), Filebeats olduqca məqbul və təhlükəsiz işləyir, buna görə də onlar üçün çıxışın əlçatmazlığı nəticəsiz keçir.

Konfiqurasiya nümunəsi belə görünür:

log_web__filebeat_clickhouse.conf

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

boru kəmərləri.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"

klik evi. Giriş saxlama

Bütün sistemlər üçün qeydlər bir cədvəldə saxlanılır (məqalənin əvvəlinə baxın). O, sorğular haqqında məlumatı saxlamaq üçün nəzərdə tutulub: bütün parametrlər müxtəlif formatlar üçün oxşardır, məsələn, IIS qeydləri, apache və nginx qeydləri. Məsələn, səhvlər, məlumat mesajları, xəbərdarlıqların qeyd olunduğu tətbiq jurnalları üçün müvafiq strukturla (hazırda dizayn mərhələsində) ayrıca bir cədvəl təqdim ediləcəkdir.

Cədvəl tərtib edərkən əsas açarı (məlumatların saxlanma zamanı çeşidlənəcəyi) qərar vermək çox vacibdir. Məlumatların sıxılma dərəcəsi və sorğu sürəti bundan asılıdır. Bizim nümunəmizdə əsas budur
SİFARİŞ VERİN (fld_app_name, fld_app_module, logdatetime)
Yəni sistemin adı, sistem komponentinin adı və hadisənin tarixi ilə. Əvvəlcə tədbirin tarixi birinci gəldi. Son yerə köçürdükdən sonra sorğular təxminən iki dəfə sürətlə işləməyə başladı. Əsas açarın dəyişdirilməsi cədvəlin yenidən yaradılmasını və verilənlərin yenidən yüklənməsini tələb edəcək ki, ClickHouse diskdəki məlumatları yenidən çeşidləsin. Bu ağır əməliyyatdır, ona görə də çeşidləmə açarına nələrin daxil edilməli olduğu barədə çox düşünmək yaxşı olar.

Onu da qeyd etmək lazımdır ki, LowCardinality məlumat tipi nisbətən son versiyalarda peyda olub. Onu istifadə edərkən, aşağı kardinallığa (bir neçə seçim) malik olan sahələr üçün sıxılmış məlumatların ölçüsü kəskin şəkildə azalır.

19.6 versiyası hazırda istifadə olunur və biz ən son versiyaya yeniləməyə cəhd etməyi planlaşdırırıq. Məsələn, Adaptive Granularity, Atlama indeksləri və DoubleDelta kodek kimi gözəl xüsusiyyətlərə malikdirlər.

Varsayılan olaraq, quraşdırma zamanı giriş səviyyəsi izləməyə təyin edilir. Qeydlər fırlanır və arxivləşdirilir, lakin eyni zamanda bir gigabayta qədər genişlənir. Ehtiyac yoxdursa, o zaman xəbərdarlıq səviyyəsini təyin edə bilərsiniz, sonra jurnalın ölçüsü kəskin şəkildə azalır. Giriş parametri config.xml faylında quraşdırılıb:

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

Bəzi faydalı əmrlər

Поскольку оригинальные пакеты установки собираются по 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. Routeri FileBeat-dən RabbitMQ növbəsinə daxil edin

Bu komponent FileBeat-dən gələn qeydləri RabbitMQ növbəsinə yönləndirmək üçün istifadə olunur. Burada iki məqam var:

  1. Təəssüf ki, FileBeat-də birbaşa RabbitMQ-a yazmaq üçün çıxış plagini yoxdur. Və bu cür funksionallıq, onların github-dakı məsələyə görə, həyata keçirilməsi planlaşdırılmır. Kafka üçün plagin var, amma nədənsə evdə istifadə edə bilmirik.
  2. DMZ-də logların toplanması üçün tələblər var. Onlara əsaslanaraq, jurnallar əvvəlcə növbəyə əlavə edilməlidir və sonra LogStash növbədən daxil olanları kənardan oxuyur.

Buna görə də, serverlərin DMZ-də yerləşdiyi vəziyyət üçün belə bir az mürəkkəb sxemdən istifadə etmək lazımdır. Konfiqurasiya nümunəsi belə görünür:

iis_w3c_logs__filebeat_rabbitmq.conf

input {
 
    beats {
        port => 5044
        type => 'iis'
        ssl => true
        ssl_certificate_authorities => ["/etc/pki/tls/certs/app/ca.pem", "/etc/pki/tls/certs/app/ca-issuing.pem"]
        ssl_certificate => "/etc/pki/tls/certs/app/queue.domain.com.cer"
        ssl_key => "/etc/pki/tls/certs/app/queue.domain.com-pkcs8.key"
        ssl_verify_mode => "peer"
    }
 
}
 
output { 
  #stdout {codec => rubydebug}
 
    rabbitmq {
        host => "127.0.0.1"
        port => 5672
        exchange => "monitor.direct"
        exchange_type => "direct"
        key => "%{[fields][fld_app_name]}"
        user => "q-writer"
        password => "password"
        ssl => false
    }
}

RabbitMQ. mesaj növbəsi

Bu komponent DMZ-də log girişlərini bufer etmək üçün istifadə olunur. Qeydiyyat bir dəstə Filebeat → LogStash vasitəsilə həyata keçirilir. Oxuma LogStash vasitəsilə DMZ xaricindən həyata keçirilir. RabboitMQ vasitəsilə işləyərkən saniyədə təxminən 4 min mesaj işlənir.

Mesaj marşrutu sistem adı ilə konfiqurasiya edilir, yəni FileBeat konfiqurasiya məlumatlarına əsaslanır. Bütün mesajlar bir növbəyə gedir. Əgər nədənsə növbə xidməti dayandırılıbsa, bu, mesajların itirilməsinə səbəb olmayacaq: FileBeats əlaqə xətaları alacaq və göndərilməsini müvəqqəti dayandıracaq. Və növbədən oxuyan LogStash də şəbəkə xətalarını alacaq və əlaqənin bərpasını gözləyəcək. Bu halda verilənlər, təbii ki, artıq verilənlər bazasına yazılmayacaq.

Növbələri yaratmaq və konfiqurasiya etmək üçün aşağıdakı təlimatlardan istifadə olunur:

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"

Qrafana. İdarə panelləri

Bu komponent monitorinq məlumatlarını vizuallaşdırmaq üçün istifadə olunur. Bu halda, Grafana 4.6+ plagini üçün ClickHouse məlumat mənbəyini quraşdırmalısınız. Biz tablosunda SQL filtrlərinin işlənməsinin səmərəliliyini artırmaq üçün onu bir az tənzimləməli olduq.

Məsələn, biz dəyişənlərdən istifadə edirik və əgər onlar filtr sahəsində təyin olunmayıbsa, onda biz istərdik ki, formanın WHERE-də şərt yaratmasın ( uriStem = » AND uriStem != » ). Bu halda ClickHouse uriStem sütununu oxuyacaq. Ümumiyyətlə, biz müxtəlif variantları sınadıq və nəhayət plaqini ($valueIfEmpty makrosunu) belə düzəltdik ki, boş dəyər olduqda sütunun özünü qeyd etmədən 1-i qaytarsın.

İndi siz qrafik üçün bu sorğudan istifadə edə bilərsiniz

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

SQL-ə belə tərcümə olunur (boş uriStem sahələrinin sadəcə 1-ə çevrildiyini qeyd edin)

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

Nəticə

ClickHouse verilənlər bazasının görünüşü bazarda əlamətdar hadisəyə çevrildi. Təsəvvür etmək çətin idi ki, tamamilə pulsuz olaraq bir anda biz böyük verilənlərlə işləmək üçün güclü və praktik alətlə silahlanmışıq. Əlbəttə ki, artan ehtiyaclarla (məsələn, parçalanma və birdən çox serverə təkrarlama) sxem daha da mürəkkəbləşəcək. Ancaq ilk təəssüratlarda bu verilənlər bazası ilə işləmək çox xoşdur. Məhsulun “insanlar üçün” hazırlandığını görmək olar.

ElasticSearch ilə müqayisədə qeydlərin saxlanması və işlənməsi xərclərinin beş-on dəfə azalacağı təxmin edilir. Başqa sözlə, cari məlumat miqdarı üçün bir neçə maşından ibarət klaster qurmalı olsaq, ClickHouse istifadə edərkən, bizim üçün bir az güclü maşın kifayətdir. Bəli, əlbəttə ki, ElasticSearch də diskdə məlumatların sıxılma mexanizmlərinə və resurs istehlakını əhəmiyyətli dərəcədə azalda bilən digər funksiyalara malikdir, lakin ClickHouse ilə müqayisədə bu, daha bahalı olacaq.

Bizim tərəfimizdən heç bir xüsusi optimallaşdırma olmadan, standart parametrlərdə məlumatların yüklənməsi və verilənlər bazasından seçim inanılmaz sürətlə işləyir. Hələ çox məlumatımız yoxdur (təxminən 200 milyon qeyd), lakin server özü zəifdir. Biz bu aləti gələcəkdə logların saxlanması ilə əlaqəli olmayan digər məqsədlər üçün istifadə edə bilərik. Məsələn, başdan sona analitika üçün, təhlükəsizlik sahəsində, maşın öyrənməsi.

Sonda müsbət və mənfi cəhətləri haqqında bir az.

Eksiler

  1. Böyük partiyalarda qeydlərin yüklənməsi. Bir tərəfdən, bu bir xüsusiyyətdir, lakin qeydləri buferləşdirmək üçün hələ də əlavə komponentlərdən istifadə etməlisiniz. Bu vəzifə həmişə asan deyil, lakin hələ də həll edilə bilər. Və mən sxemi sadələşdirmək istərdim.
  2. Bəzi ekzotik funksionallıq və ya yeni funksiyalar tez-tez yeni versiyalarda pozulur. Bu, narahatlığa səbəb olur, yeni versiyaya yüksəltmək istəyini azaldır. Məsələn, Kafka masa mühərriki istehlakçıları həyata keçirmədən birbaşa Kafkadan hadisələri oxumağa imkan verən çox faydalı bir xüsusiyyətdir. Lakin github-dakı Məsələlərin sayına görə, biz hələ də bu mühərriki istehsalda istifadə etməməyə diqqət edirik. Ancaq yan tərəfə qəfil jestlər etməsəniz və əsas funksionallıqdan istifadə etsəniz, o, stabil işləyir.

Pros

  1. Yavaşlamır.
  2. Aşağı giriş həddi.
  3. Açıq mənbə.
  4. Pulsuz.
  5. Yaxşı tərəzi (qutudan parçalanma/replikasiya)
  6. Rabitə Nazirliyi tərəfindən tövsiyə olunan Rusiya proqram təminatı reyestrinə daxil edilmişdir.
  7. Yandex-dən rəsmi dəstəyin olması.

Mənbə: www.habr.com

Добавить комментарий