Nginx Π»ΠΎΠ³ Π°Π½Π°Π»ΠΈΠ·ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Amazon Athena ΠΈ Cube.js

ОбикновСно Ρ‚ΡŠΡ€Π³ΠΎΠ²ΡΠΊΠΈ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΈ ΠΈΠ»ΠΈ Π³ΠΎΡ‚ΠΎΠ²ΠΈ Π°Π»Ρ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²ΠΈ с ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ ΠΊΠΎΠ΄, ΠΊΠ°Ρ‚ΠΎ Prometheus + Grafana, сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π·Π° наблюдСниС ΠΈ Π°Π½Π°Π»ΠΈΠ· Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° Nginx. Π’ΠΎΠ²Π° Π΅ Π΄ΠΎΠ±Ρ€Π° опция Π·Π° наблюдСниС ΠΈΠ»ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈ Π² Ρ€Π΅Π°Π»Π½ΠΎ Π²Ρ€Π΅ΠΌΠ΅, Π½ΠΎ Π½Π΅ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΡƒΠ΄ΠΎΠ±Π½Π° Π·Π° историчСски Π°Π½Π°Π»ΠΈΠ·ΠΈ. Π’ΡŠΠ² всСки популярСн рСсурс ΠΎΠ±Π΅ΠΌΡŠΡ‚ Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅ ΠΎΡ‚ рСгистрационнитС Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° nginx нараства Π±ΡŠΡ€Π·ΠΎ ΠΈ Π·Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° голямо количСство Π΄Π°Π½Π½ΠΈ Π΅ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π½Π΅Ρ‰ΠΎ ΠΏΠΎ-спСциализирано.

Π’ Ρ‚Π°Π·ΠΈ статия Ρ‰Π΅ Π²ΠΈ ΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Атина Π·Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅, ΠΊΠ°Ρ‚ΠΎ Π²Π·Π΅ΠΌΠ΅ΠΌ Π·Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Nginx, ΠΈ Ρ‰Π΅ ΠΏΠΎΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊ Π΄Π° сглобя Π°Π½Π°Π»ΠΈΡ‚ΠΈΡ‡Π½ΠΎ Ρ‚Π°Π±Π»ΠΎ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Ρ€Π°ΠΌΠΊΠ°Ρ‚Π° cube.js с ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ ΠΊΠΎΠ΄. Π•Ρ‚ΠΎ ΠΏΡŠΠ»Π½Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π½Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ:

Nginx Π»ΠΎΠ³ Π°Π½Π°Π»ΠΈΠ·ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Amazon Athena ΠΈ Cube.js

TL:DR;
Π›ΠΈΠ½ΠΊ към Π³ΠΎΡ‚ΠΎΠ²ΠΎΡ‚ΠΎ Ρ‚Π°Π±Π»ΠΎ.

Π—Π° ΡΡŠΠ±ΠΈΡ€Π°Π½Π΅ Π½Π° информация, която ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ fluentd, Π·Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° - AWS Kinesis Data ΠŸΠΎΠΆΠ°Ρ€Π΅Π½ ΠΌΠ°Ρ€ΠΊΡƒΡ‡ ΠΈ AWS Π»Π΅ΠΏΠΈΠ»ΠΎ, Π·Π° ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ - AWS S3. Използвайки Ρ‚ΠΎΠ·ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Ρ‚Π΅ Π½Π΅ само рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° nginx, Π½ΠΎ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ ΡΡŠΠ±ΠΈΡ‚ΠΈΡ, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° Π΄Ρ€ΡƒΠ³ΠΈ услуги. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ някои части с ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ Π·Π° вашия стСк, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π² kinesis Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ ΠΎΡ‚ nginx, заобикаляйки fluentd, ΠΈΠ»ΠΈ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ logstash Π·Π° Ρ‚ΠΎΠ²Π°.

Π‘ΡŠΠ±ΠΈΡ€Π°Π½Π΅ Π½Π° рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° Nginx

По ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ рСгистрационнитС Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° Nginx ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°Ρ‚ ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½:

4/9/2019 12:58:17 PM1.1.1.1 - - [09/Apr/2019:09:58:17 +0000] "GET /sign-up HTTP/2.0" 200 9168 "https://example.com/sign-in" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-"
4/9/2019 12:58:17 PM1.1.1.1 - - [09/Apr/2019:09:58:17 +0000] "GET /sign-in HTTP/2.0" 200 9168 "https://example.com/sign-up" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-"

Π’Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ΠΈ, Π½ΠΎ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-лСсно Π΄Π° ΠΊΠΎΡ€ΠΈΠ³ΠΈΡ€Π°Ρ‚Π΅ конфигурацията Π½Π° Nginx, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Π΄Π° създава рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π² JSON:

log_format json_combined escape=json '{ "created_at": "$msec", '
            '"remote_addr": "$remote_addr", '
            '"remote_user": "$remote_user", '
            '"request": "$request", '
            '"status": $status, '
            '"bytes_sent": $bytes_sent, '
            '"request_length": $request_length, '
            '"request_time": $request_time, '
            '"http_referrer": "$http_referer", '
            '"http_x_forwarded_for": "$http_x_forwarded_for", '
            '"http_user_agent": "$http_user_agent" }';

