ClickHouse Database for Humans ή Alien Technologies

Aleksey Lizunov, Επικεφαλής του Κέντρου Αρμοδιότητας για Κανάλια Απομακρυσμένων Υπηρεσιών της Διεύθυνσης Τεχνολογιών Πληροφορικής του MKB

ClickHouse Database for Humans ή Alien Technologies

Ως εναλλακτική λύση στη στοίβα ELK (ElasticSearch, Logstash, Kibana), κάνουμε έρευνα για τη χρήση της βάσης δεδομένων ClickHouse ως αποθήκευσης δεδομένων για αρχεία καταγραφής.

Σε αυτό το άρθρο, θα θέλαμε να μιλήσουμε για την εμπειρία μας από τη χρήση της βάσης δεδομένων ClickHouse και τα προκαταρκτικά αποτελέσματα της πιλοτικής λειτουργίας. Θα πρέπει να σημειωθεί αμέσως ότι τα αποτελέσματα ήταν εντυπωσιακά.


ClickHouse Database for Humans ή Alien Technologies

Στη συνέχεια, θα περιγράψουμε με περισσότερες λεπτομέρειες πώς είναι διαμορφωμένο το σύστημά μας και από ποια στοιχεία αποτελείται. Αλλά τώρα θα ήθελα να μιλήσω λίγο για αυτήν τη βάση δεδομένων στο σύνολό της και γιατί αξίζει να δώσουμε προσοχή. Η βάση δεδομένων ClickHouse είναι μια αναλυτική βάση δεδομένων στηλών υψηλής απόδοσης από την Yandex. Χρησιμοποιείται στις υπηρεσίες Yandex, αρχικά είναι η κύρια αποθήκευση δεδομένων για το Yandex.Metrica. Σύστημα ανοιχτού κώδικα, δωρεάν. Από την πλευρά του προγραμματιστή, πάντα αναρωτιόμουν πώς το εφάρμοσαν, γιατί υπάρχουν φανταστικά μεγάλα δεδομένα. Και η ίδια η διεπαφή χρήστη της Metrica είναι πολύ ευέλικτη και γρήγορη. Στην πρώτη γνωριμία με αυτή τη βάση δεδομένων, η εντύπωση είναι: «Ε, επιτέλους! Φτιαγμένο για τους ανθρώπους! Ξεκινώντας από τη διαδικασία εγκατάστασης και τελειώνοντας με την αποστολή αιτημάτων.

Αυτή η βάση δεδομένων έχει πολύ χαμηλό όριο εισόδου. Ακόμη και ένας προγραμματιστής μέσης ειδίκευσης μπορεί να εγκαταστήσει αυτήν τη βάση δεδομένων σε λίγα λεπτά και να αρχίσει να τη χρησιμοποιεί. Όλα λειτουργούν ξεκάθαρα. Ακόμη και άτομα που είναι νέοι στο Linux μπορούν να χειριστούν γρήγορα την εγκατάσταση και να κάνουν τις πιο απλές λειτουργίες. Αν νωρίτερα, με τις λέξεις Big Data, Hadoop, Google BigTable, HDFS, ένας συνηθισμένος προγραμματιστής είχε ιδέες ότι επρόκειτο για κάποια terabyte, petabyte, ότι κάποιοι υπεράνθρωποι εμπλέκονται σε ρυθμίσεις και ανάπτυξη για αυτά τα συστήματα, τότε με την εμφάνιση του ClickHouse βάση δεδομένων, έχουμε ένα απλό, κατανοητό εργαλείο με το οποίο μπορείτε να λύσετε μια σειρά εργασιών που δεν ήταν εφικτή στο παρελθόν. Χρειάζεται μόνο ένα αρκετά μέσο μηχάνημα και πέντε λεπτά για να εγκατασταθεί. Δηλαδή, πήραμε μια τέτοια βάση δεδομένων όπως, για παράδειγμα, η MySql, αλλά μόνο για την αποθήκευση δισεκατομμυρίων εγγραφών! Ένας συγκεκριμένος υπερ-αρχειοθέτης με τη γλώσσα SQL. Είναι σαν να παρέδωσαν στους ανθρώπους τα όπλα των εξωγήινων.

