Base de données ClickHouse pour les humains ou technologie extraterrestre

Alexey Lizunov, chef du centre de compétence des canaux de service à distance de la Direction des technologies de l'information de l'ICD



Comme alternative à la pile ELK (ElasticSearch, Logstash, Kibana), nous menons des recherches sur l'utilisation de la base de données ClickHouse comme entrepÎt de données pour les journaux.

Dans cet article, nous aimerions parler de notre expérience d'utilisation de la base de données ClickHouse et des résultats préliminaires de l'opération pilote. Il convient de noter tout de suite que les résultats ont été impressionnants.




Ensuite, nous dĂ©crirons plus en dĂ©tail la configuration de notre systĂšme et les composants qui le composent. Mais maintenant, je voudrais parler un peu de cette base de donnĂ©es dans son ensemble, et pourquoi vous devriez y prĂȘter attention. La base de donnĂ©es ClickHouse est une base de donnĂ©es de colonnes analytiques hautes performances de Yandex. Il est utilisĂ© dans les services Yandex, au dĂ©part c'est le principal entrepĂŽt de donnĂ©es pour Yandex.Metrica. Le systĂšme open-source est gratuit. Du point de vue du dĂ©veloppeur, j'ai toujours Ă©tĂ© intĂ©ressĂ© par la façon dont ils l'ont implĂ©mentĂ©, car il y a des donnĂ©es incroyablement volumineuses. Et l'interface utilisateur mĂ©trique elle-mĂȘme est trĂšs flexible et rapide. A la premiĂšre connaissance de cette base de donnĂ©es, l'impression: «Enfin, enfin! Conçu "pour les gens"! À partir du processus d'installation et se terminant par l'envoi de demandes. "

Cette base de donnĂ©es a un seuil d'entrĂ©e trĂšs bas. MĂȘme un dĂ©veloppeur qualifiĂ© moyen peut installer cette base de donnĂ©es en quelques minutes et commencer Ă  l'utiliser. Tout fonctionne clairement. MĂȘme les dĂ©butants de Linux peuvent rapidement passer Ă  travers l'installation et effectuer des opĂ©rations simples. Auparavant, lorsque le mot Big Data, Hadoop, Google BigTable, HDFS, le dĂ©veloppeur habituel avait l'idĂ©e qu'ils parlaient de certains tĂ©raoctets, pĂ©taoctets, que certains surhumains Ă©taient impliquĂ©s dans les paramĂštres et le dĂ©veloppement de ces systĂšmes, puis avec l'avĂšnement de la base de donnĂ©es ClickHouse, nous avons obtenu Un outil simple et comprĂ©hensible avec lequel vous pouvez rĂ©soudre la gamme de tĂąches auparavant inaccessible. Une seule voiture assez moyenne et cinq minutes Ă  installer. Autrement dit, nous avons une telle base de donnĂ©es comme, par exemple, MySql, mais uniquement pour stocker des milliards d'enregistrements! Une sorte de superviseur SQL. C'est comme si les gens recevaient des armes d'extraterrestres.

À propos de notre systùme de collecte de journaux


Pour collecter des informations, des fichiers journaux IIS d'applications Web d'un format standard sont utilisés (nous sommes également engagés dans l'analyse des journaux d'applications, mais l'objectif principal au stade de l'opération pilote avec nous est de collecter les journaux IIS).

Pour diverses raisons, nous n'avons pas complÚtement abandonné la pile ELK et nous continuons à utiliser les composants LogStash et Filebeat, qui ont fait leurs preuves et fonctionnent de maniÚre assez fiable et prévisible.

Le schéma de journalisation général est présenté dans la figure ci-dessous:



