پایگاه داده کلیک هاوس برای انسان ها یا فناوری های بیگانه

الکسی لیزونوف، رئیس مرکز صلاحیت کانال های خدمات از راه دور اداره فناوری اطلاعات MKB

پایگاه داده کلیک هاوس برای انسان ها یا فناوری های بیگانه

به عنوان جایگزینی برای پشته ELK (ElasticSearch، Logstash، Kibana)، ما در حال انجام تحقیق در مورد استفاده از پایگاه داده ClickHouse به عنوان ذخیره‌سازی داده‌ها برای گزارش‌ها هستیم.

در این مقاله می خواهیم در مورد تجربه خود در استفاده از پایگاه داده ClickHouse و نتایج اولیه عملیات پایلوت صحبت کنیم. بلافاصله باید توجه داشت که نتایج چشمگیر بود.


پایگاه داده کلیک هاوس برای انسان ها یا فناوری های بیگانه

در ادامه، نحوه پیکربندی سیستم و اجزای آن را با جزئیات بیشتری شرح خواهیم داد. اما اکنون می خواهم کمی در مورد این پایگاه داده به عنوان یک کل صحبت کنم و اینکه چرا ارزش توجه به آن را دارد. پایگاه داده ClickHouse یک پایگاه داده ستونی تحلیلی با کارایی بالا از Yandex است. این در خدمات Yandex استفاده می شود، در ابتدا ذخیره اصلی داده برای Yandex.Metrica است. سیستم منبع باز، رایگان. از نقطه نظر یک توسعه دهنده، من همیشه تعجب کرده ام که چگونه آن را پیاده سازی کرده اند، زیرا داده های فوق العاده بزرگی وجود دارد. و خود رابط کاربری متریکا بسیار انعطاف پذیر و سریع است. در اولین آشنایی با این پایگاه، تصور این است: «خب، بالاخره! ساخته شده برای مردم! از مراحل نصب شروع می شود و با ارسال درخواست ها پایان می یابد.

این پایگاه داده آستانه ورود بسیار پایینی دارد. حتی یک توسعه دهنده با مهارت متوسط ​​می تواند این پایگاه داده را در چند دقیقه نصب کرده و شروع به استفاده از آن کند. همه چیز به وضوح کار می کند. حتی افرادی که به تازگی با لینوکس آشنا هستند می توانند به سرعت نصب را انجام دهند و ساده ترین عملیات را انجام دهند. اگر قبلاً با کلمات Big Data، Hadoop، Google BigTable، HDFS، یک توسعه دهنده معمولی تصور می کرد که در مورد برخی ترابایت ها، پتابایت ها است که برخی از ابرانسان ها مشغول تنظیمات و توسعه این سیستم ها هستند، پس با ظهور ClickHouse پایگاه داده، ما یک ابزار ساده و قابل فهم دریافت کردیم که با آن می توانید طیف وسیعی از وظایف را که قبلاً دست نیافتنی نبود، حل کنید. نصب آن فقط یک دستگاه نسبتاً متوسط ​​و پنج دقیقه طول می کشد. یعنی ما چنین پایگاه داده ای به عنوان مثال MySql گرفتیم، اما فقط برای ذخیره میلیاردها رکورد! یک سوپر آرشیو خاص با زبان SQL. انگار اسلحه بیگانگان را به مردم داده اند.

درباره سیستم ثبت ما

برای جمع‌آوری اطلاعات، از فایل‌های گزارش IIS با فرمت استاندارد برنامه‌های کاربردی وب استفاده می‌شود (ما در حال حاضر در حال تجزیه گزارش‌های برنامه‌ها هستیم، اما هدف اصلی در مرحله آزمایشی جمع‌آوری گزارش‌های IIS است).

به دلایل مختلف، ما نتوانستیم به طور کامل پشته ELK را رها کنیم و همچنان از مؤلفه های LogStash و Filebeat استفاده می کنیم که خود را به خوبی ثابت کرده اند و کاملاً قابل اعتماد و قابل پیش بینی کار می کنند.

طرح کلی ثبت در شکل زیر نشان داده شده است:

پایگاه داده کلیک هاوس برای انسان ها یا فناوری های بیگانه