access_log  /var/log/nginx/access.log  json_combined;

S3 Π·Π° ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅

Π—Π° Π΄Π° ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°ΠΌΠ΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅, Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ S3. Π’ΠΎΠ²Π° Π²ΠΈ позволява Π΄Π° ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Ρ‚Π΅ ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚Π΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° Π΅Π΄Π½ΠΎ място, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Athena ΠΌΠΎΠΆΠ΅ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ с Π΄Π°Π½Π½ΠΈ Π² S3. По-късно Π² статията Ρ‰Π΅ Π²ΠΈ ΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ Π΄Π° добавятС ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π²Π°Ρ‚Π΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅, Π½ΠΎ ΠΏΡŠΡ€Π²ΠΎ ΠΈΠΌΠ°ΠΌΠ΅ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ чиста ΠΊΠΎΡ„Π° Π² S3, Π² която няма Π΄Π° сС ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π° Π½ΠΈΡ‰ΠΎ Π΄Ρ€ΡƒΠ³ΠΎ. Π‘Ρ‚Ρ€ΡƒΠ²Π° си Π΄Π° обмислитС ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ Π² ΠΊΠΎΠΉ Ρ€Π΅Π³ΠΈΠΎΠ½ Ρ‰Π΅ ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ своята ΠΊΠΎΡ„Π°, Π·Π°Ρ‰ΠΎΡ‚ΠΎ Athena Π½Π΅ сС ΠΏΡ€Π΅Π΄Π»Π°Π³Π° във всички Ρ€Π΅Π³ΠΈΠΎΠ½ΠΈ.

БъздаванС Π½Π° схСма Π² ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° Athena

НСка създадСм Ρ‚Π°Π±Π»ΠΈΡ†Π° Π² Athena Π·Π° Ρ‚Ρ€ΡƒΠΏΠΈ. НСобходим Π΅ ΠΊΠ°ΠΊΡ‚ΠΎ Π·Π° писанС, Ρ‚Π°ΠΊΠ° ΠΈ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅, Π°ΠΊΠΎ ΠΏΠ»Π°Π½ΠΈΡ€Π°Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Kinesis Firehose. ΠžΡ‚Π²ΠΎΡ€Π΅Ρ‚Π΅ ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° Π½Π° Athena ΠΈ ΡΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ‚Π°Π±Π»ΠΈΡ†Π°:

БъздаванС Π½Π° SQL Ρ‚Π°Π±Π»ΠΈΡ†Π°

