从实用角度浅析前端全链路质量监控中台技术方案

news2024/11/14 13:13:50

大厂技术  高级前端  Node进阶

点击上方 程序员成长指北,关注公众号

回复1,加入高级Node交流群

感谢作者陈煮酒的投稿。

前言

无论是纯前端业务还是服务端业务,线上质量的保障都是我们的底线要求,也是我们日常需要花费很多精力关注的环节。

今天在这里就跟大家分享一下,如何从零到一建设一个能够对线上业务进行精准监控、及时告警的系统。希望能对大家有所帮助和启发。

架构图

86ccea6bf1bee1384a8bf8ca70cead73.jpeg
技术架构图

技术方案详述

数据采集(SDK部分)

Web 端 SDK

性能上报

Performance Timing

  • Performance.timing - Web APIs | MDN

  • 60a9e788597b9c7a3b93cfb3be300706.png

  • 普及 兼容

  • 语义更关注技术侧体验,跟不上新时代要求

  • 已经 deprecated

  • 519eea0bdd49e607a9fdc89b92a92377.png

Web Vitals

-  Web Vitals

  • e887a755b9535628f3ac848d28a9ec82.png

  • 更关注用户侧体验,更有业务价值

  • 未标准化,有些指标需要根据场景具体实现

    • 幸运的是 Google 已经开源了,可以直接用 https://github.com/GoogleChrome/web-vitals

  • 浏览器支持量 < Performance Timing

  • Largest Contentful Paint

  • 0a0b131b5ec255027e8b79cb22e3116f.png

特定需求

  • SSR 业务首屏

性能打点集中在页面进入和离开,没有请求压力的问题

异常上报

全局

  • Window error

  • Window unhandledrejection

加载

  • 资源加载型(https 下加载 http 资源,加载异常...)

  • 接口异常(拦截公共请求库)

自定义

  • 提供业务方自定义上报 API

  • 白屏:页面加载后检查关键 DOM 节点(例如 SSR 业务在 JS 执行时页面一定会有东西,更多的是结合业务实际逻辑做的考虑)

  • boundary

    • React

    • Vue

  • 异常限频 防止异常无限循环上报

    SDK 比较粗暴的策略:**Counter 超过 100 直接关闭**

    从异常感知的角度,当前页面上报了超过 100 个异常,那之前 100 个已经够感知及分析了

Node.js 端 SDK

Node.js 端主要通过 服务基础中间件 / PM2 插件进行信息采集

基础中间件

  • 基于中间件机制,支持 Koa / Express

  • 请求耗时上报

  • QPS 计算

  • 请求级 - 致命异常上报

  • 框架实例异常上报

  • Process 异常上报

    • uncaughtException

    • unhandledRejection

  • 自定义 - 非致命异常上报

  • 基于 Got 封装统一请求库

    • 下游接口调用异常上报

    • 链路信息透传,traceID 带到 header 中

  • 基于 zookeeper 的配置中心

    • 常用的 Header(CSP,CORS等)下发

    • 黑白名单下发

离线监控
  • 生产环境:

    • 基于 inspector-api 通过开关采集线上 CPU Profile / Memory Snapshot 文件,回传回内网静态资源服务,超时就在本地。导入 devtool 进行分析查看

    • 进程级别心跳检测,5分钟 上报一次状态

  • 开发环境:

    • autocannon(压测工具) + clinic(分析工具)

PM2 插件

  • 监听 pm2 Eventbus 消息,对 PM2 进程状态进行实时响应

SDK 更新机制

Web 端

  • 前端基础 SDK 最怕更新不及时

  • 用 hash 来硬编码每次更新成本很高

解决方案一:

代码中用 JS 动态生成小时级时间戳,与 CDN约定映射规则,实现小时级更新

解决方案二:

方案一实时性有保证,但存在大量的缓存浪费

SDK 构建时保留小时级时间戳,写入 zookeeper,服务连接 zookeeper 进行实时下发

服务端

与服务发布流程耦合,当基础库有版本升级时,自动更新最新版本

数据处理(中央日志服务部分)

性能日志规则

上报上来的原始性能数据会经历一些处理最终产出为标准化的日志

b73dc83fbe947697a0f1c604c123ecd4.jpeg
UML 图 (2).jpg

异常日志规则

  • 第三方厂商注入的 JS 报错、业务已知无需处理的 JS 报错 / 资源错误 / 接口错误 可以进行过滤,精简日志量,降低信噪比

  • 异常过滤特征实时下发到服务

  • 默认按照 error message 解析,支持业务方自定义异常解析规则

