ฐานข้อมูล ClickHouse สำหรับมนุษย์หรือเทคโนโลยีเอเลี่ยน

Aleksey Lizunov หัวหน้าศูนย์ความสามารถสำหรับช่องทางบริการระยะไกลของคณะกรรมการเทคโนโลยีสารสนเทศของ MKB

ฐานข้อมูล ClickHouse สำหรับมนุษย์หรือเทคโนโลยีเอเลี่ยน

เพื่อเป็นทางเลือกแทน ELK stack (ElasticSearch, Logstash, Kibana) เรากำลังทำการวิจัยเกี่ยวกับการใช้ฐานข้อมูล ClickHouse เป็นที่เก็บข้อมูลสำหรับบันทึก

ในบทความนี้ เราจะขอพูดถึงประสบการณ์การใช้ฐานข้อมูล ClickHouse และผลลัพธ์เบื้องต้นของการดำเนินการนำร่อง ควรสังเกตทันทีว่าผลลัพธ์นั้นน่าประทับใจ


ฐานข้อมูล ClickHouse สำหรับมนุษย์หรือเทคโนโลยีเอเลี่ยน

ต่อไป เราจะอธิบายรายละเอียดเพิ่มเติมว่าระบบของเราได้รับการกำหนดค่าอย่างไร และประกอบด้วยส่วนประกอบใดบ้าง แต่ตอนนี้ฉันอยากจะพูดเล็กน้อยเกี่ยวกับฐานข้อมูลนี้ในภาพรวม และเหตุใดจึงควรให้ความสนใจ ฐานข้อมูล ClickHouse เป็นฐานข้อมูลคอลัมน์วิเคราะห์ประสิทธิภาพสูงจากยานเดกซ์ มันถูกใช้ในบริการ Yandex โดยเริ่มแรกเป็นที่เก็บข้อมูลหลักสำหรับ Yandex.Metrica ระบบโอเพ่นซอร์ส ฟรี จากมุมมองของนักพัฒนา ฉันสงสัยมาตลอดว่าพวกเขาใช้งานอย่างไร เพราะมีข้อมูลขนาดใหญ่ที่น่าอัศจรรย์ ส่วนติดต่อผู้ใช้ของ Metrica นั้นมีความยืดหยุ่นและรวดเร็วมาก เมื่อทำความรู้จักกับฐานข้อมูลนี้เป็นครั้งแรกความประทับใจคือ: "ในที่สุด! ทำเพื่อประชาชน! เริ่มตั้งแต่ขั้นตอนการติดตั้งและสิ้นสุดด้วยการส่งคำขอ

ฐานข้อมูลนี้มีเกณฑ์รายการที่ต่ำมาก แม้แต่นักพัฒนาที่มีทักษะปานกลางก็สามารถติดตั้งฐานข้อมูลนี้ได้ในเวลาไม่กี่นาทีและเริ่มใช้งานได้ ทุกอย่างทำงานได้อย่างชัดเจน แม้แต่ผู้ที่ยังใหม่กับ Linux ก็สามารถจัดการการติดตั้งและดำเนินการที่ง่ายที่สุดได้อย่างรวดเร็ว หากก่อนหน้านี้ด้วยคำว่า Big Data, Hadoop, Google BigTable, HDFS นักพัฒนาทั่วไปมีความคิดว่ามันเกี่ยวกับเทราไบต์หรือเพตะไบต์จำนวนหนึ่งที่มนุษย์ธรรมดาบางคนมีส่วนร่วมในการตั้งค่าและการพัฒนาสำหรับระบบเหล่านี้ การถือกำเนิดของ ClickHouse ฐานข้อมูล เรามีเครื่องมือที่เรียบง่ายและเข้าใจได้ ซึ่งคุณสามารถแก้ไขงานต่างๆ ที่ไม่สามารถบรรลุได้ก่อนหน้านี้ ใช้เวลาเพียงหนึ่งเครื่องโดยเฉลี่ยและห้านาทีในการติดตั้ง นั่นคือเราได้ฐานข้อมูลเช่น MySql แต่สำหรับการจัดเก็บหลายพันล้านระเบียนเท่านั้น! super-archiver บางตัวที่มีภาษา SQL มันเหมือนคนได้รับอาวุธของมนุษย์ต่างดาว

เกี่ยวกับระบบบันทึกของเรา