CREATE EXTERNAL TABLE `kinesis_logs_nginx`(
  `created_at` double, 
  `remote_addr` string, 
  `remote_user` string, 
  `request` string, 
  `status` int, 
  `bytes_sent` int, 
  `request_length` int, 
  `request_time` double, 
  `http_referrer` string, 
  `http_x_forwarded_for` string, 
  `http_user_agent` string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.orc.OrcSerde' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat'
LOCATION
  's3://<YOUR-S3-BUCKET>'
TBLPROPERTIES ('has_encrypted_data'='false');

БъздаванС Π½Π° Kinesis Firehose ΠΏΠΎΡ‚ΠΎΠΊ

Kinesis Firehose Ρ‰Π΅ запишС Π΄Π°Π½Π½ΠΈΡ‚Π΅, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈ ΠΎΡ‚ Nginx Π² S3 Π² избрания Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, ΠΊΠ°Ρ‚ΠΎ Π³ΠΈ Ρ€Π°Π·Π΄Π΅Π»ΠΈ Π½Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ във Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π“Π“Π“Π“/ММ/Π”Π”/Π§Π§. Π’ΠΎΠ²Π° Ρ‰Π΅ бъдС ΠΏΠΎΠ»Π΅Π·Π½ΠΎ ΠΏΡ€ΠΈ Ρ‡Π΅Ρ‚Π΅Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ. ΠœΠΎΠΆΠ΅Ρ‚Π΅, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ Π² S3 ΠΎΡ‚ fluentd, Π½ΠΎ Π² Ρ‚ΠΎΠ·ΠΈ случай Ρ‰Π΅ трябва Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ JSON, Π° Ρ‚ΠΎΠ²Π° Π΅ Π½Π΅Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ ΠΏΠΎΡ€Π°Π΄ΠΈ голСмия Ρ€Π°Π·ΠΌΠ΅Ρ€ Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅Ρ‚Π΅. ОсвСн Ρ‚ΠΎΠ²Π°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ PrestoDB ΠΈΠ»ΠΈ Athena, JSON Π΅ Π½Π°ΠΉ-бавният Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° Π΄Π°Π½Π½ΠΈ. Π’Π°ΠΊΠ° Ρ‡Π΅ ΠΎΡ‚Π²ΠΎΡ€Π΅Ρ‚Π΅ ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° Kinesis Firehose, Ρ‰Ρ€Π°ΠΊΠ½Π΅Ρ‚Π΅ Π²ΡŠΡ€Ρ…Ρƒ β€žΠ‘ΡŠΠ·Π΄Π°Π²Π°Π½Π΅ Π½Π° ΠΏΠΎΡ‚ΠΎΠΊ Π·Π° Π΄ΠΎΡΡ‚Π°Π²ΠΊΠ°β€œ, ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žΠ΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ ΠŸΠžΠ‘Π’ΠΠ’Π―ΠΠ•β€œ Π² ΠΏΠΎΠ»Π΅Ρ‚ΠΎ β€žΠ΄ΠΎΡΡ‚Π°Π²ΠΊΠ°β€œ:

Nginx Π»ΠΎΠ³ Π°Π½Π°Π»ΠΈΠ·ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Amazon Athena ΠΈ Cube.js

Π’ слСдващия Ρ€Π°Π·Π΄Π΅Π» ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°Π½Π΅ Π½Π° Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π½Π° Π·Π°ΠΏΠΈΡβ€œ - β€žΠΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°Π½ΠΎβ€œ ΠΈ ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žApache ORCβ€œ ΠΊΠ°Ρ‚ΠΎ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π½Π° запис. Π‘ΠΏΠΎΡ€Π΅Π΄ някои изслСдвания ΠžΡƒΠ΅Π½ О'Мали, Ρ‚ΠΎΠ²Π° Π΅ оптималният Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° PrestoDB ΠΈ Athena. ИзползвамС Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°, която ΡΡŠΠ·Π΄Π°Π΄ΠΎΡ…ΠΌΠ΅ ΠΏΠΎ-Π³ΠΎΡ€Π΅, ΠΊΠ°Ρ‚ΠΎ схСма. Моля, ΠΎΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° посочитС ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π½ΠΎ мСстополоТСниС Π½Π° S3 Π² kinesis; ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° сС само схСмата ΠΎΡ‚ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°. Но Π°ΠΊΠΎ посочитС Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΎ S3 мСстополоТСниС, Ρ‚ΠΎΠ³Π°Π²Π° няма Π΄Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅Ρ‚Π΅ Ρ‚Π΅Π·ΠΈ записи ΠΎΡ‚ Ρ‚Π°Π·ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Π°.

Nginx Π»ΠΎΠ³ Π°Π½Π°Π»ΠΈΠ·ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Amazon Athena ΠΈ Cube.js

Π˜Π·Π±ΠΈΡ€Π°ΠΌΠ΅ S3 Π·Π° ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΈ ΠΊΠΎΡ„Π°Ρ‚Π°, която ΡΡŠΠ·Π΄Π°Π΄ΠΎΡ…ΠΌΠ΅ ΠΏΠΎ-Ρ€Π°Π½ΠΎ. Aws Glue Crawler, Π·Π° ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ говоря ΠΌΠ°Π»ΠΊΠΎ ΠΏΠΎ-късно, Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ с прСфикси Π² ΠΊΠΎΡ„Π° S3, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π° я оставитС ΠΏΡ€Π°Π·Π½Π°.

Nginx Π»ΠΎΠ³ Π°Π½Π°Π»ΠΈΠ·ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Amazon Athena ΠΈ Cube.js

ΠžΡΡ‚Π°Π½Π°Π»ΠΈΡ‚Π΅ ΠΎΠΏΡ†ΠΈΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС промСнят Π² зависимост ΠΎΡ‚ Π²Π°ΡˆΠ΅Ρ‚ΠΎ Π½Π°Ρ‚ΠΎΠ²Π°Ρ€Π²Π°Π½Π΅; ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌ Ρ‚Π΅Π·ΠΈ ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅. Π˜ΠΌΠ°ΠΉΡ‚Π΅ ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄, Ρ‡Π΅ S3 компрСсията Π½Π΅ Π΅ Π½Π°Π»ΠΈΡ‡Π½Π°, Π½ΠΎ ORC ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° собствСна компрСсия ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅.

fluentd

Π‘Π΅Π³Π°, слСд ΠΊΠ°Ρ‚ΠΎ смС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π»ΠΈ ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Π½Π΅Ρ‚ΠΎ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅, трябва Π΄Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°ΠΌΠ΅ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅Ρ‚ΠΎ. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ fluentd, Π·Π°Ρ‰ΠΎΡ‚ΠΎ ΠΎΠ±ΠΈΡ‡Π°ΠΌ Ruby, Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Logstash ΠΈΠ»ΠΈ Π΄Π° ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΡ‚Π΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ Π½Π° kinesis. Π‘ΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ Fluentd ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС стартиран ΠΏΠΎ няколко Π½Π°Ρ‡ΠΈΠ½Π°, Ρ‰Π΅ Π²ΠΈ Ρ€Π°Π·ΠΊΠ°ΠΆΠ° Π·Π° docker, Π·Π°Ρ‰ΠΎΡ‚ΠΎ Π΅ прост ΠΈ ΡƒΠ΄ΠΎΠ±Π΅Π½.

ΠŸΡŠΡ€Π²ΠΎ, ΠΈΠΌΠ°ΠΌΠ΅ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ конфигурационния Ρ„Π°ΠΉΠ» fluent.conf. Π‘ΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ Π³ΠΎ ΠΈ Π΄ΠΎΠ±Π°Π²Π΅Ρ‚Π΅ ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ:

Ρ‚ΠΈΠΏ Π½Π°ΠΏΡ€Π΅Π΄
ΠΏΠΎΡ€Ρ‚ 24224
ΠΎΠ±Π²ΡŠΡ€Π·Π²Π°Π½Π΅ 0.0.0.0

Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° стартиратС ΡΡŠΡ€Π²ΡŠΡ€Π° Fluentd. Ако ΠΈΠΌΠ°Ρ‚Π΅ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ ΠΏΠΎ-Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½Π° конфигурация, ΠΎΡ‚ΠΈΠ΄Π΅Ρ‚Π΅ Π½Π° Π”ΠΎΠΊΠ΅Ρ€ Ρ†Π΅Π½Ρ‚ΡŠΡ€ Има ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Ρ€ΡŠΠΊΠΎΠ²ΠΎΠ΄ΡΡ‚Π²ΠΎ, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΊΠ°ΠΊ Π΄Π° сглобитС Π²Π°ΡˆΠ΅Ρ‚ΠΎ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅.

$ docker run 
  -d 
  -p 24224:24224 
  -p 24224:24224/udp 
  -v /data:/fluentd/log 
  -v <PATH-TO-FLUENT-CONF>:/fluentd/etc fluentd 
  -c /fluentd/etc/fluent.conf
  fluent/fluentd:stable

Π’Π°Π·ΠΈ конфигурация ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΏΡŠΡ‚Ρ /fluentd/log Π΄Π° ΠΊΠ΅ΡˆΠΈΡ€Π°Ρ‚Π΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ ΠΏΡ€Π΅Π΄ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ ΠΈ Π±Π΅Π· Ρ‚ΠΎΠ²Π°, Π½ΠΎ слСд Ρ‚ΠΎΠ²Π°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ рСстартиратС, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π·Π°Π³ΡƒΠ±ΠΈΡ‚Π΅ всичко, ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ ΠΊΠ΅ΡˆΠΈΡ€Π°Π½ΠΎ с ΠΌΡŠΡ‡ΠΈΡ‚Π΅Π»Π΅Π½ Ρ‚Ρ€ΡƒΠ΄. ΠœΠΎΠΆΠ΅Ρ‚Π΅ ΡΡŠΡ‰ΠΎ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π΅Π½ ΠΏΠΎΡ€Ρ‚; 24224 Π΅ стандартният ΠΏΠΎΡ€Ρ‚ Π½Π° Fluentd.

Π‘Π΅Π³Π°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Fluentd Ρ€Π°Π±ΠΎΡ‚ΠΈ, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΠΌ Nginx Π»ΠΎΠ³ΠΎΠ²Π΅ Ρ‚Π°ΠΌ. ОбикновСно изпълнявамС Nginx Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ Π½Π° Docker, ΠΊΠ°Ρ‚ΠΎ Π² Ρ‚ΠΎΠ·ΠΈ случай Docker ΠΈΠΌΠ° собствСн Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€ Π·Π° рСгистриранС Π·Π° Fluentd:

$ docker run 
--log-driver=fluentd 
--log-opt fluentd-address=<FLUENTD-SERVER-ADDRESS>
--log-opt tag="{{.Name}}" 
-v /some/content:/usr/share/nginx/html:ro 
-d 
nginx

Ако стартиратС Nginx ΠΏΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π΅Π½ Π½Π°Ρ‡ΠΈΠ½, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π»ΠΎΠ³ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅, Fluentd ΠΈΠΌΠ° плъгин Π·Π° опашка Π½Π° Ρ„Π°ΠΉΠ»Π°.

НСка Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΆΡƒΡ€Π½Π°Π»Π°, ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π½ΠΎ ΠΏΠΎ-Π³ΠΎΡ€Π΅, към конфигурацията Π½Π° Fluent:

<filter YOUR-NGINX-TAG.*>
  @type parser
  key_name log
  emit_invalid_record_to_error false
  <parse>
    @type json
  </parse>
</filter>

И ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅ Π½Π° рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ към Kinesis с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Kinesis firehose плъгин:

<match YOUR-NGINX-TAG.*>
    @type kinesis_firehose
    region region
    delivery_stream_name <YOUR-KINESIS-STREAM-NAME>
    aws_key_id <YOUR-AWS-KEY-ID>
    aws_sec_key <YOUR_AWS-SEC_KEY>
</match>

Атина

Ако стС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π»ΠΈ всичко ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ, слСд извСстно Π²Ρ€Π΅ΠΌΠ΅ (ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ Kinesis записва ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈ вСднъТ Π½Π° всСки 10 ΠΌΠΈΠ½ΡƒΡ‚ΠΈ) трябва Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π² S3. Π’ ΠΌΠ΅Π½ΡŽΡ‚ΠΎ β€žΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³β€œ Π½Π° Kinesis Firehose ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ ΠΊΠΎΠ»ΠΊΠΎ Π΄Π°Π½Π½ΠΈ са записани Π² S3, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ Π³Ρ€Π΅ΡˆΠΊΠΈ. НС забравяйтС Π΄Π° Π΄Π°Π΄Π΅Ρ‚Π΅ Π΄ΠΎΡΡ‚ΡŠΠΏ Π·Π° писанС Π΄ΠΎ ΠΊΠΎΡ„Π°Ρ‚Π° S3 Π½Π° ролята Kinesis. Ако Kinesis Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π° Π½Π΅Ρ‰ΠΎ, Ρ‚ΠΎΠΉ Ρ‰Π΅ Π΄ΠΎΠ±Π°Π²ΠΈ Π³Ρ€Π΅ΡˆΠΊΠΈΡ‚Π΅ към ΡΡŠΡ‰Π°Ρ‚Π° ΠΊΠΎΡ„Π°.

Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π² Athena. НСка Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ Π½Π°ΠΉ-Π½ΠΎΠ²ΠΈΡ‚Π΅ заявки, Π·Π° ΠΊΠΎΠΈΡ‚ΠΎ Π²ΡŠΡ€Π½Π°Ρ…ΠΌΠ΅ Π³Ρ€Π΅ΡˆΠΊΠΈ:

SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;

Π‘ΠΊΠ°Π½ΠΈΡ€Π°Π½Π΅ Π½Π° всички записи Π·Π° всяка заявка

Π‘Π΅Π³Π° Π½Π°ΡˆΠΈΡ‚Π΅ рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ са ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π΅Π½ΠΈ ΠΈ ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈ Π² S3 Π² ORC, компрСсирани ΠΈ Π³ΠΎΡ‚ΠΎΠ²ΠΈ Π·Π° Π°Π½Π°Π»ΠΈΠ·. Kinesis Firehose Π΄ΠΎΡ€ΠΈ Π³ΠΈ ΠΎΡ€Π³Π°Π½ΠΈΠ·ΠΈΡ€Π° Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ Π·Π° всСки час. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, Π΄ΠΎΠΊΠ°Ρ‚ΠΎ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Π½Π΅ Π΅ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π°, Athena Ρ‰Π΅ Π·Π°Ρ€Π΅ΠΆΠ΄Π° Π΄Π°Π½Π½ΠΈ Π·Π° всички Π²Ρ€Π΅ΠΌΠ΅Π½Π° ΠΏΡ€ΠΈ всяка заявка, с Ρ€Π΅Π΄ΠΊΠΈ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ. Π’ΠΎΠ²Π° Π΅ голям ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΏΠΎΡ€Π°Π΄ΠΈ Π΄Π²Π΅ ΠΏΡ€ΠΈΡ‡ΠΈΠ½ΠΈ:

  • ΠžΠ±Π΅ΠΌΡŠΡ‚ Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π½Π΅ΠΏΡ€Π΅ΠΊΡŠΡΠ½Π°Ρ‚ΠΎ растС, забавяйки заявкитС;
  • Athena сС таксува въз основа Π½Π° ΠΎΠ±Π΅ΠΌΠ° Π½Π° сканиранитС Π΄Π°Π½Π½ΠΈ, с ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ 10 MB Π½Π° заявка.

Π—Π° Π΄Π° ΠΊΠΎΡ€ΠΈΠ³ΠΈΡ€Π°ΠΌΠ΅ Ρ‚ΠΎΠ²Π°, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ AWS Glue Crawler, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ ΠΎΠ±Ρ…ΠΎΠ΄ΠΈ Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π² S3 ΠΈ Ρ‰Π΅ запишС информацията Π·Π° дяла Π² Glue Metastore. Π’ΠΎΠ²Π° Ρ‰Π΅ Π½ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ дяловС ΠΊΠ°Ρ‚ΠΎ Ρ„ΠΈΠ»Ρ‚ΡŠΡ€ ΠΏΡ€ΠΈ Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ към Athena ΠΈ Ρ‰Π΅ сканира само Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈΡ‚Π΅, посочСни Π² заявката.

НастройванС Π½Π° Amazon Glue Crawler

Amazon Glue Crawler сканира всички Π΄Π°Π½Π½ΠΈ Π² ΠΊΠΎΡ„Π°Ρ‚Π° S3 ΠΈ създава Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ с дяловС. Π‘ΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ Glue Crawler ΠΎΡ‚ AWS Glue ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° ΠΈ Π΄ΠΎΠ±Π°Π²Π΅Ρ‚Π΅ ΠΊΠΎΡ„Π°, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Ρ‚Π΅ Π΄Π°Π½Π½ΠΈΡ‚Π΅. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π΅Π΄ΠΈΠ½ Ρ€ΠΎΠ±ΠΎΡ‚ Π·Π° няколко ΠΊΠΎΡ„ΠΈ, Π² ΠΊΠΎΠΉΡ‚ΠΎ случай Ρ‚ΠΎΠΉ Ρ‰Π΅ създадС Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ Π² посочСната Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ с ΠΈΠΌΠ΅Π½Π°, ΠΊΠΎΠΈΡ‚ΠΎ ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π°Ρ‚ Π½Π° ΠΈΠΌΠ΅Π½Π°Ρ‚Π° Π½Π° ΠΊΠΎΡ„ΠΈΡ‚Π΅. Ако ΠΏΠ»Π°Π½ΠΈΡ€Π°Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ Ρ€Π΅Π΄ΠΎΠ²Π½ΠΎ, Π½Π΅ забравяйтС Π΄Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Ρ‚Π΅ Π³Ρ€Π°Ρ„ΠΈΠΊΠ° Π·Π° стартиранС Π½Π° Crawler, Π·Π° Π΄Π° отговаря Π½Π° Π²Π°ΡˆΠΈΡ‚Π΅ Π½ΡƒΠΆΠ΄ΠΈ. ИзползвамС Π΅Π΄ΠΈΠ½ Crawler Π·Π° всички маси, ΠΊΠΎΠΉΡ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈ Π½Π° всСки час.

ΠŸΡ€Π΅Π³Ρ€Π°Π΄Π΅Π½ΠΈ маси

Π‘Π»Π΅Π΄ ΠΏΡŠΡ€Π²ΠΎΡ‚ΠΎ стартиранС Π½Π° Ρ€ΠΎΠ±ΠΎΡ‚Π°, Ρ‚Π°Π±Π»ΠΈΡ†ΠΈΡ‚Π΅ Π·Π° всяка сканирана ΠΊΠΎΡ„Π° трябва Π΄Π° сС появят Π² Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ, посочСна Π² настройкитС. ΠžΡ‚Π²ΠΎΡ€Π΅Ρ‚Π΅ ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° Π½Π° Athena ΠΈ Π½Π°ΠΌΠ΅Ρ€Π΅Ρ‚Π΅ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° с рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° Nginx. НСка сС ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅ΠΌ Π½Π΅Ρ‰ΠΎ:

SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
  partition_0 = '2019' AND
  partition_1 = '04' AND
  partition_2 = '08' AND
  partition_3 = '06'
  );

