Node Framework를 ELK에 연결하는 과정 요약
이 글의 내용은 Node 프레임워크를 ELK에 연결하는 과정을 요약한 것입니다. 참고할 만한 가치가 있으니 도움이 필요한 분들에게 도움이 되길 바랍니다.
우리 모두는 클러스터 수가 증가하면 이러한 원시적인 작업으로 인한 비효율성으로 인해 기존 네트워크 문제를 찾는 데 큰 어려움을 겪을 뿐만 아니라 이를 수행하는 것도 불가능하게 됩니다. 목표한 최적화 및 개선은 물론, 서비스 프레임워크의 다양한 지표에 대한 효과적인 정량적 진단을 수행하는 것도 불가능합니다. 이때 정보검색, 서비스 진단, 데이터 분석 등의 기능을 갖춘 실시간 로그 모니터링 시스템을 구축하는 것이 특히 중요하다.
ELK(ELK 스택: ElasticSearch, LogStash, Kibana, Beats)는 오픈 소스와 높은 성능을 갖춘 성숙한 로깅 솔루션입니다. 우리 사업에서 사용하는 서비스 프레임워크는 ELK 시스템과 어떻게 연결되나요?
비즈니스 배경
비즈니스 프레임워크 배경:
비즈니스 프레임워크는 NodeJs WebServer를 기반으로 합니다.
서비스는 Winston 로그 모듈을 사용하여 로그를 현지화합니다.
서비스에서 생성된 로그가 저장됩니다.
서비스는 서로 다른 지역의 여러 머신에 배포됩니다
액세스 단계
전체 프레임워크를 ELK에 다음 단계로 간단히 요약하겠습니다.
로그 구조 설계 : 전통적인 일반 텍스트로 구성 로그는 구조화된 객체로 변경되어 JSON으로 출력됩니다.
로그 수집: 프레임워크 요청 수명 주기의 일부 주요 노드에서 로그를 출력합니다.
ES 인덱스 템플릿 정의: JSON에서 매핑 설정 to ES 실제 저장소
1. 로그 구조 설계
전통적으로 우리는 로그 출력을 할 때 로그 레벨(level)과 로그 내용 문자열(message)을 직접 출력했습니다. 그러나 우리는 언제, 무슨 일이 일어났는지에만 주의를 기울이는 것이 아니라, 유사한 로그가 몇 번이나 발생했는지, 로그의 내용과 맥락, 관련 로그에도 주의를 기울여야 할 수도 있습니다. 따라서 우리는 단순히 로그를 객체로 구성할 뿐만 아니라 로그의 주요 필드도 추출합니다.
1. 로그를 이벤트로 추상화
각 로그의 발생을 이벤트로 추상화합니다. 이벤트에는 다음이 포함됩니다.
이벤트 메타필드
이벤트 발생 시간: 날짜시간, 타임스탬프
이벤트 수준: 레벨, 예: ERROR, INFO, WARNING, DEBUG
이벤트 이름: 이벤트, 예: client-request
이벤트 발생 상대 시간(단위: 나노초): reqLife, 이 필드는 요청과 관련된 이벤트가 발생하기 시작하는 시간(간격)입니다.
이벤트 위치: 라인, 서버 코드 위치, 서버 위치
요청 메타 필드
요청 고유 ID: reqId, 이 필드는 전체 요청 링크에서 발생하는 모든 이벤트를 통해 실행됩니다.
요청 사용자 ID: reqUid, 이 필드는 사용자의 액세스 또는 링크 요청
데이터 필드
다양한 유형의 이벤트를 출력하려면 다양한 세부정보가 필요합니다. 이러한 세부정보(비메타 필드)를 d -- 데이터에 넣습니다. 이를 통해 이벤트 구조가 더 명확해지고 동시에 데이터 필드가 메타 필드를 오염시키는 것을 방지할 수 있습니다.
예: 서버가 사용자 요청을 받을 때마다 인쇄되는 client-init 이벤트와 같이 사용자의 IP, URL 및 기타 이벤트를 데이터 필드에 고유하게 분류합니다. object中
완전한 예 제공
{ "datetime":"2018-11-07 21:38:09.271", "timestamp":1541597889271, "level":"INFO", "event":"client-init", "reqId":"rJtT5we6Q", "reqLife":5874, "reqUid": "999793fc03eda86", "d":{ "url":"/", "ip":"9.9.9.9", "httpVersion":"1.1", "method":"GET", "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", "headers":"*" }, "browser":"{"name":"Chrome","version":"70.0.3538.77","major":"70"}", "engine":"{"version":"537.36","name":"WebKit"}", "os":"{"name":"Mac OS","version":"10.14.0"}", "content":"(Empty)", "line":"middlewares/foo.js:14", "server":"127.0.0.1" }
일부 필드(예: browser, os,engine)때때로 로그가 외부 레이어에서 가능한 한 평평해지기를 원하는 이유는 무엇입니까? (최대 깊이는 2), ES에서 불필요한 인덱스로 인한 성능 손실을 방지합니다. 실제 출력에서는 깊이가 1보다 큰 값을 문자열로 출력합니다. 때때로 일부 객체 필드가 우리에게 중요하므로 이러한 특수 필드를 외부 레이어에 배치하여 출력 깊이가 2보다 크지 않도록 합니다.
일반적으로 로그를 출력할 때 이벤트 이름
과 데이터 필드
에만 주의하면 됩니다. 또한, 로그를 출력하는 방식으로 context에 접근하여 일률적으로 획득, 계산, 출력할 수 있다. 事件名称
及数据字段
即可。其他,我们可以在打印日志的方法中,通过访问上下文统一获取,计算,输出。
2. 日志改造输出
前面我们提到了如何定义一个日志事件, 那么,我们如何基于已有日志方案做升级,同时,兼容旧代码的日志调用方式。
升级关键节点的日志
// 改造前 logger.info('client-init => ' + JSON.stringfiy({ url, ip, browser, //... })); // 改造后 logger.info({ event: 'client-init', url, ip, browser, //... });
兼容旧的日志调用方式
logger.debug('checkLogin');
因为 winston 的 日志方法本身就支持 string 或者 object 的传入方式, 所以对于旧的字符串传入写法,formatter 接收到的实际上是{ level: 'debug', message: 'checkLogin' }。formatter 是 winston 的日志输出前调整日志格式的一道工序, 这一点使我们在日志输出前有机会将这类调用方式输出的日志,转为一个纯输出事件 -- 我们称它们为raw-log事件,而不需要修改调用方式。
改造日志输出格式
前面提到 winston 输出日志前,会经过我们预定义的formatter,因此除了兼容逻辑的处理外,我们可以将一些公共逻辑统一放在这里处理。而调用上,我们只关注字段本身即可。
元字段提取及处理
字段长度控制
兼容逻辑处理
如何提取元字段,这里涉及上下文的创建与使用,这里简单介绍一下 domain 的创建与使用。
//--- middlewares/http-context.js const domain = require('domain'); const shortid = require('shortid'); module.exports = (req, res, next) => { const d = domain.create(); d.id = shortid.generate(); // reqId; d.req = req; //... res.on('finish', () => process.nextTick(() => { d.id = null; d.req = null; d.exit(); }); d.run(() => next()); } //--- app.js app.use(require('./middlewares/http-context.js')); //--- formatter.js if (process.domain) { reqId = process.domain.id; }
这样,我们就可以将 reqId
- 기존 로그 호출 방식과 호환
윈스턴의 로그 메소드 자체는 문자열 또는 객체 입력 방법이므로 이전 문자열 입력 쓰기 방법의 경우 포맷터가 실제로 받는 것은 { level: 'debug', message: 'checkLogin' }입니다. 포맷터는 로그 출력 전에 Winston의 로그 형식을 조정하는 프로세스입니다. 이는 로그 출력 전에 이러한 종류의 호출 방법을 통해 로그 출력을 순수 출력 이벤트로 변환할 수 있는 기회를 제공합니다. 이를 원시 로그 이벤트라고 부릅니다. 호출 방법.
PUT _template/my_logs_template { "index_patterns": "my_logs*", "mappings": { "_doc": { "properties": { "title": { "type": "date", "format": "epoch_millis" }, } } } }
로그인 후 복사로그인 후 복사 - 로그 출력 형식 변환앞서 언급했듯이 Winston은 로그를 출력하기 전에 미리 정의된 포맷터를 거치게 되므로 호환 가능한 논리 처리 외에도 일부 공통 논리를 결합할 수도 있습니다. 여기에 모두 모아두세요. 통화에 관해서는 현장 자체에만 집중합니다.
PUT my_logs { "mappings": { "_doc": { "properties": { "title": { "type": "date", "format": "epoch_millis" }, } } } }
메타필드 추출 및 처리
필드 길이 제어#🎜 🎜 #
호환 논리 처리
이런 방식으로 요청의 모든 이벤트에 reqId
를 출력하여 이벤트 상관 목적을 달성할 수 있습니다.
2. 로그 수집
이제 이벤트 출력 방법을 알았으니 다음 단계에서는 두 가지 문제를 고려해야 합니다.
下游依赖
http-start: 打印于请求下游起始:请求地址,请求包体,模块别名(方便基于名字聚合而且域名)
http-success: 打印于请求返回 200:请求地址,请求包体,响应包体(code & msg & data),耗时
http-error: 打印于请求返回非 200,亦即连接服务器失败:请求地址,请求包体,响应包体(code & message & stack),耗时。
http-timeout: 打印于请求连接超时:请求地址,请求包体,响应包体(code & msg & stack),耗时。
字段这么多,该怎么选择? 一言以蔽之,事件输出的字段原则就是:输出你关注的,方便检索的,方便后期聚合的字段。一些建议
请求下游的请求体和返回体有固定格式, e.g. 输入:{ action: 'getUserInfo', payload: {} } 输出: { code: 0, msg: '', data: {}} 我们可以在事件输出 action,code 等,以便后期通过 action 检索某模块具体某个接口的各项指标和聚合。
一些原则
保证输出字段类型一致 由于所有事件都存储在同一个 ES 索引, 因此,相同字段不管是相同事件还是不同事件,都应该保持一致,例如:code不应该既是数字,又是字符串,这样可能会产生字段冲突,导致某些记录(document)无法被冲突字段检索到。
ES 存储类型为 keyword, 不应该超过 ES mapping 设定的 ignore_above 中指定的字节数(默认4096个字节)。否则同样可能会产生无法被检索的情况
三、ES 索引模版定义
这里引入 ES 的两个概念,映射(Mapping)与模版(Template)。
首先,ES 基本的存储类型大概枚举下,有以下几种
String: keyword & text
Numeric: long, integer, double
Date: date
Boolean: boolean
一般的,我们不需要显示指定每个事件字段的在ES对应的存储类型,ES 会自动根据字段第一次出现的document中的值来决定这个字段在这个索引中的存储类型。但有时候,我们需要显示指定某些字段的存储类型,这个时候我们需要定义这个索引的 Mapping, 来告诉 ES 这此字段如何存储以及如何索引。
e.g.
还记得事件元字段中有一个字段为 timestamp ?实际上,我们输出的时候,timestamp 的值是一个数字,它表示跟距离 1970/01/01 00:00:00 的毫秒数,而我们期望它在ES的存储类型为 date 类型方便后期的检索和可视化, 那么我们创建索引的时候,指定我们的Mapping。
PUT my_logs { "mappings": { "_doc": { "properties": { "title": { "type": "date", "format": "epoch_millis" }, } } } }
但一般的,我们可能会按日期自动生成我们的日志索引,假定我们的索引名称格式为 my_logs_yyyyMMdd (e.g. my_logs_20181030)。那么我们需要定义一个模板(Template),这个模板会在(匹配的)索引创建时自动应用预设好的 Mapping。
PUT _template/my_logs_template { "index_patterns": "my_logs*", "mappings": { "_doc": { "properties": { "title": { "type": "date", "format": "epoch_millis" }, } } } }
小结
至此,日志改造及接入的准备工作都已经完成了,我们只须在机器上安装 FileBeat -- 一个轻量级的文件日志Agent, 它负责将日志文件中的日志传输到 ELK。接下来,我们便可使用 Kibana 快速的检索我们的日志。
위 내용은 Node Framework를 ELK에 연결하는 과정 요약의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제