ในการรวบรวมข้อมูล จะใช้ไฟล์บันทึก IIS ของเว็บแอปพลิเคชันรูปแบบมาตรฐาน (ขณะนี้เรากำลังแยกวิเคราะห์บันทึกแอปพลิเคชันด้วย แต่เป้าหมายหลักในขั้นตอนนำร่องคือการรวบรวมบันทึก IIS)

ด้วยเหตุผลต่างๆ นานา เราจึงไม่สามารถละทิ้ง ELK stack ได้อย่างสมบูรณ์ และเรายังคงใช้ส่วนประกอบ LogStash และ Filebeat ซึ่งพิสูจน์แล้วว่าทำงานได้ดีและทำงานได้ค่อนข้างน่าเชื่อถือและคาดการณ์ได้

รูปแบบการบันทึกทั่วไปแสดงในรูปด้านล่าง:

ฐานข้อมูล ClickHouse สำหรับมนุษย์หรือเทคโนโลยีเอเลี่ยน

คุณลักษณะของการเขียนข้อมูลไปยังฐานข้อมูล ClickHouse นั้นไม่บ่อยนัก (หนึ่งครั้งต่อวินาที) การแทรกบันทึกเป็นชุดใหญ่ เห็นได้ชัดว่านี่เป็นส่วนที่ "มีปัญหา" ที่สุดที่คุณพบเมื่อคุณใช้งานฐานข้อมูล ClickHouse เป็นครั้งแรก โครงร่างจะซับซ้อนขึ้นเล็กน้อย
ปลั๊กอินสำหรับ LogStash ซึ่งแทรกข้อมูลโดยตรงลงใน ClickHouse ช่วยได้มากที่นี่ คอมโพเนนต์นี้ถูกปรับใช้บนเซิร์ฟเวอร์เดียวกันกับฐานข้อมูล ดังนั้น โดยทั่วไปแล้ว จึงไม่แนะนำให้ทำ แต่จากมุมมองที่ใช้งานได้จริง เพื่อไม่ให้สร้างเซิร์ฟเวอร์แยกต่างหากในขณะที่ใช้งานบนเซิร์ฟเวอร์เดียวกัน เราไม่ได้สังเกตเห็นความล้มเหลวหรือความขัดแย้งของทรัพยากรกับฐานข้อมูล นอกจากนี้ ควรสังเกตว่าปลั๊กอินมีกลไกการลองใหม่ในกรณีที่เกิดข้อผิดพลาด และในกรณีที่เกิดข้อผิดพลาด ปลั๊กอินจะเขียนชุดข้อมูลที่ไม่สามารถแทรกลงดิสก์ได้ (รูปแบบไฟล์สะดวก: หลังจากแก้ไขแล้ว คุณสามารถแทรกชุดข้อมูลที่แก้ไขแล้วได้อย่างง่ายดายโดยใช้ไคลเอนต์คลิกเฮาส์)

รายการซอฟต์แวร์ทั้งหมดที่ใช้ในโครงร่างแสดงในตาราง:

รายการซอฟต์แวร์ที่ใช้

ชื่อ

ลักษณะ

ลิงค์จำหน่าย

NGINX

Reverse-proxy เพื่อจำกัดการเข้าถึงโดยพอร์ตและจัดระเบียบการอนุญาต

ปัจจุบันไม่ได้ใช้ในโครงการ

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

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

ไฟล์บีท

การถ่ายโอนบันทึกไฟล์

https://www.elastic.co/downloads/beats/filebeat (ชุดการแจกจ่ายสำหรับ Windows 64 บิต)

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

ที่เก็บล็อก

ตัวเก็บบันทึก

ใช้เพื่อรวบรวมบันทึกจาก FileBeat รวมถึงรวบรวมบันทึกจากคิว RabbitMQ (สำหรับเซิร์ฟเวอร์ที่อยู่ใน DMZ)

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

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

Logstash-เอาท์พุท-clickhouse

ปลั๊กอิน Loagstash สำหรับถ่ายโอนบันทึกไปยังฐานข้อมูล ClickHouse เป็นชุด

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

/usr/share/logstash/bin/logstash-plugin ติดตั้ง logstash-output-clickhouse

/usr/share/logstash/bin/logstash-plugin ติดตั้ง logstash-filter-prune

/usr/share/logstash/bin/logstash-plugin ติดตั้ง 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

ที่เก็บล็อก

บันทึกเราเตอร์จากคิว FileBeat ไปยัง RabbitMQ