Π’Π°Π·ΠΈ заявка Ρ‰Π΅ ΠΈΠ·Π±Π΅Ρ€Π΅ всички записи, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ 6 сутринта ΠΈ 7 сутринта Π½Π° 8 Π°ΠΏΡ€ΠΈΠ» 2019 Π³. Но ΠΊΠΎΠ»ΠΊΠΎ ΠΏΠΎ-Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ Π΅ Ρ‚ΠΎΠ²Π° ΠΎΡ‚ просто Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΎΡ‚ Π½Π΅Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°? НСка Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ ΠΈ ΠΈΠ·Π±Π΅Ρ€Π΅ΠΌ ΡΡŠΡ‰ΠΈΡ‚Π΅ записи, ΠΊΠ°Ρ‚ΠΎ Π³ΠΈ Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅Π²ΠΎ ΠΊΠ»Π΅ΠΉΠΌΠΎ:

Nginx Π»ΠΎΠ³ Π°Π½Π°Π»ΠΈΠ·ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Amazon Athena ΠΈ Cube.js

3.59 сСкунди ΠΈ 244.34 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡ‚Π° Π΄Π°Π½Π½ΠΈ Π² Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ със само Π΅Π΄Π½Π° сСдмица рСгистрационни Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅. НСка ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Ρ„ΠΈΠ»Ρ‚ΡŠΡ€ ΠΏΠΎ дял:

