ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

前端海量异常日志上报优化:IndexedDB做本地缓存,解决上报阻塞、丢日志问题

前端海量异常日志上报优化:IndexedDB做本地缓存,解决上报阻塞、丢日志问题 本系列围绕Web端实时异常分析监控系统展开。上一篇讲解了监控SDK的设计JS错误、页面性能、API接口异常三类数据的采集原理与工程坑点。本篇为系列第三篇重点解决日志上报环节的痛点大量异常突发时网络请求风暴、弱网/断网环境日志丢失。详细讲解IndexedDB双分区缓存架构、日志完整流转生命周期、WebSocket与HTTP双通道上报策略同时分析浏览器环境下缓存机制的各类降级与边界处理。后续文章进入服务端分析引擎模块。1. 前言客户端SDK完成异常采集之后很多人第一直觉就是拿到异常数据直接发起HTTP请求上报到后端服务。在异常数量很少的时候这种简单直报的方式可以正常工作。但是放到真实线上复杂场景会暴露出非常多棘手的问题。想象这样一类线上故障场景业务页面出现全局性JS报错用户每一次交互都会触发一条异常日志。此时页面会在短时间内批量产生几十上百条异常如果每一条异常都立刻发起fetch或者XMLHttpRequest请求上报。大量并发网络请求会抢占业务接口的网络带宽造成正常业务请求排队、超时SDK的上报逻辑反而加重了页面故障形成雪上加霜的局面。除了请求风暴之外还有弱网、断网场景的问题。移动端用户网络切换、地铁隧道信号差、用户直接断开Wi‑Fi此时网络不可用同步发起的上报请求会直接失败珍贵的异常日志直接全部丢失。等到网络恢复之后这些已经产生的异常不会再重新触发问题现场就此消失后端完全无法感知这一部分用户的故障。localStorage可以实现本地存储但是它是同步阻塞API存储大数据量的时候会阻塞浏览器主线程同时存储容量存在严格上限一般只有5MB并不适合用来缓存大量监控日志。Cookie存储空间更小更不能用来存放日志数据。基于以上痛点我们需要一套浏览器端本地缓存异步延迟上报的方案。利用IndexedDB做本地持久化存储设计日志缓存区、日志同步区双分区配合WebSocketHTTP双通道上报既避免上报阻塞业务又尽可能减少断网场景下日志丢失。本篇只讲架构策略与设计思路不放出完整IndexedDB增删改查业务代码做技术保留。2. IndexedDB选型依据与基础特性IndexedDB是浏览器原生提供的非关系型本地数据库具备几个非常契合监控日志缓存的特性完全异步API所有读写操作全部异步执行不会阻塞JS主线程不会造成页面卡顿存储容量大存储配额受浏览器磁盘策略管控远大于localStorage的5MB限制可以存放批量异常日志支持键值对存储、索引查询方便按时间、上报状态筛选日志数据持久化存储页面刷新、标签页重启之后缓存的数据依然可以保留。当然IndexedDB也不是完美的它也存在现实约束浏览器隐私模式下部分浏览器会禁用IndexedDB或者允许使用但是页面关闭之后立刻清空全部数据不同浏览器的错误回调、事务行为存在细微兼容性差异API接口调用繁琐代码量相比localStorage要大很多。所以整套缓存方案需要配套降级逻辑当IndexedDB不可用的时候退化为内存队列上报模式。内存队列模式下断网会丢失日志但至少保证页面功能不会崩溃。3. 日志缓存区、同步区双分区架构设计本方案在IndexedDB内部建立两套对象仓库分别为日志缓存区、日志同步区两个分区职责明确日志会按照固定的流程在两个分区之间流转。3.1 两个分区职责划分日志缓存区新捕获产生的异常日志首先写入缓存区。缓存区存放尚未开始同步上报的原始日志。这里是日志进入本地存储的第一站。日志同步区日志从缓存区取出上报后端并且确认上报成功之后移动到同步区。同步区代表已经成功同步到服务端的日志记录后续可以按照过期策略做清理。为什么要划分两个分区而不是只用一张表加状态字段在高并发产生大量日志的场景下分开两个对象仓库可以减少同一个事务内的数据读写竞争。上报读取数据的时候只操作缓存区成功之后迁移到同步区清理过期数据只操作同步区。降低大数量下IndexedDB事务报错、死锁的概率。3.2 日志完整生命周期SDK捕获JS错误/性能指标/API异常组装成完整日志对象将日志写入IndexedDB的日志缓存区判断当前网络环境建立上报通信通道从缓存区批量读取多条未上报日志通过通道向服务端发送收到后端返回上报成功应答将这批日志迁移写入日志同步区按照过期清理策略定时删除同步区内超过保留周期的旧日志。关键点必须拿到后端成功应答之后才算上报完成不能日志取出之后就直接删除。如果网络中途中断本次上报失败日志仍然保留在缓存区等待下一次网络恢复继续重试上报避免日志丢失。4. WebSocket HTTP双通道上报策略仅仅有本地缓存还不够还要设计上报通信通道。本系统采用双通道策略优先WebSocket长连接做实时日志同步当WebSocket不可用时自动降级到HTTP批量上报。4.1 WebSocket实时上报触发时机并不是页面一打开就无条件建立WebSocket连接。频繁建立长连接会增加服务端连接压力。这里设置触发规则当本次会话第一次产生异常日志的时候才去初始化建立WebSocket连接。页面全程没有发生任何异常则不会创建长连接节约服务器资源。WebSocket建立成功之后持续进行日志推送适合异常爆发时的实时同步。前端把缓存区的日志批量封装通过帧消息发送给后端。4.2 WebSocket失效时降级HTTP批量上报WebSocket会遇到很多无法建立的场景部分公司内网防火墙、代理服务器会拦截WebSocket协议移动端网络切换的时候长连接会意外断开。此时SDK自动切换为HTTP批量上报模式从IndexedDB缓存区读取多条日志组装成数组使用POST接口批量提交给后端而不是一条日志一次请求。批量上报可以显著减少http请求次数降低网络开销。4.3 心跳与连接重建逻辑WebSocket连接过程中SDK会维护简单心跳机制。前端定时发送心跳包检测长连接是否存活。如果心跳超时判定连接已经断开SDK关闭旧连接标记通道降级为HTTP监听online网络事件当检测到网络重新恢复可以尝试重新建立WebSocket。5. 本地缓存淘汰与过期清理策略浏览器磁盘空间不能无限占用如果用户长时间不清理页面缓存区会不断堆积大量历史日志会占用浏览器存储空间。因此必须设置缓存淘汰与过期清理规则。时间过期清理同步区的日志超过配置保存时长例如7天执行批量删除。已经上报完成的日志没有必要永久保存在浏览器本地。缓存区容量上限给日志缓存区设置最大记录条数阈值。当缓存区内日志超过阈值优先丢弃最老旧的异常日志。新日志继续写入防止存储无限膨胀。这里是妥协点极端持续故障场景下如果一直网络不通缓存区打满旧日志会被丢弃。优先保证新产生的异常可以被记录。清理时机不做高频定时轮询选择在写入新日志的间隙顺带执行过期清理减少频繁的IndexedDB事务调用降低性能消耗。6. 各类异常边界与降级处理方案浏览器环境复杂多变很多场景会导致IndexedDB不可用必须做好完备降级不能因为缓存模块异常把整个业务页面搞崩。6.1 隐私模式下IndexedDB不可用部分浏览器隐私模式打开页面IndexedDB会抛出异常无法正常写入数据。降级策略关闭持久化缓存切换为内存队列模式。日志存放在JS内存数组尽可能批量上报。缺点页面刷新、标签关闭之后内存队列全部清空断网时日志会丢失但页面业务逻辑不受影响。6.2 页面强制关闭还存在未上报日志用户直接关闭标签页、浏览器此时缓存区还有尚未上报完成的日志。浏览器页面unload阶段同步JS操作很有可能被浏览器直接终止。可以尝试使用navigator.sendBeacon接口。sendBeacon是浏览器专门为页面卸载场景设计的API可以在页面退出之前异步发送少量数据。局限sendBeacon有数据体积上限不能发送大批量日志只能尽可能发送少量高优先级异常无法保证100%送达属于尽力而为的补偿手段。6.3 上报过程中又持续产生新异常在读取缓存区、执行上报的同时页面继续产生新异常写入缓存区。SDK需要做好读写隔离避免上报迭代读取的时候重复发送同一条日志。可以给缓存区日志增加上报状态标记标记“上报中”避免同一日志被多次重复提交到后端。7. 该套缓存上报方案收益与现实局限收益解决异常集中爆发带来的网络请求风暴通过本地缓存批量上报减少网络请求数量不抢占业务接口带宽弱网、断网场景日志持久化保存在IndexedDB网络恢复后重试上报大幅降低日志丢失概率WebSocket实时同步兼顾时效性HTTP批量作为兜底适配各种复杂网络环境有完整的降级策略存储API失效时不会导致业务页面报错崩溃。局限IndexedDB本身API复杂存在浏览器兼容性差异开发调试成本较高用户手动清理浏览器缓存缓存区全部日志直接丢失SDK无法阻止用户行为页面强制关闭场景只能尽力回传部分日志依然存在少量日志丢失可能性无法做到绝对不丢本缓存上报只是整套监控体系的其中一环需要和后端接收服务配合才能发挥完整效果。8. 本篇小结与系列后续内容预告本篇围绕日志上报环节的痛点讲解IndexedDB的选型日志缓存区、同步区双分区架构日志完整流转生命周期WebSocketHTTP双通道上报、缓存淘汰清理策略同时梳理隐私模式、页面关闭等各类边界场景下的降级方案。客户端完成日志上报之后大量原始日志抵达服务端。下一篇我们进入服务端分析引擎讲解LevelDB存储选型JS Error异常多维度分析逻辑以及Source‑Map堆栈还原定位源码的完整实现思路。第四篇线上JS报错如何快速定位源码位置异常分析引擎、Source‑Map反解与问题归类实现思路第五篇Web监控系统页面性能、API接口指标统计分析可视化大盘设计思路第六篇Web监控告警不要乱轰炸自定义基线、三级分级报警、多渠道通知体系设计方案第七篇【系列收官】Web实时异常监控系统异常闭环流程、工程取舍与Sentry方案横向对比总结。本文为系列第三篇讲解前端日志本地缓存与双通道上报策略。下一篇进入后端服务端分析引擎。版权声明本文为技术思路探讨相关方案仅做学习交流请勿直接复制用于生产环境。
返回列表