Ихэвчлэн арилжааны бүтээгдэхүүнүүд эсвэл Prometheus + Grafana зэрэг бэлэн нээлттэй эхийн хувилбаруудыг Nginx-ийн ажиллагааг хянах, шинжлэхэд ашигладаг. Энэ нь мониторинг эсвэл бодит цагийн аналитик хийхэд тохиромжтой сонголт боловч түүхэн шинжилгээ хийхэд тийм ч тохиромжтой биш юм. Аливаа алдартай нөөц дээр nginx бүртгэлийн өгөгдлийн хэмжээ хурдацтай нэмэгдэж байгаа бөгөөд их хэмжээний өгөгдөлд дүн шинжилгээ хийхийн тулд илүү нарийн мэргэшсэн зүйлийг ашиглах нь логик юм.
Энэ нийтлэлд би танд хэрхэн ашиглах талаар хэлэх болно
TL: DR;
Мэдээлэл цуглуулахын тулд бид ашигладаг
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 Stream үүсгэх
Kinesis Firehose нь Nginx-ээс S3 руу хүлээн авсан өгөгдлийг сонгосон форматаар бичиж, YYYY/MM/DD/HH форматын лавлах болгон хуваах болно. Энэ нь өгөгдлийг уншихад хэрэг болно. Мэдээжийн хэрэг та fluentd-ээс S3 руу шууд бичиж болно, гэхдээ энэ тохиолдолд та JSON бичих хэрэгтэй болно, энэ нь файлын хэмжээ том учраас үр ашиггүй юм. Нэмж дурдахад, PrestoDB эсвэл Athena ашиглах үед JSON нь хамгийн удаан өгөгдлийн формат юм. Тиймээс Kinesis Firehose консолыг нээгээд "Хүргэлтийн урсгалыг үүсгэх" дээр товшоод "хүргэх" талбарт "шууд PUT" -ийг сонгоно уу:
Дараагийн табаас "Бичлэгийн формат хөрвүүлэлт" - "Идэвхжүүлсэн" гэж сонгоод бичлэгийн форматаар "Apache ORC"-г сонгоно уу. Зарим судалгаагаар
Хадгалалт болон өмнө нь үүсгэсэн хувингаар бид S3-г сонгоно. Би бага зэрэг ярих болно Aws Glue Crawler нь S3 хувин дахь угтвартай ажиллах боломжгүй тул үүнийг хоосон орхих нь чухал юм.
Үлдсэн сонголтуудыг таны ачааллаас хамааран өөрчилж болно; Би ихэвчлэн үндсэн сонголтуудыг ашигладаг. S3 шахалтыг ашиглах боломжгүй боловч ORC нь анхдагчаар үндсэн шахалтыг ашигладаг гэдгийг анхаарна уу.
Чадварлаг
Одоо бид бүртгэлийг хадгалах, хүлээн авах тохиргоог хийсэн тул илгээх тохиргоог хийх хэрэгтэй. Бид ашиглах болно
Эхлээд бидэнд 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 руу лог илгээх
<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>
Athena
Хэрэв та бүх зүйлийг зөв тохируулсан бол хэсэг хугацааны дараа (анхдагчаар Kinesis нь хүлээн авсан өгөгдлийг 10 минут тутамд нэг удаа бүртгэдэг) S3 дээр бүртгэлийн файлуудыг харах болно. Kinesis Firehose-ийн "хяналт" цэснээс та S3-д хэр их өгөгдөл бичигдсэн, мөн алдааг харж болно. Kinesis дүрд S3 хувин руу бичих эрхийг өгөхөө бүү мартаарай. Хэрэв Kinesis ямар нэг зүйлийг задлан шинжилж чадаагүй бол алдааг ижил хувин дээр нэмнэ.
Одоо та Афина дахь өгөгдлийг үзэх боломжтой. Бид алдаа гаргасан хамгийн сүүлийн хүсэлтүүдийг олцгооё:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
Хүсэлт бүрийн бүх бүртгэлийг сканнердаж байна
Одоо бидний бүртгэлийг ORC-д S3-д боловсруулж, хадгалж, шахаж, дүн шинжилгээ хийхэд бэлэн болсон. Kinesis Firehose тэдгээрийг цаг тутамд лавлах болгон зохион байгуулдаг. Гэсэн хэдий ч хүснэгтийг хуваахгүй бол Athena нь ховор тохиолдлуудыг эс тооцвол хүсэлт болгонд бүх цаг үеийн өгөгдлийг ачаалах болно. Энэ нь хоёр шалтгааны улмаас том асуудал юм:
- Өгөгдлийн хэмжээ байнга нэмэгдэж, асуулга удаашруулж байна;
- Athena-ийн төлбөрийг сканнердсан өгөгдлийн хэмжээн дээр үндэслэн тооцдог бөгөөд хүсэлт бүрт хамгийн багадаа 10 MB байх ёстой.
Үүнийг засахын тулд бид AWS Glue Crawler ашигладаг бөгөөд энэ нь S3 дээрх өгөгдлийг мөлхөж, хуваалтын мэдээллийг Glue Metastore руу бичих болно. Энэ нь бидэнд Athena-д асуулга хийх үед хуваалтуудыг шүүлтүүр болгон ашиглах боломжийг олгох бөгөөд энэ нь зөвхөн асуулгад заасан сангуудыг сканнердах болно.
Amazon Glue Crawler-г тохируулж байна
Amazon Glue Crawler нь S3 хувин дахь бүх өгөгдлийг сканнердаж, хуваалт бүхий хүснэгтүүдийг үүсгэдэг. AWS Glue консолоос Glue Crawler үүсгэж, өгөгдөл хадгалах хувин нэмнэ үү. Та нэг мөлхөгчийг хэд хэдэн хувин дээр ашиглаж болох бөгөөд энэ тохиолдолд энэ нь хувингийн нэрэнд тохирсон нэрээр заасан мэдээллийн санд хүснэгтүүдийг үүсгэх болно. Хэрэв та энэ өгөгдлийг тогтмол ашиглахаар төлөвлөж байгаа бол 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 цагаас өглөөний XNUMX цагийн хооронд хүлээн авсан бүх бүртгэлийг сонгоно. Гэхдээ энэ нь хуваагдаагүй хүснэгтээс уншихаас хамаагүй илүү үр дүнтэй вэ? Ижил бичлэгүүдийг цаг хугацааны тэмдгээр шүүж олж сонгоцгооё:
3.59 секунд, 244.34 мегабайт өгөгдөлтэй, ердөө долоо хоногийн бүртгэлтэй. Хуваалтаар шүүж үзье:
Бага зэрэг хурдан, гэхдээ хамгийн чухал нь - ердөө 1.23 мегабайт өгөгдөл! Үнийн хувьд хүсэлт бүрт хамгийн багадаа 10 мегабайт байхгүй бол хамаагүй хямд байх болно. Гэхдээ энэ нь хамаагүй дээр хэвээр байгаа бөгөөд том өгөгдлийн багц дээр ялгаа нь илүү гайхалтай байх болно.
Cube.js ашиглан хяналтын самбар бүтээх
Хяналтын самбарыг угсрахдаа бид Cube.js аналитик хүрээг ашигладаг. Энэ нь маш олон функцтэй боловч бид хоёрыг сонирхож байна: хуваалтын шүүлтүүрийг автоматаар ашиглах чадвар, өгөгдлийг урьдчилан нэгтгэх чадвар. Энэ нь өгөгдлийн схемийг ашигладаг
Шинэ Cube.js програм үүсгэцгээе. Бид AWS стекийг аль хэдийн ашиглаж байгаа тул Lambda-г байршуулахдаа ашиглах нь логик юм. Хэрэв та Cube.js backend-ийг 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`
}
}
});
Энд бид хувьсагчийг ашиглаж байна
Бид мөн хяналтын самбар дээр харуулахыг хүсч буй хэмжүүр, параметрүүдийг тохируулж, урьдчилсан нэгтгэлүүдийг зааж өгдөг. 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 backend өгдөг
Cube.js сервер нь хүсэлтийг хүлээн авдаг
{
"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