Nginx Π»ΠΎΠ³ Π°Π½Π°Π»ΠΈΠ·ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Amazon Athena ΠΈ Cube.js

Малко ΠΏΠΎ-Π±ΡŠΡ€Π·ΠΎ, Π½ΠΎ Π½Π°ΠΉ-Π²Π°ΠΆΠ½ΠΎΡ‚ΠΎ - само 1.23 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡ‚Π° Π΄Π°Π½Π½ΠΈ! Π‘ΠΈ Π±ΠΈΠ»ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π΅Π²Ρ‚ΠΈΠ½ΠΎ, Π°ΠΊΠΎ Π½Π΅ бяха ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½ΠΈΡ‚Π΅ 10 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡ‚Π° Π½Π° заявка Π² Ρ†Π΅Π½Π°Ρ‚Π°. Но всС ΠΎΡ‰Π΅ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ ΠΈ ΠΏΡ€ΠΈ Π³ΠΎΠ»Π΅ΠΌΠΈ масиви ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ Ρ€Π°Π·Π»ΠΈΠΊΠ°Ρ‚Π° Ρ‰Π΅ бъдС ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-впСчатляваща.

Π˜Π·Π³Ρ€Π°ΠΆΠ΄Π°Π½Π΅ Π½Π° Ρ‚Π°Π±Π»ΠΎ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Cube.js