6ca4ba3039e8692c3a040928e640a963.jpeg
UML 图 (3).jpg

自身稳定性

  • 限流机制,一段时间内某个key(domain + path + ip 定时清除)上报超过阈值

  • 进程状态监控

  • CPU / 内存状态监控

数据消费(平台部分)

性能消费

  • 实时趋势 / 天级趋势

    • 多指标:DOMContentLoaded、TTFB、LCP、FP

    • 多维度:地域、机型、网络类型、运营商...

    • 多渠道:主流浏览器、特定APP

    • 基于 多维度信息补充 环节

  • 机型分布、地域分布、浏览器版本分布...

总结:基于采集到的性能数据做各种形式的图表展示

异常消费

实时异常列表

  • 按照规则聚合 倒排

  • 前端异常以 domain 为维度,Node.js 异常以 app 为维度

  • 支持堆栈解析(构建侧支持 sourcemap 上传能力)

日志消费

由服务端基础 SDK 统一生成 traceID,透传到页面和下游服务。

  • 通过 traceID 串联页面异步请求 / 服务端请求链条

  • 通过 traceID 定位单一异常的具体信息

数据存储设计

  • 实时查询 ES,读写分离,天级查询 MySQL => 降低 ES 查询压力

  • 标准化日志为 JSON String => 方便 logstash 解析,后期扩展字段更加灵活,基本无新增成本

  • 持久化存储每个字段单独一条数据,定期分表 => 后续指标的接入更加灵活,无新增成本

告警机制

告警过于迟钝会失去意义,告警过于频繁会降低敏感性

告警分级制度

  • 请求级异常 / 前端异常:按照数量进行聚合后触达

    • 实时 / 天级性能趋势波动 超过阈值

    • 请求级异常数量 超过阈值

  • 进程级异常:实时触达

告警确认制度

平台提供异常确认功能,今日已确认的异常数量在计算中将会屏蔽,直到下次再次触达阈值继续告警

阈值调整

  • 整体阈值:按照 domain / app 天级上报量 十万分之五 自动生成,支持业务方自行修改

  • 单一阈值:业务自定,以 异常特征 为维度进行阈值设定

合成监控

上面整体是 RUM(Real User Monitoring)部分,需要采集真实用户数据进行分析。大量的真实用户数据可以非常好的反映整个业务的趋势和实时的业务稳定情况。

对于一个完整的监控中台,还需要一些离线的采集手段做更详细的分析得到更直接的建议,也就是合成监控。

这部分我们选择基于 Lighthouse Node CLI 进行建设

Lighthouse 简介

d3ad9eb55f5762f9e8b5b0992b040f36.png
image.png
  • Driver

    • 对 Puppeteer 和 Chrome Devtools Protocol 的接口

  • Gatherers

    • 收集器:通过 Driver 收集页面的相关信息。Performance、Network 等

  • 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": {...},
}
  • Report

    • 基于 LHR 输出报告

    • 常规情况开发同学可以通过 Chrome Devtools 的 lighthouse 选项卡进行手动的操作采集得到 reporter 报告6150946e0cea90bc0d4a57f88255956b.png

弊端:

  • 评分不稳定,忽高忽低

  • 有些项可能当前业务并不关注

基于上述两点,我们选择针对业务特点去建设自定义规则

常用配置

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.'
        },
    }
};

settings

控制整个审计过程。

  • onlyAudits:只执行哪些审计

  • maxWaitForFcp:最大等待页面 FCP 时间,超时直接抛错

  • ...

详见:https://github.com/GoogleChrome/lighthouse/blob/575e29b8b6634bfb280bc820efea6795f3dd9017/types/externs.d.ts#L141-L186

passes

控制如何加载请求的****URL

Passes 数组每一项代表着不同情况,都会重新加载一次页面,所以需要控制数量

  • recordTrace:否启用上个 pass 跟踪记录

  • networkQuietThresholdMs:距离上个 pass 完成后安静时长,以确保所有请求瀑布流走完,默认5000

  • gatherers:配置的收集器

  • ...

详见:https://github.com/GoogleChrome/lighthouse/blob/da3c865d698abc9365fa7bb087a08ce8c89b0a05/docs/configuration.md

可以配置自定义收集器

详见:https://github.com/GoogleChrome/lighthouse/tree/main/docs/recipes/custom-audit

audits

控制要运行和包含在最终报告中的 audit

可以配置自定义 audit

categories、groups

对报告中的审计结果进行评分和分类

在分类中对结果进行可视化分组

自定义