PHP와 Vue: 프론트엔드 개발 도구의 완벽한 조합 오늘날 인터넷이 빠르게 발전하는 시대에 프론트엔드 개발은 점점 더 중요해지고 있습니다. 사용자가 웹 사이트 및 애플리케이션 경험에 대한 요구 사항이 점점 더 높아짐에 따라 프런트 엔드 개발자는 보다 효율적이고 유연한 도구를 사용하여 반응형 및 대화형 인터페이스를 만들어야 합니다. 프론트엔드 개발 분야의 두 가지 중요한 기술인 PHP와 Vue.js는 함께 사용하면 완벽한 도구라고 볼 수 있습니다. 이 기사에서는 독자가 이 두 가지를 더 잘 이해하고 적용할 수 있도록 PHP와 Vue의 조합과 자세한 코드 예제를 살펴보겠습니다.

인터넷 기술이 발전하면서 프론트엔드 개발이 점점 더 중요해지고 있습니다. 특히 모바일 장치의 인기는 효율적이고 안정적이며 안전하고 유지 관리가 쉬운 프런트 엔드 개발 기술을 요구합니다. 빠르게 발전하는 프로그래밍 언어로서 Go 언어는 점점 더 많은 개발자가 사용하고 있습니다. 그렇다면 프론트엔드 개발에 Go 언어를 사용하는 것이 가능할까요? 다음으로 이 글에서는 프론트엔드 개발에 Go 언어를 사용하는 방법을 자세히 설명하겠습니다. 먼저 프론트엔드 개발에 Go 언어가 사용되는 이유를 살펴보겠습니다. 많은 사람들이 Go 언어가 언어라고 생각합니다.