Π—Π° Π΄Π° сглобим Ρ‚Π°Π±Π»ΠΎΡ‚ΠΎ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π°Π½Π°Π»ΠΈΡ‚ΠΈΡ‡Π½Π°Ρ‚Π° Ρ€Π°ΠΌΠΊΠ° Cube.js. Π’ΠΎΠΉ ΠΈΠΌΠ° доста Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½ΠΎ Π½ΠΈΠ΅ сС интСрСсувамС ΠΎΡ‚ Π΄Π²Π΅: Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚Ρ‚Π° Π·Π° Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈ Π·Π° дяловС ΠΈ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ Π°Π³Ρ€Π΅Π³ΠΈΡ€Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ. Π’ΠΎΠΉ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° схСма Π·Π° Π΄Π°Π½Π½ΠΈ схСма Π½Π° Π΄Π°Π½Π½ΠΈ, написан Π½Π° Javascript Π·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° SQL ΠΈ изпълнСниС Π½Π° заявка към Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ. Врябва само Π΄Π° посочим ΠΊΠ°ΠΊ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Ρ„ΠΈΠ»Ρ‚ΡŠΡ€Π° Π·Π° дяловС Π² схСмата Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅.

НСка създадСм Π½ΠΎΠ²ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Cube.js. Въй ΠΊΠ°Ρ‚ΠΎ Π²Π΅Ρ‡Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ AWS стСка, Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Lambda Π·Π° внСдряванС. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ СкспрСсния шаблон Π·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅, Π°ΠΊΠΎ ΠΏΠ»Π°Π½ΠΈΡ€Π°Ρ‚Π΅ Π΄Π° хостватС Π±Π΅ΠΊΠ΅Π½Π΄Π° Π½Π° Cube.js Π² Heroku ΠΈΠ»ΠΈ Docker. ДокумСнтацията описва Π΄Ρ€ хостинг ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ.