บันทึก. น่าเสียดายที่ FileBeat ไม่ส่งออกไปยัง RabbitMQ โดยตรง ดังนั้นจึงจำเป็นต้องมีลิงก์กลางในรูปแบบของ Logstash

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

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

RabbitMQ

คิวข้อความ นี่คือบัฟเฟอร์บันทึกใน 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 (ไมโป)

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 (พวกเขาแยกวิเคราะห์ในขั้นตอนของการแทรกลงในตารางจากฟิลด์สตริงข้อความค้นหา)

นอกจากนี้ ยังมีการเพิ่มฟิลด์ระบบหลายฟิลด์ลงในตารางเพื่อเก็บข้อมูลเกี่ยวกับระบบ ส่วนประกอบ เซิร์ฟเวอร์ ดูตารางด้านล่างสำหรับคำอธิบายของฟิลด์เหล่านี้ ในตารางเดียว เราจัดเก็บบันทึกสำหรับหลายระบบ

ชื่อ

ลักษณะ

ตัวอย่าง

fld_app_name

ชื่อแอปพลิเคชัน/ระบบ
ค่าที่ถูกต้อง:

  • site1.domain.com ไซต์ภายนอก 1
  • site2.domain.com ไซต์ภายนอก 2
  • internal-site1.domain.local ไซต์ภายใน 1

site1.domain.com

fld_app_module

โมดูลระบบ
ค่าที่ถูกต้อง:

  • เว็บ - เว็บไซต์
  • svc - บริการเว็บไซต์
  • intgr - บริการเว็บบูรณาการ
  • โบ - ผู้ดูแลระบบ (BackOffice)

เว็บ

fld_เว็บไซต์_ชื่อ

ชื่อไซต์ใน IIS

สามารถติดตั้งได้หลายระบบบนเซิร์ฟเวอร์เดียว หรือแม้แต่หลายอินสแตนซ์ของโมดูลระบบเดียว

เว็บหลัก

fld_server_name

ชื่อเซิร์ฟเวอร์

web1.โดเมน.com

fld_log_file_name.fld_log_file_name

พาธไปยังล็อกไฟล์บนเซิร์ฟเวอร์

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.

คำอธิบายส่วนประกอบที่ใช้

ไฟล์บีท การถ่ายโอนบันทึกไฟล์

คอมโพเนนต์นี้ติดตามการเปลี่ยนแปลงไฟล์บันทึกบนดิสก์และส่งข้อมูลไปยัง 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: ~

ที่เก็บล็อก ตัวรวบรวมบันทึก

คอมโพเนนต์นี้ออกแบบมาเพื่อรับรายการบันทึกจาก 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"

คลิกเฮาส์ บันทึกการจัดเก็บ

บันทึกสำหรับระบบทั้งหมดจะถูกเก็บไว้ในตารางเดียว (ดูที่จุดเริ่มต้นของบทความ) มีจุดประสงค์เพื่อจัดเก็บข้อมูลเกี่ยวกับคำขอ: พารามิเตอร์ทั้งหมดจะคล้ายกันสำหรับรูปแบบที่แตกต่างกัน เช่น บันทึก IIS, apache และบันทึก nginx สำหรับบันทึกของแอปพลิเคชัน ซึ่งมีการบันทึกข้อผิดพลาด ข้อความแสดงข้อมูล คำเตือน ตารางแยกต่างหากจะมีโครงสร้างที่เหมาะสม (ขณะนี้อยู่ในขั้นตอนการออกแบบ)

เมื่อออกแบบตาราง การตัดสินใจเลือกคีย์หลักเป็นสิ่งสำคัญมาก (ซึ่งข้อมูลจะถูกจัดเรียงระหว่างการจัดเก็บ) ระดับของการบีบอัดข้อมูลและความเร็วในการค้นหาขึ้นอยู่กับสิ่งนี้ ในตัวอย่างของเรา กุญแจสำคัญคือ
สั่งซื้อโดย (fld_app_name, fld_app_module, logdatetime)
นั่นคือตามชื่อของระบบ ชื่อของคอมโพเนนต์ของระบบ และวันที่ของเหตุการณ์ ในขั้นต้นวันที่ของเหตุการณ์มาก่อน หลังจากย้ายไปยังตำแหน่งสุดท้าย ข้อความค้นหาเริ่มทำงานเร็วขึ้นประมาณสองเท่า การเปลี่ยนคีย์หลักจะต้องสร้างตารางใหม่และโหลดข้อมูลซ้ำ เพื่อให้ ClickHouse จัดเรียงข้อมูลบนดิสก์ใหม่ นี่เป็นการดำเนินการที่หนัก ดังนั้นจึงควรคิดให้มากเกี่ยวกับสิ่งที่ควรรวมไว้ในคีย์การเรียงลำดับ