프론트엔드 개발 인터뷰에서 일반적인 질문은 HTML/CSS 기초, JavaScript 기초, 프레임워크 및 라이브러리, 프로젝트 경험, 알고리즘 및 데이터 구조, 성능 최적화, 크로스 도메인 요청, 프론트엔드 엔지니어링, 디자인 패턴, 새로운 기술 및 트렌드. 면접관 질문은 후보자의 기술적 능력, 프로젝트 경험, 업계 동향에 대한 이해를 평가하기 위해 고안되었습니다. 따라서 지원자는 자신의 능력과 전문성을 입증할 수 있도록 해당 분야에 대한 충분한 준비를 갖추어야 합니다.

Django는 빠른 개발과 깔끔한 방법을 강조하는 Python으로 작성된 웹 애플리케이션 프레임워크입니다. Django는 웹 프레임워크이지만 Django가 프런트엔드인지 백엔드인지에 대한 질문에 답하려면 프런트엔드와 백엔드의 개념에 대한 깊은 이해가 필요합니다. 프론트엔드는 사용자가 직접 상호작용하는 인터페이스를 의미하고, 백엔드는 HTTP 프로토콜을 통해 데이터와 상호작용하는 서버측 프로그램을 의미합니다. 프론트엔드와 백엔드가 분리되면 프론트엔드와 백엔드 프로그램을 독립적으로 개발하여 각각 비즈니스 로직과 인터랙티브 효과, 데이터 교환을 구현할 수 있습니다.