$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena

ΠŸΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈΡ‚Π΅ Π½Π° срСдата сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π·Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π½Π΅ Π½Π° Π΄ΠΎΡΡ‚ΡŠΠΏΠ° Π΄ΠΎ Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ Π² cube.js. Π“Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΡŠΡ‚ Ρ‰Π΅ създадС .env Ρ„Π°ΠΉΠ», Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° посочитС Π²Π°ΡˆΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ Π·Π° Атина.

Π‘Π΅Π³Π° ΠΈΠΌΠ°ΠΌΠ΅ Π½ΡƒΠΆΠ΄Π° схСма Π½Π° Π΄Π°Π½Π½ΠΈ, Π² ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ посочим ΠΊΠ°ΠΊ Ρ‚ΠΎΡ‡Π½ΠΎ сС ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Ρ‚ Π½Π°ΡˆΠΈΡ‚Π΅ Π»ΠΎΠ³ΠΎΠ²Π΅. Π’Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΡŠΡ‰ΠΎ Π΄Π° посочитС ΠΊΠ°ΠΊ Π΄Π° изчисляватС ΠΏΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈΡ‚Π΅ Π·Π° Ρ‚Π°Π±Π»Π°Ρ‚Π° Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅.

Π’ дирСктория schema, ΡΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ„Π°ΠΉΠ» Logs.js. Π•Ρ‚ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅Π½ ΠΌΠΎΠ΄Π΅Π» Π½Π° Π΄Π°Π½Π½ΠΈ Π·Π° nginx:

Код на модСла

const partitionFilter = (from, to) => `
    date(from_iso8601_timestamp(${from})) <= date_parse(partition_0 || partition_1 || partition_2, '%Y%m%d') AND
    date(from_iso8601_timestamp(${to})) >= date_parse(partition_0 || partition_1 || partition_2, '%Y%m%d')
    `

cube(`Logs`, {
  sql: `
  select * from part_demo_kinesis_bucket
  WHERE ${FILTER_PARAMS.Logs.createdAt.filter(partitionFilter)}
  `,

  measures: {
    count: {
      type: `count`,
    },

    errorCount: {
      type: `count`,
      filters: [
        { sql: `${CUBE.isError} = 'Yes'` }
      ]
    },

    errorRate: {
      type: `number`,
      sql: `100.0 * ${errorCount} / ${count}`,
      format: `percent`
    }
  },

  dimensions: {
    status: {
      sql: `status`,
      type: `number`
    },

    isError: {
      type: `string`,
      case: {
        when: [{
          sql: `${CUBE}.status >= 400`, label: `Yes`
        }],
        else: { label: `No` }
      }
    },

    createdAt: {
      sql: `from_unixtime(created_at)`,
      type: `time`
    }
  }
});

Π’ΡƒΠΊ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°Ρ‚Π° FILTER_PARAMSΠ·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° SQL заявка с Ρ„ΠΈΠ»Ρ‚ΡŠΡ€ Π·Π° дяловС.

НиС ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈΡ‚Π΅ ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΡ‚Π΅, ΠΊΠΎΠΈΡ‚ΠΎ искамС Π΄Π° ΠΏΠΎΠΊΠ°Π·Π²Π°ΠΌΠ΅ Π½Π° Ρ‚Π°Π±Π»ΠΎΡ‚ΠΎ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅, ΠΈ опрСдСлямС ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΈ Π°Π³Ρ€Π΅Π³Π°Ρ†ΠΈΠΈ. Cube.js Ρ‰Π΅ създадС Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ с ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½ΠΈ Π΄Π°Π½Π½ΠΈ ΠΈ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎ Ρ‰Π΅ Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅, ΠΊΠΎΠ³Π°Ρ‚ΠΎ пристигнат. Π’ΠΎΠ²Π° Π½Π΅ само ускорява заявкитС, Π½ΠΎ ΠΈ намалява Ρ€Π°Π·Ρ…ΠΎΠ΄ΠΈΡ‚Π΅ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Athena.