ควรสังเกตด้วยว่าชนิดข้อมูล LowCardinality ปรากฏในเวอร์ชันที่ค่อนข้างใหม่ เมื่อใช้งาน ขนาดของข้อมูลที่บีบอัดจะลดลงอย่างมากสำหรับฟิลด์เหล่านั้นที่มีจำนวนสมาชิกต่ำ (ตัวเลือกน้อย)

เวอร์ชัน 19.6 กำลังใช้งานอยู่ และเราวางแผนที่จะลองอัปเดตเป็นเวอร์ชันล่าสุด พวกเขามีคุณสมบัติที่ยอดเยี่ยม เช่น Adaptive Granularity, Skipping indices และ DoubleDelta codec เป็นต้น

ตามค่าดีฟอลต์ ระหว่างการติดตั้ง ระดับการบันทึกจะถูกตั้งค่าเป็นการติดตาม บันทึกจะถูกหมุนและเก็บถาวร แต่ในขณะเดียวกันก็ขยายได้ถึงกิกะไบต์ หากไม่จำเป็น คุณสามารถตั้งค่าระดับการเตือน จากนั้นขนาดของบันทึกจะลดลงอย่างมาก การตั้งค่าการบันทึกถูกตั้งค่าในไฟล์ 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

ที่เก็บล็อก บันทึกเราเตอร์จากคิว 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
    }
}

แรบบิทเอ็มคิว. คิวข้อความ

ส่วนประกอบนี้ใช้เพื่อบัฟเฟอร์รายการบันทึกใน 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 ล้านบันทึก) แต่เซิร์ฟเวอร์เองก็อ่อนแอ เราสามารถใช้เครื่องมือนี้ในอนาคตเพื่อวัตถุประสงค์อื่นที่ไม่เกี่ยวข้องกับการจัดเก็บบันทึก ตัวอย่างเช่น สำหรับการวิเคราะห์แบบครบวงจร ในด้านความปลอดภัย การเรียนรู้ของเครื่อง

ในตอนท้ายเล็กน้อยเกี่ยวกับข้อดีและข้อเสีย

cons

  1. กำลังโหลดบันทึกเป็นชุดใหญ่ ในแง่หนึ่ง นี่เป็นคุณสมบัติ แต่คุณยังคงต้องใช้ส่วนประกอบเพิ่มเติมสำหรับการบันทึกบัฟเฟอร์ งานนี้ไม่ง่ายเสมอไป แต่ก็ยังสามารถแก้ไขได้ และฉันต้องการทำให้โครงร่างง่ายขึ้น
  2. ฟังก์ชันแปลกใหม่หรือคุณลักษณะใหม่ๆ บางอย่างมักใช้งานไม่ได้ในเวอร์ชันใหม่ สิ่งนี้ทำให้เกิดความกังวลลดความปรารถนาที่จะอัปเกรดเป็นเวอร์ชันใหม่ ตัวอย่างเช่น เอ็นจิ้นตารางคาฟคาเป็นคุณลักษณะที่มีประโยชน์มากที่ช่วยให้คุณอ่านเหตุการณ์จากคาฟคาได้โดยตรง โดยไม่ต้องใช้งานคอนซูเมอร์ แต่เมื่อพิจารณาจากจำนวนปัญหาบน GitHub เรายังคงระมัดระวังที่จะไม่ใช้เอนจิ้นนี้ในการผลิต อย่างไรก็ตาม หากคุณไม่ขยับไปด้านข้างอย่างกระทันหันและใช้ฟังก์ชันการทำงานหลัก ก็จะทำงานได้อย่างเสถียร

ข้อดี

  1. ไม่ช้าลง
  2. เกณฑ์การเข้าต่ำ
  3. โอเพ่นซอร์ส.
  4. ฟรี.
  5. ปรับขนาดได้ดี (การแบ่งส่วน/การจำลองแบบนอกกรอบ)
  6. รวมอยู่ในการลงทะเบียนซอฟต์แวร์รัสเซียที่แนะนำโดยกระทรวงคมนาคม
  7. การปรากฏตัวของการสนับสนุนอย่างเป็นทางการจากยานเดกซ์

ที่มา: will.com

เพิ่มความคิดเห็น