Golang은 프런트엔드 애플리케이션을 포함하여 다양한 유형의 애플리케이션을 개발하는 데 사용할 수 있는 매우 다양한 프로그래밍 언어입니다. JavaScript와 같은 언어로 인해 발생하는 일련의 문제, 예를 들어 유형 안전성이 낮고 성능이 낮으며 코드 유지 관리가 어려운 문제 등이 있습니다.

C# 개발자로서 우리의 개발 작업에는 일반적으로 프런트엔드와 백엔드 개발이 포함됩니다. 기술이 발전하고 프로젝트의 복잡성이 증가함에 따라 프런트엔드와 백엔드의 공동 개발이 점점 더 중요해지고 복잡해졌습니다. 이 문서에서는 C# 개발자가 개발 작업을 보다 효율적으로 완료하는 데 도움이 되는 몇 가지 프런트 엔드 및 백엔드 공동 개발 기술을 공유합니다. 인터페이스 사양을 결정한 후 프런트엔드와 백엔드의 공동 개발은 API 인터페이스의 상호 작용과 분리될 수 없습니다. 프론트엔드와 백엔드 협업 개발이 원활하게 진행되기 위해서는 가장 중요한 것은 좋은 인터페이스 사양을 정의하는 것입니다. 인터페이스 사양에는 인터페이스 이름이 포함됩니다.

빠르고 효율적인 프로그래밍 언어인 Go 언어는 백엔드 개발 분야에서 널리 사용됩니다. 그러나 Go 언어를 프런트엔드 개발과 연관시키는 사람은 거의 없습니다. 실제로 프런트엔드 개발에 Go 언어를 사용하면 효율성이 향상될 뿐만 아니라 개발자에게 새로운 지평을 열어줄 수도 있습니다. 이 기사에서는 프런트엔드 개발에 Go 언어를 사용할 수 있는 가능성을 살펴보고 독자가 이 영역을 더 잘 이해할 수 있도록 구체적인 코드 예제를 제공합니다. 전통적인 프런트엔드 개발에서는 사용자 인터페이스를 구축하기 위해 JavaScript, HTML, CSS를 사용하는 경우가 많습니다.

인스턴트 메시징을 구현하는 방법에는 WebSocket, Long Polling, Server-Sent Events, WebRTC 등이 있습니다. 자세한 소개: 1. 실시간 양방향 통신을 달성하기 위해 클라이언트와 서버 사이에 지속적인 연결을 설정할 수 있는 WebSocket 프런트 엔드는 WebSocket API를 사용하여 WebSocket 연결을 생성하고 송수신을 통해 인스턴트 메시징을 달성할 수 있습니다. 2. 실시간 통신 등을 시뮬레이션하는 기술인 Long Polling