Lighthouse 暴露了标准的 GatherAudit 的接口,我们可以继承实现自己的收集器和审查器

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:目标页面加载后调用,在所有 gatherpass 方法之后

  • 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:为报告提供的额外信息,支持多种格式

13e5137bc46de0827acbd8c68f91a574.png
image.png

注意事项

  • cli 的性能评分与 devtool 会有一定差距,甚至相同平台每次跑的性能评分也会有较大差距,以参考为主

  • 更适合做比较稳定的测量,比如资源加载类,DOM节点类

总结与未来展望

上述中台是在支持日常业务之余不断去迭代的,功能上还有很多不完善以及待优化之处。

从业务层面考虑:在建设它的这几年,它比较好的承担了业务对于监控中台的需要,并且为业务解决了大多数的问题。

从技术层面来考虑:未来还有很多能做的东西

  • 底层能力

    • 更完善灵活的日志能力支持

    • 更底层的服务监控能力

  • 归因能力 由经验型归因到智能型归因 => 智能运维

    • 经验型归因:提供尽可能全面的信息帮助定位问题,最后取决于业务同学的经验

    • 智能型归因:通过对历史数据集的最大化利用,利用算法智能推导异常原因,常规问题降低工程师精力占用

  • 大流量场景下的中台稳定性问题

    • 网关负载

    • 限流

  • 云原生能力

    • 更快速稳定的扩缩容

    • Prometheus 云原生监控

    • ...

本质上来说,我们做的一切技术工作都是为了业务提效。

在监控运维能力的各个方向都有更多的资源去探索深入的时候,我们可以依托于这些能力去建设更稳定的服务。

工程师就可以有更多的精力去放在业务的迭代和技术的提升中,让我们的技术工作更有价值。

Node 社群

我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。

如果你觉得这篇内容对你有帮助,我想请你帮我2个小忙:
1. 点个「在看」,让更多人也能看到这篇文章2. 订阅官方博客 www.inode.club 让我们一起成长

点赞和在看就是最大的支持❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/57149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【大数据入门核心技术-Zookeeper】(五)ZooKeeper集群搭建

目录 一、准备工作 1、集群分布 2、创建数据目录 3、下载安装包 二、解压安装 1、解压 2、修改配置文件zoo.cfg 3、添加myid配置 4、分发zk文件夹和分别新建myid 5、配置环境变量 6、三台机器分别启动zookeeper服务 一、准备工作 1、集群分布 服务器IP主机名myid的…

有损压缩与无损压缩

有损压缩与无损压缩数据压缩有损压缩无损压缩有损压缩与无损压缩的区别Which One to Use?Final Words有损压缩、无损压缩&#xff08;图片、音频、视频&#xff09;图片文件格式音频文件格式视频文件格式数据压缩 数据压缩&#xff08;Data Compression&#xff09;是减小任何…

教你6招轻松搞定 网站被木马反复篡改

提到网络被恶意篡改&#xff0c;应该让很多做了百度竞价的企业官网怀恨已久了吧&#xff1f;这类行为的目的就是通过这些受害网站获得排名并跳转到违法网站&#xff0c;达到不法的目的。对于企业来说不但损失了百度竞价的费用&#xff0c;还对企业形象造成很大的影响。甚至直接…

【Flink】检查点算法实现原理之检查点分界线

一 检查点的实现算法 一种简单的想法&#xff08;同步的思想&#xff09; 暂停应用保存状态到检查点再重新恢复应用&#xff08;Spark Streaming&#xff09; Flink 的改进实现&#xff08;异步的思想&#xff09; 基于 Chandy-Lamport 算法的分布式快照算法将检查点的保存和数…

20221203使用python3处理Google翻译英文SRT格式字幕

20221203使用python3处理Google翻译英文SRT格式字幕 1、暂时不处理UNICODE编码的TXT&#xff0c;本例以ANSI编码的TXT为准。 2、将来处理自动处理目录中的全部TXT文件。&#xff08;甚至递归处理子目录中的TXT文件&#xff09; 源码&#xff1a; #f_pathrC:\Users\Admin\Desk…

如何解hard算法题?

如何解困难题&#xff1f;前言一、案例二、困难题拆解1、自己的思路2、官方的思路3、源码Javagolang总结参考文献前言 上一篇文章写bitCount源码解析&#xff0c;对困难题有一些抽象的理解。 困难题就是一个个简单的知识点组成&#xff0c;加上其内在的逻辑联系。所以一个困难…

S2SH志愿者捐赠管理系统|捐助计算机毕业论文Java项目源码下载

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 《基于S2SH实现的志愿者捐赠管理系统》该项目采用技术jsp、strust2、Spring、hibernate、tomcat服务器、mysql数据库 &#xff0c;项目含有源码、…