Σχετικά με το σύστημα καταγραφής μας

Για τη συλλογή πληροφοριών, χρησιμοποιούνται αρχεία καταγραφής IIS εφαρμογών ιστού τυπικής μορφής (επί του παρόντος αναλύουμε αρχεία καταγραφής εφαρμογών, αλλά ο κύριος στόχος στο πιλοτικό στάδιο είναι η συλλογή αρχείων καταγραφής IIS).

Για διάφορους λόγους, δεν μπορέσαμε να εγκαταλείψουμε εντελώς τη στοίβα ELK και συνεχίζουμε να χρησιμοποιούμε τα στοιχεία LogStash και Filebeat, τα οποία έχουν αποδειχθεί καλά και λειτουργούν αρκετά αξιόπιστα και προβλέψιμα.

Το γενικό σχήμα καταγραφής φαίνεται στο παρακάτω σχήμα:

ClickHouse Database for Humans ή Alien Technologies

Ένα χαρακτηριστικό της εγγραφής δεδομένων στη βάση δεδομένων ClickHouse είναι η σπάνια (μία ανά δευτερόλεπτο) εισαγωγή εγγραφών σε μεγάλες παρτίδες. Αυτό, προφανώς, είναι το πιο «προβληματικό» μέρος που αντιμετωπίζετε όταν εργάζεστε για πρώτη φορά με τη βάση δεδομένων ClickHouse: το σχήμα γίνεται λίγο πιο περίπλοκο.
Η προσθήκη για το LogStash, η οποία εισάγει απευθείας δεδομένα στο ClickHouse, βοήθησε πολύ εδώ. Αυτό το στοιχείο αναπτύσσεται στον ίδιο διακομιστή με την ίδια τη βάση δεδομένων. Άρα, σε γενικές γραμμές, δεν συνιστάται να το κάνετε, αλλά από πρακτική άποψη, ώστε να μην παράγονται ξεχωριστοί διακομιστές ενώ είναι αναπτυγμένος στον ίδιο διακομιστή. Δεν παρατηρήσαμε αποτυχίες ή διενέξεις πόρων με τη βάση δεδομένων. Επιπλέον, θα πρέπει να σημειωθεί ότι το πρόσθετο διαθέτει μηχανισμό επανάληψης δοκιμής σε περίπτωση σφαλμάτων. Και σε περίπτωση σφαλμάτων, το πρόσθετο εγγράφει στο δίσκο μια δέσμη δεδομένων που δεν μπόρεσε να εισαχθεί (η μορφή αρχείου είναι βολική: μετά την επεξεργασία, μπορείτε εύκολα να εισαγάγετε τη διορθωμένη παρτίδα χρησιμοποιώντας το clickhouse-client).

Μια πλήρης λίστα του λογισμικού που χρησιμοποιείται στο σχήμα παρουσιάζεται στον πίνακα:

Κατάλογος λογισμικού που χρησιμοποιείται

Όνομα

Περιγραφή

Σύνδεσμος διανομής

nginx

Reverse-proxy για περιορισμό της πρόσβασης από θύρες και οργάνωση εξουσιοδότησης

Επί του παρόντος δεν χρησιμοποιείται στο σύστημα

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

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

FileBeat

Μεταφορά αρχείων καταγραφής.

https://www.elastic.co/downloads/beats/filebeat (κιτ διανομής για Windows 64bit).

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

logstash

Συλλέκτης κορμών.

Χρησιμοποιείται για τη συλλογή αρχείων καταγραφής από το FileBeat, καθώς και για τη συλλογή αρχείων καταγραφής από την ουρά RabbitMQ (για διακομιστές που βρίσκονται στο DMZ.)

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

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

Logstash-output-clickhouse

Πρόσθετο Loagstash για μεταφορά αρχείων καταγραφής στη βάση δεδομένων ClickHouse σε παρτίδες

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

Κάντε κλικ στο σπίτι

Αποθήκευση κορμού 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