НСка Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Ρ‚Π°Π·ΠΈ информация към Ρ„Π°ΠΉΠ»Π° със схСмата Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅:

preAggregations: {
  main: {
    type: `rollup`,
    measureReferences: [count, errorCount],
    dimensionReferences: [isError, status],
    timeDimensionReference: createdAt,
    granularity: `day`,
    partitionGranularity: `month`,
    refreshKey: {
      sql: FILTER_PARAMS.Logs.createdAt.filter((from, to) => 
        `select
           CASE WHEN from_iso8601_timestamp(${to}) + interval '3' day > now()
           THEN date_trunc('hour', now()) END`
      )
    }
  }
}

НиС уточнявамС Π² Ρ‚ΠΎΠ·ΠΈ ΠΌΠΎΠ΄Π΅Π», Ρ‡Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ Π°Π³Ρ€Π΅Π³ΠΈΡ€Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ Π·Π° всички ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° раздСлянС ΠΏΠΎ мСсСци. РаздСлянС ΠΏΡ€Π΅Π΄ΠΈ Π°Π³Ρ€Π΅Π³ΠΈΡ€Π°Π½Π΅ ΠΌΠΎΠΆΠ΅ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΎ Π΄Π° ускори ΡΡŠΠ±ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ ΠΈ Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π΄Π°Π½Π½ΠΈ.

Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° сглобим Ρ‚Π°Π±Π»ΠΎΡ‚ΠΎ!

Π‘Π΅ΠΊΠ΅Π½Π΄ΡŠΡ‚ Π½Π° Cube.js прСдоставя REST API ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ клиСнтски Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Π·Π° популярни ΠΏΡ€Π΅Π΄Π½ΠΈ Ρ€Π°ΠΌΠΊΠΈ. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ React вСрсията Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, Π·Π° Π΄Π° ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΠΌ Ρ‚Π°Π±Π»ΠΎΡ‚ΠΎ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅. Cube.js прСдоставя само Π΄Π°Π½Π½ΠΈ, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Ρ‰Π΅ Π½ΠΈ трябва Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π° визуализация - харСсва ΠΌΠΈ прСзарСТдания, Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ всякакви.

Π‘ΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ Cube.js ΠΏΡ€ΠΈΠ΅ΠΌΠ° заявката Π² JSON Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, ΠΊΠΎΠΉΡ‚ΠΎ опрСдСля Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ. НапримСр, Π·Π° Π΄Π° изчислитС ΠΊΠΎΠ»ΠΊΠΎ Π³Ρ€Π΅ΡˆΠΊΠΈ Π΅ Π΄Π°Π» Nginx Π½Π° Π΄Π΅Π½, трябва Π΄Π° ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΡ‚Π΅ слСдната заявка:

{
  "measures": ["Logs.errorCount"],
  "timeDimensions": [
    {
      "dimension": "Logs.createdAt",
      "dateRange": ["2019-01-01", "2019-01-07"],
      "granularity": "day"
    }
  ]
}

НСка инсталирамС ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Cube.js ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈΡ‚Π΅ Π½Π° React Ρ‡Ρ€Π΅Π· NPM:

$ npm i --save @cubejs-client/core @cubejs-client/react

ВнасямС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈ cubejs ΠΈ QueryRendererΠ·Π° изтСглянС Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅ ΠΈ ΡΡŠΠ±ΠΈΡ€Π°Π½Π΅ Π½Π° Ρ‚Π°Π±Π»ΠΎΡ‚ΠΎ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅:

Код Π½Π° Ρ‚Π°Π±Π»ΠΎΡ‚ΠΎ

import React from 'react';
import { LineChart, Line, XAxis, YAxis } from 'recharts';
import cubejs from '@cubejs-client/core';
import { QueryRenderer } from '@cubejs-client/react';

const cubejsApi = cubejs(
  'YOUR-CUBEJS-API-TOKEN',
  { apiUrl: 'http://localhost:4000/cubejs-api/v1' },
);

export default () => {
  return (
    <QueryRenderer
      query={{
        measures: ['Logs.errorCount'],
        timeDimensions: [{
            dimension: 'Logs.createdAt',
            dateRange: ['2019-01-01', '2019-01-07'],
            granularity: 'day'
        }]
      }}
      cubejsApi={cubejsApi}
      render={({ resultSet }) => {
        if (!resultSet) {
          return 'Loading...';
        }

        return (
          <LineChart data={resultSet.rawData()}>
            <XAxis dataKey="Logs.createdAt"/>
            <YAxis/>
            <Line type="monotone" dataKey="Logs.errorCount" stroke="#8884d8"/>
          </LineChart>
        );
      }}
    />
  )
}

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈΡ‚Π΅ Π½Π° Ρ‚Π°Π±Π»ΠΎΡ‚ΠΎ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ са Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΈ Π½Π° ΠΊΠΎΠ΄ΠΎΠ²Π° ΠΏΡΡΡŠΡ‡Π½Π° кутия.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€