L'une des caractéristiques de l'écriture de données dans la base de données ClickHouse est l'insertion peu fréquente (une fois par seconde) d'enregistrements en lots importants. Apparemment, c'est la partie la plus «problématique» que vous rencontrez lorsque vous rencontrez pour la premiÚre fois la base de données ClickHouse: le schéma est un peu compliqué.
Le plugin LogStash a beaucoup aidĂ© ici, qui insĂšre directement des donnĂ©es dans ClickHouse. Ce composant est dĂ©ployĂ© sur le mĂȘme serveur que la base de donnĂ©es elle-mĂȘme. Donc, d'une maniĂšre gĂ©nĂ©rale, il n'est pas recommandĂ© de le faire, mais d'un point de vue pratique, afin de ne pas produire de serveurs sĂ©parĂ©s pendant qu'il est dĂ©ployĂ© sur le mĂȘme serveur. Nous n'avons pas observĂ© d'Ă©checs ou de conflits de ressources avec la base de donnĂ©es. De plus, il est Ă  noter que le plugin dispose d'un mĂ©canisme de retray en cas d'erreur. Et en cas d'erreur, le plugin Ă©crit sur le disque un paquet de donnĂ©es qui n'a pas pu ĂȘtre insĂ©rĂ© (le format de fichier est pratique: aprĂšs l'Ă©dition, vous pouvez facilement insĂ©rer le paquet corrigĂ© en utilisant clickhouse-client).

La liste complÚte des logiciels utilisés dans le schéma est présentée dans le tableau:

Liste des logiciels utilisés
Le titre
La description
Lien de distribution

Nginx


Proxy inverse pour restreindre l'accĂšs au port et l'autorisation



Non utilisé actuellement dans le circuit.


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


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


Filebeat


Transférez les journaux de fichiers.


https://www.elastic.co/downloads/beats/filebeat (distribution pour Windows 64 bits).


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


Logstash


Collecteur de journaux.



Utilisé pour collecter les journaux de FileBeat, ainsi que pour collecter les journaux de la file d'attente RabbitMQ (pour les serveurs qui se trouvent dans la DMZ.)


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


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


Logstash - sortie - clickhouse


Plugin Loagstash pour transférer des journaux vers la base de données ClickHouse par lots


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


Référentiel de journaux 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


Remarque Depuis août 2018, les assemblys rpm «normaux» pour RHEL sont apparus dans le référentiel Yandex, vous pouvez donc essayer de les utiliser. Au moment de l'installation, nous utilisions des packages compilés par Altinity.


Grafana


Visualisation du journal. Configurer les tableaux de bord



https://grafana.com/


https://grafana.com/grafana/download



Redhat & Centos (64 Bit) - DerniĂšre version


Source de données ClickHouse pour Grafana 4.6+


Plugin Grafana avec source de données ClickHouse


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


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


Logstash


Connectez le routeur de FileBeat Ă  la file d'attente RabbitMQ.


Remarque Malheureusement, FileBeat n'a pas de sortie directement dans RabbitMQ, donc un lien intermédiaire sous la forme de Logstash est requis


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


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


Rabbitmq


File d'attente des messages Ceci est un tampon d'entrées de journal dans 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 (requis pour RabbitMQ)


Exécution d'Erlang. Requis pour que RabbitMQ fonctionne


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


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




La configuration du serveur avec la base de données ClickHouse est présentée dans le tableau suivant:
Le titre
Valeur
Remarque

La configuration


Disque dur: 40 Go
RAM: 8 Go
Processeur: Core 2 2Ghz


Il est nĂ©cessaire de prĂȘter attention aux conseils sur le fonctionnement de la base de donnĂ©es ClickHouse ( https://clickhouse.yandex/docs/ru/operations/tips/ )


Logiciel Ă  l'Ă©chelle du systĂšme


SystĂšme d'exploitation: Red Hat Enterprise Linux Server (Maipo)


JRE (Java 8)




Comme vous pouvez le voir, il s'agit d'un poste de travail normal.

La structure du tableau de stockage des journaux est la suivante:

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; 


Nous utilisons des valeurs par dĂ©faut pour le partitionnement (par mois) et la granularitĂ© de l'index. Tous les champs correspondent pratiquement aux entrĂ©es du journal IIS pour l'enregistrement des requĂȘtes http. SĂ©parĂ©ment, des champs sĂ©parĂ©s pour stocker les balises utm (ils sont analysĂ©s au stade de l'insertion dans la table Ă  partir du champ de chaĂźne de requĂȘte).

Dans le tableau, plusieurs champs systĂšme sont Ă©galement ajoutĂ©s pour stocker des informations sur les systĂšmes, les composants et les serveurs. Voir le tableau ci-dessous pour une description de ces champs. Dans une mĂȘme table, nous stockons les journaux de plusieurs systĂšmes.

Le titre
La description
Exemple

fld_app_name


Nom de l'application / du systĂšme
Valeurs valides:


  • site1.domain.com Site externe 1
  • site2.domain.com Site externe 2
  • internal-site1.domain.local Site interne 1

site1.domain.com

fld_app_module


Module systĂšme
Valeurs valides:


  • web - Site Web
  • svc - Service de site Web
  • intgr - Service d'intĂ©gration Web
  • bo - Administrateur (BackOffice)

web


fld_website_name


Nom du site Web dans IIS


Plusieurs systĂšmes peuvent ĂȘtre dĂ©ployĂ©s sur un serveur, voire plusieurs instances d'un mĂȘme module systĂšme


web-main


fld_server_name


Nom du serveur


web1.domain.com


fld_log_file_name


Chemin d'accĂšs au fichier journal sur le serveur


C: \ inetpub \ logs \ LogFiles
\ W3SVC1 \ u_ex190711.log

Cela vous permet de créer efficacement des graphiques dans Grafana. Par exemple, affichez les demandes du frontend d'un systÚme spécifique. Ceci est similaire au compteur de site dans Yandex.Metrica.

Voici quelques statistiques sur l'utilisation de la base de données pendant deux mois.

Nombre d'enregistrements par systĂšme et composant
 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.) 

La quantité de données sur le disque
 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. 

Le degré de compression des données dans les colonnes
 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. 


Description des composants utilisés

FileBeat. Transfert du journal des fichiers


Ce composant surveille les modifications des fichiers journaux sur le disque et transfÚre les informations à LogStash. Il est installé sur tous les serveurs sur lesquels les fichiers journaux sont écrits (généralement IIS). Il fonctionne en mode queue (c'est-à-dire qu'il transfÚre uniquement les enregistrements ajoutés dans un fichier). Mais séparément, vous pouvez configurer l'intégralité du transfert de fichiers. Ceci est utile lorsque vous devez télécharger des données des mois précédents. Mettez simplement le fichier journal dans un dossier et il le lira dans son intégralité.

Lorsque le service s'arrĂȘte, les donnĂ©es cessent d'ĂȘtre transfĂ©rĂ©es vers le stockage.

Un exemple de configuration est le suivant:

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 Collecteur de journaux


Ce composant est destiné à recevoir des entrées de journal de FileBeat (ou via la file d'attente RabbitMQ), à analyser et à insérer des bundles dans la base de données ClickHouse.

Pour insĂ©rer dans ClickHouse, le plug-in Logstash-output-clickhouse est utilisĂ©. Le plugin Logstash a un mĂ©canisme pour rĂ©cupĂ©rer les requĂȘtes, mais avec un arrĂȘt rĂ©gulier, il est prĂ©fĂ©rable d'arrĂȘter le service lui-mĂȘme. Lorsque vous vous arrĂȘtez, les messages s'accumulent dans la file d'attente RabbitMQ, donc si vous vous arrĂȘtez pendant longtemps, il est prĂ©fĂ©rable d'arrĂȘter Filebeats sur les serveurs. Dans un schĂ©ma oĂč RabbitMQ n'est pas utilisĂ© (sur un rĂ©seau local, Filebeat envoie des journaux directement Ă  Logstash), Filebeats fonctionne de maniĂšre assez raisonnable et sĂ»re, donc pour eux l'inaccessibilitĂ© de la sortie est sans consĂ©quence.

Un exemple de configuration est le suivant:

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. Stockage des journaux


Les journaux de tous les systÚmes sont enregistrés dans une seule table (voir le début de l'article). Il est destiné à stocker des informations sur les demandes: tous les paramÚtres sont similaires pour différents formats, par exemple, les journaux IIS, les journaux apache et nginx. Pour les journaux d'application dans lesquels, par exemple, des erreurs, des messages d'information, des avertissements sont enregistrés, un tableau séparé sera fourni avec la structure correspondante (maintenant au stade de la conception).

Lors de la conception d'une table, il est trĂšs important de dĂ©terminer la clĂ© primaire (selon laquelle les donnĂ©es seront triĂ©es pendant le stockage). Le degrĂ© de compression des donnĂ©es et la vitesse de requĂȘte en dĂ©pendent. Dans notre exemple, la clĂ© est
ORDER BY (fld_app_name, fld_app_module, logdatetime)
C'est-Ă -dire par le nom du systĂšme, le nom du composant systĂšme et la date de l'Ă©vĂ©nement. La date d'origine de l'Ă©vĂ©nement Ă©tait en premier lieu. AprĂšs l'avoir dĂ©placĂ© au dernier endroit, les requĂȘtes ont commencĂ© Ă  fonctionner environ deux fois plus rapidement. La modification de la clĂ© primaire nĂ©cessitera de recrĂ©er la table et de recharger les donnĂ©es pour que ClickHouse trie Ă  nouveau les donnĂ©es sur le disque. Il s'agit d'une opĂ©ration difficile, il est donc conseillĂ© de penser Ă  l'avance ce qui doit ĂȘtre inclus dans la clĂ© de tri.

Il convient également de noter que relativement dans les versions récentes, le type de données LowCardinality est apparu. Lors de son utilisation, la taille des données compressées est fortement réduite pour les champs qui ont une faible cardinalité (peu d'options).

Maintenant, la version 19.6 est utilisée et nous prévoyons d'essayer de mettre à jour la version au plus tard. Ils comprenaient des fonctionnalités merveilleuses telles que la granularité adaptative, les indices de saut et le codec DoubleDelta, par exemple.

Par défaut, lors de l'installation, le niveau du journal de configuration est défini sur trace. Les journaux sont tournés et archivés, mais s'étendent à un gigaoctet. S'il n'y a pas besoin, vous pouvez définir le niveau d'avertissement, puis la taille du journal diminue fortement. Les paramÚtres de journalisation sont définis dans le fichier config.xml:

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

Quelques commandes utiles
       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 Routeur de journaux FileBeat vers la file d'attente RabbitMQ


Ce composant est utilisé pour router les journaux provenant de FileBeat vers la file d'attente RabbitMQ. Il y a deux points:

  1. Malheureusement, FileBeat n'a pas de plugin de sortie pour Ă©crire directement sur RabbitMQ. Et une telle fonctionnalitĂ©, Ă  en juger par l'ish sur leur github, n'est pas prĂ©vue pour la mise en Ɠuvre. Il existe un plugin pour Kafka, mais pour une raison quelconque, nous ne pouvons pas l'utiliser Ă  la maison.
  2. Il existe des exigences pour la collecte des journaux dans la DMZ. Sur cette base, les journaux doivent d'abord ĂȘtre ajoutĂ©s Ă  la file d'attente, puis LogStash de l'extĂ©rieur lit les entrĂ©es de la file d'attente.

Par conséquent, c'est précisément pour le cas de l'emplacement du serveur dans la DMZ que vous devez utiliser un schéma aussi légÚrement compliqué. Un exemple de configuration est le suivant:

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. File d'attente des messages


Ce composant est utilisĂ© pour mettre en mĂ©moire tampon les entrĂ©es de journal dans la DMZ. L'enregistrement se fait via le lien Filebeat → LogStash La lecture se fait depuis l'extĂ©rieur de la DMZ via LogStash. Lorsque vous utilisez RabboitMQ, environ 4 000 messages sont traitĂ©s par seconde.

Le routage des messages est configurĂ© en fonction du nom du systĂšme, c'est-Ă -dire en fonction des donnĂ©es de configuration de FileBeat. Tous les messages tombent dans une file d'attente. Si, pour une raison quelconque, le service de file d'attente est arrĂȘtĂ©, cela n'entraĂźnera pas de perte de messages: FileBeats recevra des erreurs de connexion et suspendra l'envoi temporaire. Et LogStash, qui lit Ă  partir de la file d'attente, recevra Ă©galement des erreurs rĂ©seau et attendra que la connexion reprenne. Les donnĂ©es dans ce cas, bien sĂ»r, ne seront plus Ă©crites dans la base de donnĂ©es.

Les instructions suivantes sont utilisées pour créer et configurer des files d'attente:

 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 Tableaux de bord


Ce composant est utilisé pour visualiser les données de surveillance. Dans ce cas, vous devez installer la source de données ClickHouse pour le plug-in Grafana 4.6+. Nous avons dû le modifier un peu pour augmenter l'efficacité du traitement des filtres SQL sur un tableau de bord.

Par exemple, nous utilisons des variables, et si elles ne sont pas dĂ©finies dans le champ de filtre, nous aimerions qu'il ne gĂ©nĂšre pas de condition sous la forme WHERE (uriStem = `` AND uriStem! = ''). Dans ce cas, ClickHouse lira la colonne uriStem. En gĂ©nĂ©ral, nous avons essayĂ© diffĂ©rentes options et finalement corrigĂ© le plugin (macro $ valueIfEmpty) de sorte qu'en cas de valeur vide, il retournerait 1, sans mentionner la colonne elle-mĂȘme.

Et maintenant, vous pouvez utiliser cette requĂȘte pour le graphique

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

qui est converti en SQL (notez que les champs uriStem vides ont été convertis en seulement 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 

Conclusion


L'apparition de la base de données ClickHouse est devenue un événement marquant sur le marché. Il était difficile d'imaginer que gratuitement en un instant, nous étions armés d'un outil puissant et pratique pour travailler avec les mégadonnées. Bien sûr, avec des besoins croissants (par exemple, partitionnement et réplication sur plusieurs serveurs), le schéma deviendra plus complexe. Mais à premiÚre vue, travailler avec cette base de données est trÚs agréable. On peut voir que le produit est fait "pour les gens".

Par rapport à ElasticSearch, le coût de stockage et de traitement des journaux, selon les estimations préliminaires, est réduit de cinq à dix fois. En d'autres termes, si pour la quantité actuelle de données, nous devons configurer un cluster de plusieurs machines, alors lorsque vous utilisez ClickHouse, nous n'avons besoin que d'une seule machine à faible puissance. Oui, bien sûr, ElasticSearch dispose également de mécanismes de compression des données sur disque et d'autres fonctionnalités qui peuvent réduire considérablement la consommation de ressources, mais par rapport à ClickHouse, cela sera coûteux.

Sans aucune optimisation particuliĂšre de sa part, sur les paramĂštres par dĂ©faut, le chargement des donnĂ©es et la rĂ©cupĂ©ration des donnĂ©es de la base de donnĂ©es fonctionnent Ă  une vitesse incroyable. Jusqu'Ă  prĂ©sent, nous avons un peu de donnĂ©es (environ 200 millions d'enregistrements), mais le serveur lui-mĂȘme est faible. À l'avenir, nous pouvons utiliser cet outil Ă  d'autres fins non liĂ©es au stockage des journaux. Par exemple, pour l'analyse de bout en bout, dans le domaine de la sĂ©curitĂ©, du machine learning.

En fin de compte, un peu sur les avantages et les inconvénients.

Inconvénients


  1. Téléchargement d'enregistrements en gros lots. Ceci, d'une part, est une fonctionnalité, mais vous devez toujours utiliser des composants supplémentaires pour tamponner les enregistrements. Cette tùche n'est pas toujours simple, mais toujours résoluble. Et je voudrais simplifier le schéma.
  2. Certaines fonctionnalités exotiques ou nouvelles fonctionnalités font souvent leur apparition dans de nouvelles versions. Cela soulÚve des préoccupations, réduisant le désir de passer à une nouvelle version. Par exemple, le moteur de table Kafka est une fonctionnalité trÚs utile qui vous permet de lire directement les événements de Kafka, sans implémentation de consommateurs. Mais à en juger par le nombre de problÚmes sur le github, nous sommes toujours réticents à utiliser ce moteur en production. Cependant, si vous ne faites pas de mouvements brusques sur le cÎté et utilisez les fonctionnalités de base, cela fonctionne de maniÚre stable.

Avantages


  1. Cela ne ralentit pas.
  2. Seuil d'entrée bas.
  3. Open source
  4. C'est gratuit.
  5. S'adapte bien (partitionnement / rĂ©plication prĂȘts Ă  l'emploi)
  6. Il est inclus dans le registre des logiciels russes recommandé par le ministÚre des Communications.
  7. La présence du soutien officiel de Yandex.

Source: https://habr.com/ru/post/fr472912/


All Articles