Σημείωση. Από τον Αύγουστο του 2018, οι "κανονικές" κατασκευές στροφών για RHEL εμφανίστηκαν στο αποθετήριο Yandex, οπότε μπορείτε να δοκιμάσετε να τις χρησιμοποιήσετε. Κατά τη στιγμή της εγκατάστασης, χρησιμοποιούσαμε πακέτα που κατασκευάστηκαν από την Altinity.

Γκράφανα

Οπτικοποίηση ημερολογίου. Ρύθμιση πινάκων εργαλείων

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 Bit) - τελευταία έκδοση

Πηγή δεδομένων ClickHouse για Grafana 4.6+

Πρόσθετο για Grafana με πηγή δεδομένων ClickHouse

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

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

logstash

Καταγραφή του δρομολογητή από το FileBeat στην ουρά RabbitMQ.

Σημείωση. Δυστυχώς, το FileBeat δεν έχει έξοδο απευθείας στο RabbitMQ, επομένως απαιτείται ένας ενδιάμεσος σύνδεσμος με τη μορφή Logstash

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

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

RabbitMQ

ουρά μηνυμάτων. Αυτό είναι το buffer καταγραφής στο 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 (Απαιτείται για RabbitMQ)

Erlang χρόνου εκτέλεσης. Απαιτείται για να λειτουργήσει το RabbitMQ

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

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

Η διαμόρφωση διακομιστή με τη βάση δεδομένων ClickHouse παρουσιάζεται στον ακόλουθο πίνακα:

Όνομα

Αξία

Σημείωση

Διαμόρφωση

HDD: 40GB
RAM: 8GB
Επεξεργαστής: Core 2 2Ghz