02、数据卷(Data Volumes)以及dockefile详解

目录 1、Docker 数据管理 2、数据卷(Data Volumes) 3、数据卷容器 4、dockerfile 5、dockerfile基本结构 6、docker使用Dockerfile创建jdk容器 启动虚拟机&#xff0c;进入CentOS 7、dockerfile实践经验 1、Docker 数据管理 在生产环境中使用 Docker &#xff0c;往往需…

混合动力电动车优化调度与建模(发动机,电机,电池组等组件建模)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f4dd;目前更新&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;电力系统相关知识&#xff0c;期刊论文&…

6-4布线问题(分支限界)

6-4布线问题&#xff08;分支限界&#xff09; 一、问题描述 印刷电路板将布线区域划分成m*n个方格阵列,如图(1)所示。 精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案。 在布线时,电路只能沿直线或直角布线,如图(2)所示。 为了避免线路相交&#xf…

C语言第十二课(下):操作符详解【逗号表达式、下标引用、函数调用、结构成员操作符与操作符属性】

目录 前言&#xff1a; 一、逗号表达式&#xff08;exp1&#xff0c;exp2&#xff0c;exp3&#xff0c;...&#xff0c;expN&#xff09;&#xff1a; 二、下标引用、函数调用和结构成员[ ]、( )、. 、->&#xff1a; 1.下标引用操作符[ ]&#xff1a; 2.函数调用操作符( …

Tomcat过时了?别多想,很多公司还是在用的。这份Tomcat架构详解,真的颠覆你的认知

Tomcat 不但没有过时&#xff0c;Spring Boot 还给 Tomcat 第二春了。 微服务的兴起&#xff0c;Tomcat 针对很多应用已经做成 embedded 模式了&#xff0c;Tomcat 本身是容器&#xff0c;Tomcat 的出现就是为了解决但是 EJB 和 Weblogic&#xff0c;JBoss 这种大而全的大象导致…

C++ OpenCV【视频合并:多个图像拼接在一张图像】

提示&#xff1a;本文中视频拼接指的是将多张图像按空间合并在一张图像上&#xff0c;而不是将多张图像按时间顺序拼接成一个多帧片段。 文章目录 前言 一、OpenCV知识点 1.OpenCV裁剪矩形区域赋值 2.OpenCV将Mat粘贴到指定位置 二、程序样例 1.程序源码 2.运行结果 前言 C版…

[附源码]Python计算机毕业设计Django姜太公渔具销售系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

看完这篇,还不懂JAVA内存模型(JMM)算我输

前言 开篇一个例子&#xff0c;我看看都有谁会&#xff1f;如果不会的&#xff0c;或者不知道原理的&#xff0c;还是老老实实看完这篇文章吧。 Slf4j(topic "c.VolatileTest") public class VolatileTest {static boolean run true;public static void main(Str…

一个简单的HTML网页 个人网站设计与实现 HTML+CSS+JavaScript自适应个人相册展示留言博客模板

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

Ubtunu排查磁盘空间是否已满—并清理的方式

项目场景&#xff1a; 最近使用nodejs开发的后端项目部署到Ubtunu服务器后接口无法访问了&#xff0c;接口也调用不通&#xff0c;NGINX报502错误。 问题描述 使用远程连接工具传文件也是无法上传&#xff0c;提示找不到文件&#xff0c;SCP命令也无法上传。 scp传文件报错&…

一文教会你如何在内网搭建一套属于自己小组的在线 API 文档?

Hello&#xff0c;大家好&#xff0c;我是阿粉&#xff0c;对接文档是每个开发人员不可避免都要写的&#xff0c;友好的文档可以大大的提升工作效率。 阿粉最近将项目的文档基于 Gitbook 和 Gitlab 的 Webhook 功能的在内网部署了一套实时的&#xff0c;使用起来特方便了。跟着…

第二证券|11月十大牛股出炉 特一药业163%涨幅问鼎榜首

到11月30日收盘&#xff0c;11月份十大牛股中7只个股涨幅超过100%&#xff0c;涨幅最小的也有87%&#xff0c;均匀涨幅较上个月有所扩大。 11月&#xff0c;A股出现震荡爬高态势&#xff0c;到11月30日收盘&#xff0c;上证指数月内涨8.91%&#xff0c;深证成指涨6.84%&#xf…

大学生HTML作业节日网页 HTML作业节日文化网页期末作业 html+css+js节日网页 HTML学生节日介绍 HTML学生作业网页视频

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…