یکی از ویژگی های نوشتن داده ها در پایگاه داده ClickHouse، درج نادر (یک بار در ثانیه) رکوردها در دسته های بزرگ است. این، ظاهراً «مشکل‌آمیزترین» قسمتی است که در اولین تجربه کار با پایگاه داده ClickHouse با آن مواجه می‌شوید: این طرح کمی پیچیده‌تر می‌شود.
افزونه LogStash که مستقیماً داده ها را در ClickHouse وارد می کند، در اینجا کمک زیادی کرد. این مؤلفه بر روی همان سروری که خود پایگاه داده است مستقر می شود. بنابراین، به طور کلی، انجام آن توصیه نمی شود، اما از نقطه نظر عملی، به طوری که در زمانی که در همان سرور مستقر است، سرورهای جداگانه تولید نکنید. ما هیچ نقص یا تضاد منابع با پایگاه داده مشاهده نکردیم. علاوه بر این، لازم به ذکر است که افزونه دارای مکانیزم امتحان مجدد در صورت بروز خطا می باشد. و در صورت بروز خطا، افزونه دسته ای از داده ها را که نمی توانند درج کنند روی دیسک می نویسد (فرمت فایل مناسب است: پس از ویرایش، می توانید به راحتی دسته اصلاح شده را با استفاده از clickhouse-client وارد کنید).

لیست کامل نرم افزارهای مورد استفاده در این طرح در جدول ارائه شده است:

لیست نرم افزارهای مورد استفاده

نام

شرح

لینک توزیع

NGINX

پروکسی معکوس برای محدود کردن دسترسی توسط پورت ها و سازماندهی مجوز

در حال حاضر در این طرح استفاده نمی شود

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

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

FileBeat

انتقال لاگ های فایل

https://www.elastic.co/downloads/beats/filebeat (کیت توزیع برای ویندوز 64 بیت).

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، ساخت‌های «عادی» rpm برای RHEL در مخزن Yandex ظاهر شدند، بنابراین می‌توانید از آنها استفاده کنید. در زمان نصب، ما از بسته های ساخته شده توسط Altinity استفاده می کردیم.

گرافانا

تجسم گزارش راه اندازی داشبوردها

https://grafana.com/

https://grafana.com/grafana/download

Redhat & Centos (64 بیت) - آخرین نسخه

منبع داده 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

خرگوش ام کیو

صف پیام این بافر ورود به سیستم در 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: 40 گیگابایت
RAM: 8GB
پردازنده: Core 2 2GHz