Είναι απαραίτητο να δώσετε προσοχή στις συμβουλές για τη λειτουργία της βάσης δεδομένων ClickHouse (https://clickhouse.yandex/docs/ru/operations/tips/)

Γενικό λογισμικό συστήματος

ΛΣ: Red Hat Enterprise Linux Server (Maipo)

JRE (Java 8)

 

Όπως μπορείτε να δείτε, αυτός είναι ένας συνηθισμένος σταθμός εργασίας.

Η δομή του πίνακα για την αποθήκευση των κορμών έχει ως εξής:

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;

Χρησιμοποιούμε προεπιλεγμένη κατάτμηση (ανά μήνα) και ευρετηρίαση. Όλα τα πεδία πρακτικά αντιστοιχούν σε καταχωρήσεις καταγραφής IIS για την καταγραφή αιτημάτων http. Ξεχωριστά, σημειώνουμε ότι υπάρχουν ξεχωριστά πεδία για την αποθήκευση ετικετών utm (αναλύονται στο στάδιο της εισαγωγής στον πίνακα από το πεδίο συμβολοσειράς ερωτήματος).

Επίσης, πολλά πεδία συστήματος έχουν προστεθεί στον πίνακα για αποθήκευση πληροφοριών σχετικά με συστήματα, στοιχεία, διακομιστές. Δείτε τον παρακάτω πίνακα για μια περιγραφή αυτών των πεδίων. Σε έναν πίνακα, αποθηκεύουμε αρχεία καταγραφής για πολλά συστήματα.

Όνομα

Περιγραφή

Παράδειγμα

fld_app_name

Όνομα εφαρμογής/συστήματος
Έγκυρες τιμές:

  • site1.domain.com Εξωτερικός ιστότοπος 1
  • site2.domain.com Εξωτερικός ιστότοπος 2
  • interior-site1.domain.local Εσωτερικός ιστότοπος 1

site1.domain.com

fld_app_module

Μονάδα συστήματος
Έγκυρες τιμές:

  • web - Ιστοσελίδα
  • svc - Υπηρεσία τοποθεσίας Web
  • intgr - Ενσωμάτωση Web Service
  • bo - Διαχειριστής (BackOffice)

ιστός

fld_website_name

Όνομα τοποθεσίας στο IIS

Πολλά συστήματα μπορούν να αναπτυχθούν σε έναν διακομιστή ή ακόμη και πολλές παρουσίες μιας μονάδας συστήματος

κύριος ιστός

fld_server_name

Ονομα διακομιστή

web1.domain.com

fld_log_file_name

Διαδρομή προς το αρχείο καταγραφής στο διακομιστή

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

Αυτό σας επιτρέπει να δημιουργείτε αποτελεσματικά γραφήματα στο Grafana. Για παράδειγμα, δείτε αιτήματα από το frontend ενός συγκεκριμένου συστήματος. Αυτό είναι παρόμοιο με τον μετρητή ιστότοπου στο Yandex.Metrica.

Ακολουθούν ορισμένα στατιστικά στοιχεία σχετικά με τη χρήση της βάσης δεδομένων για δύο μήνες.

Αριθμός εγγραφών που αναλύονται ανά συστήματα και τα στοιχεία τους

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

Ο όγκος των δεδομένων στο δίσκο

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.

Βαθμός συμπίεσης δεδομένων σε στήλες

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.

Περιγραφή χρησιμοποιημένων εξαρτημάτων

FileBeat. Μεταφορά αρχείων καταγραφής

Αυτό το στοιχείο παρακολουθεί τις αλλαγές στα αρχεία καταγραφής στο δίσκο και μεταβιβάζει τις πληροφορίες στο LogStash. Εγκατεστημένο σε όλους τους διακομιστές όπου είναι γραμμένα αρχεία καταγραφής (συνήθως IIS). Λειτουργεί σε λειτουργία ουράς (δηλαδή μεταφέρει μόνο τις προστιθέμενες εγγραφές στο αρχείο). Αλλά χωριστά μπορεί να ρυθμιστεί ώστε να μεταφέρει ολόκληρα αρχεία. Αυτό είναι χρήσιμο όταν χρειάζεται να κάνετε λήψη δεδομένων από προηγούμενους μήνες. Απλώς βάλτε το αρχείο καταγραφής σε ένα φάκελο και θα το διαβάσει ολόκληρο.

Όταν διακοπεί η υπηρεσία, τα δεδομένα δεν μεταφέρονται πλέον στο χώρο αποθήκευσης.

Ένα παράδειγμα διαμόρφωσης μοιάζει με αυτό:

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. Συλλέκτης κορμών

Αυτό το στοιχείο έχει σχεδιαστεί για να λαμβάνει καταχωρήσεις καταγραφής από το FileBeat (ή μέσω της ουράς RabbitMQ), αναλύοντας και εισάγοντας παρτίδες στη βάση δεδομένων ClickHouse.

Για εισαγωγή στο ClickHouse, χρησιμοποιείται η προσθήκη Logstash-output-clickhouse. Η προσθήκη Logstash έχει έναν μηχανισμό επανάληψης αιτήματος, αλλά με έναν τακτικό τερματισμό, είναι καλύτερο να σταματήσετε την ίδια την υπηρεσία. Όταν διακοπεί, τα μηνύματα θα συγκεντρωθούν στην ουρά RabbitMQ, οπότε αν η διακοπή είναι για μεγάλο χρονικό διάστημα, τότε είναι καλύτερο να σταματήσετε το Filebeats στους διακομιστές. Σε ένα σύστημα όπου το RabbitMQ δεν χρησιμοποιείται (στο τοπικό δίκτυο, το Filebeat στέλνει απευθείας αρχεία καταγραφής στο Logstash), τα Filebeats λειτουργούν αρκετά αποδεκτά και με ασφάλεια, επομένως για αυτούς η μη διαθεσιμότητα της εξόδου περνά χωρίς συνέπειες.

Ένα παράδειγμα διαμόρφωσης μοιάζει με αυτό:

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

αγωγοί.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. Αποθήκευση κορμού

Τα αρχεία καταγραφής για όλα τα συστήματα αποθηκεύονται σε έναν πίνακα (δείτε στην αρχή του άρθρου). Προορίζεται για την αποθήκευση πληροφοριών σχετικά με αιτήματα: όλες οι παράμετροι είναι παρόμοιες για διαφορετικές μορφές, όπως αρχεία καταγραφής IIS, αρχεία καταγραφής apache και nginx. Για τα αρχεία καταγραφής εφαρμογών, στα οποία, για παράδειγμα, καταγράφονται σφάλματα, πληροφοριακά μηνύματα, προειδοποιήσεις, θα παρέχεται ξεχωριστός πίνακας με την κατάλληλη δομή (επί του παρόντος στο στάδιο του σχεδιασμού).

Όταν σχεδιάζετε έναν πίνακα, είναι πολύ σημαντικό να αποφασίσετε για το πρωτεύον κλειδί (με το οποίο θα ταξινομηθούν τα δεδομένα κατά την αποθήκευση). Ο βαθμός συμπίεσης δεδομένων και η ταχύτητα ερωτήματος εξαρτώνται από αυτό. Στο παράδειγμά μας, το κλειδί είναι
ΠΑΡΑΓΓΕΛΙΑ ΑΝΑ (fld_app_name, fld_app_module, logdatetime)
Δηλαδή, με το όνομα του συστήματος, το όνομα του στοιχείου συστήματος και την ημερομηνία του συμβάντος. Αρχικά, πρώτη ήταν η ημερομηνία της εκδήλωσης. Μετά τη μεταφορά του στην τελευταία θέση, τα ερωτήματα άρχισαν να λειτουργούν περίπου δύο φορές πιο γρήγορα. Η αλλαγή του πρωτεύοντος κλειδιού θα απαιτήσει την εκ νέου δημιουργία του πίνακα και την εκ νέου φόρτωση των δεδομένων, έτσι ώστε το ClickHouse να ταξινομήσει εκ νέου τα δεδομένα στο δίσκο. Αυτή είναι μια βαριά λειτουργία, επομένως είναι καλή ιδέα να σκεφτείτε πολύ τι πρέπει να συμπεριληφθεί στο κλειδί ταξινόμησης.

Θα πρέπει επίσης να σημειωθεί ότι ο τύπος δεδομένων LowCardinality εμφανίστηκε σε σχετικά πρόσφατες εκδόσεις. Κατά τη χρήση του, το μέγεθος των συμπιεσμένων δεδομένων μειώνεται δραστικά για εκείνα τα πεδία που έχουν χαμηλή καρδινάτητα (λίγες επιλογές).

Η έκδοση 19.6 χρησιμοποιείται αυτήν τη στιγμή και σκοπεύουμε να δοκιμάσουμε την ενημέρωση στην πιο πρόσφατη έκδοση. Έχουν τέτοια υπέροχα χαρακτηριστικά όπως η Adaptive Granularity, οι δείκτες παράλειψης και ο κωδικοποιητής DoubleDelta, για παράδειγμα.

Από προεπιλογή, κατά την εγκατάσταση, το επίπεδο καταγραφής έχει οριστεί σε ανίχνευση. Τα αρχεία καταγραφής περιστρέφονται και αρχειοθετούνται, αλλά ταυτόχρονα επεκτείνονται σε ένα gigabyte. Εάν δεν υπάρχει ανάγκη, τότε μπορείτε να ρυθμίσετε το επίπεδο προειδοποίησης, τότε το μέγεθος του κορμού μειώνεται δραστικά. Η ρύθμιση καταγραφής ορίζεται στο αρχείο config.xml:

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

Μερικές χρήσιμες εντολές

Поскольку оригинальные пакеты установки собираются по 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. Καταγραφή του δρομολογητή από το FileBeat στην ουρά RabbitMQ

Αυτό το στοιχείο χρησιμοποιείται για τη δρομολόγηση αρχείων καταγραφής που προέρχονται από το FileBeat στην ουρά RabbitMQ. Υπάρχουν δύο σημεία εδώ:

  1. Δυστυχώς, το FileBeat δεν διαθέτει πρόσθετο εξόδου για απευθείας εγγραφή στο RabbitMQ. Και μια τέτοια λειτουργικότητα, αν κρίνουμε από το ζήτημα στο github τους, δεν έχει προγραμματιστεί για εφαρμογή. Υπάρχει ένα πρόσθετο για τον Kafka, αλλά για κάποιο λόγο δεν μπορούμε να το χρησιμοποιήσουμε στο σπίτι.
  2. Υπάρχουν απαιτήσεις για τη συλλογή κορμών στο DMZ. Με βάση αυτά, τα αρχεία καταγραφής πρέπει πρώτα να προστεθούν στην ουρά και στη συνέχεια το LogStash διαβάζει τις καταχωρήσεις από την ουρά από έξω.

Επομένως, για την περίπτωση που οι διακομιστές βρίσκονται στο DMZ πρέπει να χρησιμοποιήσετε ένα τόσο πολύπλοκο σχήμα. Ένα παράδειγμα διαμόρφωσης μοιάζει με αυτό:

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. ουρά μηνυμάτων

Αυτό το στοιχείο χρησιμοποιείται για την προσωρινή αποθήκευση εγγραφών καταγραφής στο DMZ. Η εγγραφή γίνεται μέσω μιας δέσμης Filebeat → LogStash. Η ανάγνωση γίνεται εκτός του DMZ μέσω του LogStash. Κατά τη λειτουργία μέσω του RabboitMQ, υποβάλλονται σε επεξεργασία περίπου 4 χιλιάδες μηνύματα ανά δευτερόλεπτο.

Η δρομολόγηση μηνυμάτων διαμορφώνεται με βάση το όνομα συστήματος, δηλαδή με βάση τα δεδομένα διαμόρφωσης του FileBeat. Όλα τα μηνύματα πηγαίνουν σε μία ουρά. Εάν για κάποιο λόγο διακοπεί η υπηρεσία ουράς, τότε αυτό δεν θα οδηγήσει σε απώλεια μηνυμάτων: Το FileBeats θα λάβει σφάλματα σύνδεσης και θα αναστείλει προσωρινά την αποστολή. Και το LogStash που διαβάζει από την ουρά θα λάβει επίσης σφάλματα δικτύου και θα περιμένει να αποκατασταθεί η σύνδεση. Σε αυτήν την περίπτωση, τα δεδομένα, φυσικά, δεν θα εγγράφονται πλέον στη βάση δεδομένων.

Οι ακόλουθες οδηγίες χρησιμοποιούνται για τη δημιουργία και τη διαμόρφωση ουρών:

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"

Γραφάνα. Ταμπλό

Αυτό το στοιχείο χρησιμοποιείται για την οπτικοποίηση δεδομένων παρακολούθησης. Σε αυτήν την περίπτωση, πρέπει να εγκαταστήσετε την προσθήκη δεδομένων ClickHouse για Grafana 4.6+. Έπρεπε να το τροποποιήσουμε λίγο για να βελτιώσουμε την αποτελεσματικότητα της επεξεργασίας των φίλτρων SQL στο ταμπλό.

Για παράδειγμα, χρησιμοποιούμε μεταβλητές και αν δεν έχουν οριστεί στο πεδίο φίλτρου, τότε θα θέλαμε να μην δημιουργήσει μια συνθήκη στο WHERE της φόρμας ( uriStem = » ΚΑΙ uriStem != » ). Σε αυτήν την περίπτωση, το ClickHouse θα διαβάσει τη στήλη uriStem. Γενικά, δοκιμάσαμε διαφορετικές επιλογές και τελικά διορθώσαμε το πρόσθετο (τη μακροεντολή $valueIfEmpty) έτσι ώστε σε περίπτωση κενού τιμής να επιστρέφει 1, χωρίς να αναφέρεται η ίδια η στήλη.

Και τώρα μπορείτε να χρησιμοποιήσετε αυτό το ερώτημα για το γράφημα

$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 (σημειώστε ότι τα κενά πεδία uriStem έχουν μετατραπεί σε μόλις 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

Συμπέρασμα

Η εμφάνιση της βάσης δεδομένων ClickHouse έχει γίνει ορόσημο στην αγορά. Ήταν δύσκολο να φανταστεί κανείς ότι, εντελώς δωρεάν, σε μια στιγμή οπλιστήκαμε με ένα ισχυρό και πρακτικό εργαλείο για εργασία με μεγάλα δεδομένα. Φυσικά, με τις αυξανόμενες ανάγκες (για παράδειγμα, διαμοιρασμός και αναπαραγωγή σε πολλούς διακομιστές), το σχέδιο θα γίνει πιο περίπλοκο. Αλλά με τις πρώτες εντυπώσεις, η εργασία με αυτήν τη βάση δεδομένων είναι πολύ ευχάριστη. Μπορεί να φανεί ότι το προϊόν είναι κατασκευασμένο "για ανθρώπους".

Σε σύγκριση με το ElasticSearch, το κόστος αποθήκευσης και επεξεργασίας αρχείων καταγραφής εκτιμάται ότι θα μειωθεί κατά πέντε έως δέκα φορές. Με άλλα λόγια, εάν για τον τρέχοντα όγκο δεδομένων θα έπρεπε να δημιουργήσουμε ένα σύμπλεγμα πολλών μηχανημάτων, τότε όταν χρησιμοποιούμε το ClickHouse, μας αρκεί ένα μηχάνημα χαμηλής κατανάλωσης. Ναι, φυσικά, το ElasticSearch διαθέτει επίσης μηχανισμούς συμπίεσης δεδομένων στον δίσκο και άλλες δυνατότητες που μπορούν να μειώσουν σημαντικά την κατανάλωση πόρων, αλλά σε σύγκριση με το ClickHouse, αυτό θα είναι πιο ακριβό.

Χωρίς ιδιαίτερες βελτιστοποιήσεις από μέρους μας, στις προεπιλεγμένες ρυθμίσεις, η φόρτωση δεδομένων και η επιλογή από τη βάση δεδομένων λειτουργεί με εκπληκτική ταχύτητα. Δεν έχουμε πολλά δεδομένα ακόμα (περίπου 200 εκατομμύρια εγγραφές), αλλά ο ίδιος ο διακομιστής είναι αδύναμος. Μπορούμε να χρησιμοποιήσουμε αυτό το εργαλείο στο μέλλον για άλλους σκοπούς που δεν σχετίζονται με την αποθήκευση αρχείων καταγραφής. Για παράδειγμα, για end-to-end analytics, στον τομέα της ασφάλειας, της μηχανικής εκμάθησης.

Στο τέλος, λίγα λόγια για τα υπέρ και τα κατά.

Μειονεκτήματα

  1. Φόρτωση εγγραφών σε μεγάλες παρτίδες. Από τη μία πλευρά, αυτό είναι ένα χαρακτηριστικό, αλλά εξακολουθείτε να πρέπει να χρησιμοποιείτε πρόσθετα στοιχεία για την αποθήκευση εγγραφών στην προσωρινή μνήμη. Αυτό το έργο δεν είναι πάντα εύκολο, αλλά και πάλι επιλύσιμο. Και θα ήθελα να απλοποιήσω το σχήμα.
  2. Ορισμένες εξωτικές λειτουργίες ή νέες δυνατότητες συχνά σπάνε σε νέες εκδόσεις. Αυτό προκαλεί ανησυχία, μειώνοντας την επιθυμία για αναβάθμιση σε νέα έκδοση. Για παράδειγμα, η μηχανή πίνακα Kafka είναι μια πολύ χρήσιμη δυνατότητα που σας επιτρέπει να διαβάζετε απευθείας συμβάντα από τον Kafka, χωρίς να εφαρμόζετε καταναλωτές. Ωστόσο, αν κρίνουμε από τον αριθμό των θεμάτων στο github, εξακολουθούμε να προσέχουμε να μην χρησιμοποιήσουμε αυτόν τον κινητήρα στην παραγωγή. Ωστόσο, εάν δεν κάνετε ξαφνικές χειρονομίες στο πλάι και χρησιμοποιήσετε την κύρια λειτουργικότητα, τότε λειτουργεί σταθερά.

Πλεονεκτήματα

  1. Δεν επιβραδύνει.
  2. Χαμηλό όριο εισόδου.
  3. Ανοιχτή πηγή.
  4. Ελεύθερος.
  5. Κλιμακώνεται καλά (διαμοιρασμός/αντιγραφή εκτός συσκευασίας)
  6. Περιλαμβάνεται στο μητρώο του ρωσικού λογισμικού που συνιστάται από το Υπουργείο Επικοινωνιών.
  7. Η παρουσία επίσημης υποστήριξης από την Yandex.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο