无论是纯前端业务还是服务端业务,线上质量的保障都是我们的底线要求,也是我们日常需要花费很多精力关注的环节。
今天在这里就跟大家分享一下,如何从零到一建设一个能够对线上业务进行精准监控、及时告警的系统。 希望能对大家有所帮助和启发。
性能打点集中在页面进入和离开,没有请求压力的问题
Window error
Window unhandledrejection
API
DOM
节点(例如 SSR 业务在 JS 执行时页面一定会有东西,更多的是结合业务实际逻辑做的考虑)React
Vue
Counter
超过 100 直接关闭**
从异常感知的角度,当前页面上报了超过 100 个异常,那之前 100 个已经够感知及分析了
Node.js 端主要通过 服务基础中间件 / PM2 插件进行信息采集
Koa / Express
Process
异常上报
uncaughtException
unhandledRejection
Got
封装统一请求库
zookeeper
的配置中心
CPU Profile / Memory Snapshot
文件,回传回内网静态资源服务,超时就在本地。导入 devtool
进行分析查看pm2 Eventbus
消息,对 PM2
进程状态进行实时响应解决方案一:
代码中用 JS 动态生成小时级时间戳,与 CDN约定映射规则,实现小时级更新
解决方案二:
方案一实时性有保证,但存在大量的缓存浪费
SDK 构建时保留小时级时间戳,写入 zookeeper
,服务连接 zookeeper
进行实时下发
与服务发布流程耦合,当基础库有版本升级时,自动更新最新版本
上报上来的原始性能数据会经历一些处理最终产出为标准化的日志
error message
解析,支持业务方自定义异常解析规则key
(domain + path + ip 定时清除)上报超过阈值总结:基于采集到的性能数据做各种形式的图表展示
实时异常列表
由服务端基础 SDK 统一生成 traceID,透传到页面和下游服务。
告警过于迟钝会失去意义,告警过于频繁会降低敏感性
平台提供异常确认功能,今日已确认的异常数量在计算中将会屏蔽,直到下次再次触达阈值继续告警
上面整体是 RUM(Real User Monitoring)部分,需要采集真实用户数据进行分析。大量的真实用户数据可以非常好的反映整个业务的趋势和实时的业务稳定情况。
对于一个完整的监控中台,还需要一些离线的采集手段做更详细的分析得到更直接的建议,也就是合成监控。
这部分我们选择基于 Lighthouse Node CLI 进行建设
Audit
审核器:基于 Gather 收集到的信息,进行解析计算得到分数。
会输出一个 LHR(Lighthouse Result Object) 对象
{
"lighthouseVersion": "5.1.0",
"fetchTime": "2019-05-05T20:50:54.185Z",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3358.0 Safari/537.36",
"requestedUrl": "http://example.com",
"finalUrl": "https://www.example.com/",
"audits": {...},
"configSettings": {...},
"timing": {...},
"categories": {...},
"categoryGroups": {...},
}
弊端:
基于上述两点,我们选择针对业务特点去建设自定义规则
module.exports = {
extends: 'lighthouse:default',
settings: {
onlyAudits: ['first-meaningful-paint', 'speed-index', 'interactive',],
maxWaitForFcp: 3000
},
passes: [
{
passName: 'fastPass',
gatherers: ['fast-gatherer'],
},
{
passName: 'slowPass',
recordTrace: true,
useThrottling: true,
networkQuietThresholdMs: 5000,
gatherers: ['slow-gatherer'],
}
],
categories: {
performance: {
title: 'Performance',
description: 'This category judges your performance',
auditRefs: [
{ id: 'first-meaningful-paint', weight: 2, group: 'metrics' },
{ id: 'first-contentful-paint', weight: 3, group: 'metrics' },
{ id: 'interactive', weight: 5, group: 'metrics' },
],
}
},
groups: {
'metrics': {
title: 'Metrics',
description: 'These metrics encapsulate your web app's performance across a number of dimensions.'
},
}
};
控制整个审计过程。
控制如何加载请求的****URL
Passes 数组每一项代表着不同情况,都会重新加载一次页面,所以需要控制数量
可以配置自定义收集器
详见:https://github.com/GoogleChrome/lighthouse/tree/main/docs/recipes/custom-audit
控制要运行和包含在最终报告中的 audit
可以配置自定义 audit
对报告中的审计结果进行评分和分类
在分类中对结果进行可视化分组
Lighthouse 暴露了标准的 Gather
、Audit
的接口,我们可以继承实现自己的收集器和审查器
const { Gatherer } = require('lighthouse');
class ResourceSizeGather extends Gatherer {
afterPass(options, loadData) {
return loadData.networkRecords.reduce((arr, record) => {
if (record.resourceType === 'Image') {
arr.push(record)
}
return arr;
}, []);
}
}
module.exports = ResourceSizeGather;
afterPass
:目标页面加载后调用,在所有 gather
的 pass
方法之后loadData
:会提供网络请求相关数据const { Audit } = require('lighthouse');
const INIT_SCORE = 100;
class ResourceSizeAudit extends Audit {
static get meta() {
return {
id: 'resource-size-audit',
title: '正常图片',
failureTitle: '过大图片',
description: '过大图片列表',
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
requiredArtifacts: ['ResourceSizeGather'],
};
}
static audit(artifacts) {
const imageList = artifacts.ResourceSizeGather;
const overSizeList = imageList.filter((img => img.resourceSize > 50 * 1024));
const finalScore = (INIT_SCORE - overSizeList.length * 0.5) / 100;
const headings = [
{ key: 'url', itemType: 'thumbnail', text: '资源预览' },
{ key: 'url', itemType: 'url', text: '图片资源地址' },
{ key: 'resourceSize', itemType: 'bytes', text: '原始大小' },
{ key: 'transferSize', itemType: 'bytes', text: '传输大小' }, ];
return {
score: finalScore,
displayValue: `${overSizeList.length} / ${imageList.length} Size > 50 KB`,
details: Audit.makeTableDetails(headings, overSizeList),
};
}
}
module.exports = ResourceSizeAudit;
meta
:返回审查器的元信息
requiredArtifacts
:当前审查器依赖的采集器,必填audit
:经过计算,返回本次审查结果
score
:本次审查的分数,必填displayValue
:审查结果(字符串值)details
:为报告提供的额外信息,支持多种格式上述中台是在支持日常业务之余不断去迭代的,功能上还有很多不完善以及待优化之处。
从业务层面考虑:在建设它的这几年,它比较好的承担了业务对于监控中台的需要,并且为业务解决了大多数的问题。
从技术层面来考虑:未来还有很多能做的东西
Prometheus
云原生监控本质上来说,我们做的一切技术工作都是为了业务提效。
在监控运维能力的各个方向都有更多的资源去探索深入的时候,我们可以依托于这些能力去建设更稳定的服务。
工程师就可以有更多的精力去放在业务的迭代和技术的提升中,让我们的技术工作更有价值。