توجه به نکاتی برای راه اندازی پایگاه داده کلیک هاوس (https://clickhouse.yandex/docs/ru/operations/tips/)

نرم افزار سیستم عمومی

سیستم عامل: Red Hat Enterprise Linux Server (Maipo)

JRE (جاوا 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 وجود دارد (آنها در مرحله درج در جدول از قسمت query string تجزیه می شوند).

همچنین چندین فیلد سیستمی برای ذخیره اطلاعات مربوط به سیستم ها، قطعات، سرورها به جدول اضافه شده است. برای توضیح این فیلدها به جدول زیر مراجعه کنید. در یک جدول، ما لاگ برای چندین سیستم ذخیره می کنیم.

نام

شرح

مثال

fld_app_name

نام برنامه/سیستم
مقادیر معتبر:

  • site1.domain.com سایت خارجی 1
  • site2.domain.com سایت خارجی 2
  • interior-site1.domain.local سایت داخلی 1

site1.domain.com

fld_app_module

ماژول سیستم
مقادیر معتبر:

  • وب - وب سایت
  • svc - سرویس وب سایت
  • intgr - یکپارچه سازی وب سرویس
  • bo - Admin (BackOffice)

وب

fld_website_name

نام سایت در IIS

چندین سیستم را می توان بر روی یک سرور یا حتی چندین نمونه از یک ماژول سیستم مستقر کرد

وب اصلی

fld_server_name

نام ارائهکننده

web1.domain.com

fld_log_file_name

مسیر فایل log در سرور

C:inetpublogsLogFiles
W3SVC1u_ex190711.log

این به شما این امکان را می دهد که به طور موثر نمودارها را در Grafana بسازید. به عنوان مثال، درخواست ها را از قسمت جلویی یک سیستم خاص مشاهده کنید. این شبیه به پیشخوان سایت در 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) نصب می شود. در حالت دم کار می کند (یعنی فقط رکوردهای اضافه شده را به فایل منتقل می کند). اما به طور جداگانه می توان آن را برای انتقال کل فایل ها پیکربندی کرد. این زمانی مفید است که نیاز به دانلود داده های ماه های قبل دارید. فقط فایل log را در یک پوشه قرار دهید تا آن را به طور کامل بخواند.

هنگامی که سرویس متوقف می شود، داده ها دیگر به فضای ذخیره سازی منتقل نمی شوند.

یک نمونه پیکربندی به این صورت است:

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

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"

خانه کلیک. ذخیره سازی سیاهه

گزارش‌ها برای همه سیستم‌ها در یک جدول ذخیره می‌شوند (به ابتدای مقاله مراجعه کنید). در نظر گرفته شده است که اطلاعات مربوط به درخواست‌ها را ذخیره کند: همه پارامترها برای فرمت‌های مختلف مانند گزارش‌های IIS، گزارش‌های آپاچی و nginx مشابه هستند. برای لاگ های برنامه که مثلاً خطاها، پیام های اطلاعاتی، اخطارها در آنها ثبت می شود، جدول جداگانه ای با ساختار مناسب (در حال حاضر در مرحله طراحی) ارائه خواهد شد.

هنگام طراحی جدول، تصمیم گیری در مورد کلید اصلی (که داده ها در طول ذخیره سازی بر اساس آن مرتب می شوند) بسیار مهم است. میزان فشرده سازی داده ها و سرعت پرس و جو به این بستگی دارد. در مثال ما، کلید این است
سفارش بر اساس (fld_app_name، fld_app_module، logdatetime)
یعنی با نام سیستم، نام جزء سیستم و تاریخ رویداد. در ابتدا، تاریخ رویداد اول بود. پس از انتقال آن به آخرین مکان، پرس و جوها تقریباً دو برابر سریعتر شروع به کار کردند. تغییر کلید اصلی مستلزم ایجاد مجدد جدول و بارگیری مجدد داده ها است تا ClickHouse مجدداً داده ها را روی دیسک مرتب کند. این یک عملیات سنگین است، بنابراین ایده خوبی است که در مورد مواردی که باید در کلید مرتب سازی گنجانده شود، زیاد فکر کنید.

همچنین لازم به ذکر است که نوع داده LowCardinality در نسخه های نسبتاً اخیر ظاهر شده است. هنگام استفاده از آن، اندازه داده های فشرده برای آن دسته از فیلدهایی که کاردینالیته پایینی دارند (گزینه های کمی) به شدت کاهش می یابد.

نسخه 19.6 در حال حاضر در حال استفاده است و ما قصد داریم به آخرین نسخه به روز رسانی کنیم. آنها دارای ویژگی های فوق العاده ای مانند Adaptive Granularity، Skipping Indices و کدک DoubleDelta هستند.

به‌طور پیش‌فرض، در حین نصب، سطح گزارش روی ردیابی تنظیم می‌شود. گزارش‌ها چرخانده و بایگانی می‌شوند، اما در عین حال تا یک گیگابایت گسترش می‌یابند. اگر نیازی نیست، می توانید سطح هشدار را تنظیم کنید، سپس اندازه ورود به سیستم به شدت کاهش می یابد. تنظیمات ورود به سیستم در فایل 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 آنها، برای اجرا برنامه ریزی نشده است. یک افزونه برای کافکا وجود دارد، اما به دلایلی نمی توانیم از آن در خانه استفاده کنیم.
  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 = »AND 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، در زمینه امنیت، یادگیری ماشین.

در پایان کمی در مورد جوانب مثبت و منفی.

منفی

  1. بارگیری رکوردها در دسته های بزرگ. از یک طرف، این یک ویژگی است، اما هنوز باید از اجزای اضافی برای بافر کردن رکوردها استفاده کنید. این کار همیشه آسان نیست، اما هنوز هم قابل حل است. و من می خواهم این طرح را ساده کنم.
  2. برخی از عملکردهای عجیب و غریب یا ویژگی های جدید اغلب در نسخه های جدید شکسته می شوند. این باعث نگرانی می شود و تمایل به ارتقاء به نسخه جدید را کاهش می دهد. به عنوان مثال، موتور جدول کافکا یک ویژگی بسیار مفید است که به شما امکان می‌دهد رویدادها را مستقیماً از کافکا، بدون پیاده‌سازی مصرف‌کنندگان، بخوانید. اما با قضاوت بر اساس تعداد مشکلات موجود در github، ما همچنان مراقب هستیم که از این موتور در تولید استفاده نکنیم. با این حال، اگر حرکات ناگهانی به پهلو انجام ندهید و از عملکرد اصلی استفاده نکنید، به طور پایدار کار می کند.

مزایا

  1. کند نمی شود.
  2. آستانه ورود پایین
  3. متن باز.
  4. رایگان.
  5. به خوبی مقیاس بندی می شود (شارد/تکثیر خارج از جعبه)
  6. در رجیستر نرم افزار روسی توصیه شده توسط وزارت ارتباطات گنجانده شده است.
  7. وجود پشتیبانی رسمی از Yandex.

منبع: www.habr.com

اضافه کردن نظر