拓冰建站拓冰建站
首页 / 资讯中心 / 正文

electron-anyproxy源码解析(四):recorder基于nedb的请求录制与缓存架构设计

electron-anyproxy源码解析四recorder基于nedb的请求录制与缓存架构设计【免费下载链接】electron-anyproxy A http/https proxy client, using to analyze and mock.项目地址: https://gitcode.com/gh_mirrors/el/electron-anyproxyelectron-anyproxy 是一款基于 Electron 的 http/https 代理客户端核心能力是抓包分析与接口 Mock。本篇 electron-anyproxy源码解析继续深入其内部实现聚焦请求录制模块 recorder它如何在内存、nedb 数据库与文件系统三者之间分配职责如何做到「元数据入库、响应体落盘」的缓存架构设计以及如何通过事件机制把录制结果实时推送到前端界面。理解了这套架构你就掌握了整个代理工具数据链路的地基。一、recorder 模块的定位整个代理工具的「数据中枢」在 electron-anyproxy 中recorder 是记录一切的模块它记录每一次请求的 URL、Host、Method、请求头、响应头、状态码、耗时以及完整的请求/响应体。它并不直接处理网络 IO而是作为被动接收者由请求处理链路主动喂数据。recorder 实例在 proxy.js 的 ProxyServer 构造器中创建this.recorder new Recorder(); global.recorder this.recorder;创建后它被注入 RequestHandlerlib/requestHandler.js和 webInterfacelib/webInterface.js成为请求处理与前端展示之间的桥梁。可以说recorder 是代理工具的「数据中枢」。二、缓存架构设计内存自增 ID nedb 数据库 文件系统三层结构这是整个模块最值得学习的设计。recorder 没有把所有数据一股脑塞进数据库而是做了清晰的分层数据存储位置设计原因自增 ID内存变量globalId生成唯一主键避免依赖数据库自增请求/响应元数据nedb 数据库文件结构化查询、排序、分页响应体内容独立文件res_body_{id}大体积二进制不污染数据库按需读取1. 随机缓存目录每次启动都是全新的快照recorder 初始化时会生成一个随机缓存目录lib/recorder.jsconst CACHE_DIR_PREFIX cache_r; const DB_FILE_NAME anyproxy_db; function getCacheDir() { const rand Math.floor(Math.random() * 1000000); const cachePath path.join(proxyUtil.getAnyProxyPath(cache), ./ CACHE_DIR_PREFIX rand); fs.mkdirSync(cachePath); return cachePath; }目录位于~/.anyproxy/cache/cache_r{随机数}下。随机后缀意味着每次启动代理都是全新的录制快照互不干扰也简化了清理逻辑。2. nedb 数据库零配置的嵌入式文档数据库recorder 使用 nedb 作为存储引擎。nedb 是纯 JavaScript 实现的嵌入式 NoSQL 数据库API 与 MongoDB 高度相似非常适合 Electron 这类需要随应用分发、又不想引入重量级数据库服务的场景db new Datastore({ filename: dbFilePath, autoload: true }); db.persistence.setAutocompactionInterval(5001);两个细节值得注意autoload: true让数据库打开即用setAutocompactionInterval(5001)每 5 秒自动压缩一次数据文件。nedb 采用 append-only 写入频繁更新会产生大量冗余记录自动压缩能显著减小文件体积。如果磁盘文件加载失败比如权限问题代码会优雅降级为纯内存数据库保证代理功能不中断这种容错思路值得借鉴。3. 响应体落盘body-map 设计响应体可能包含大图片、大文件没有存入数据库而是单独写成文件const BODY_FILE_PRFIX res_body_; self.updateRecordBody function (id, info) { if (!id || !info.resBody) return; const bodyFile path.join(cachePath, BODY_FILE_PRFIX id); fs.writeFile(bodyFile, info.resBody); };数据库里只保存_id响应体通过res_body_{id}文件按需读取。这种「元数据与内容分离」的缓存架构设计避免了数据库膨胀也让大响应体的读取不会阻塞录制流程。三、请求录制核心流程appendRecord 与 updateRecord 的前后呼应录制不是一个动作而是一对动作由 lib/requestHandler.js 在请求处理的不同阶段触发请求到达时调用recorder.appendRecord(resourceInfo)分配自增 ID插入初始记录并立即通过事件推送前端用户能马上看到「请求已发出」响应返回后填充状态码、响应头、响应体、耗时等字段调用recorder.updateRecord(resourceInfoId, resourceInfo)更新同一条记录。这两个方法内部都调用了normalizeInfo把原始信息规整为统一的记录结构singleRecord._id id; singleRecord.url info.url; singleRecord.host info.host; singleRecord.method info.method; singleRecord.reqHeader info.req.headers; singleRecord.startTime info.startTime; singleRecord.statusCode info.statusCode; singleRecord.resHeader info.resHeader; singleRecord.duration info.endTime - info.startTime;其中duration耗时由 endTime 减去 startTime 计算得出为前端展示接口耗时提供了直接数据。四、响应体解码字符集识别与类型判定的巧妙处理响应体拿到手后不能直接展示recorder 提供了getDecodedBody方法完成两件事字符集解码遍历响应头 JSON 字符串正则匹配charset若服务端不是 UTF-8 编码则用 iconv-lite 转码内容类型判定根据content-type区分 JSON、图片和普通文本图片以 Buffer 形式返回便于前端直接渲染。对应前端接口位于 lib/webInterface.js/fetchBody?idxx返回解码后的内容rawtrue则直接输出原始二进制如图片。五、查询接口设计满足列表、分页与详情的全部场景recorder 暴露了四个查询方法覆盖前端所有数据需求getSummaryList(cb)全量查询用于统计getRecords(idStart, limit, cb)按_id升序排序并分页配合 Web 界面「加载更多」的场景例如 webInterface 中一次取 10000 条lib/webInterface.js 的/latestLog接口getSingleRecord(id, cb)按主键查询单条详情getBody(id, cb)/getDecodedBody(id, cb)读取响应体。排序、limit 都直接在 nedb 查询中完成无需在 JS 层做二次处理代码非常精简。六、事件驱动EventEmitter 与 WebSocket 的实时推送链路recorder 继承了events.EventEmitter这是它连接前端的关键设计。emitUpdate在每次 append 或 update 后触发update事件而 lib/wsServer.js 订阅了这个事件recorder.on(update, (data) { sendMultipleMessage(data); });消息不会一条条立刻发出而是先进入messageQueue队列由 50ms 的定时器批量打包广播前端通过 WebSocket 一次性收到多条更新大幅降低推送频率、提升渲染性能。这正是客户端 network.vue 中请求列表实时滚动的数据来源。七、缓存清理机制关闭即清空ProxyServer 的close()方法会调用recorder.clear()通过递归删除缓存目录实现一键清空lib/util.js 的deleteFolderContentsRecursive。因为缓存目录是随机命名的独立快照删除时无需担心误伤其他数据这也是随机目录设计带来的另一大红利。八、总结recorder 架构设计的三个启示回顾整个 lib/recorder.js这套请求录制与缓存架构设计给我们带来三点启发职责分层元数据入库、内容落盘、ID 自增放内存各司其职互不拖累容错降级数据库加载失败自动切内存模式保证代理主流程不受影响事件解耦录制、推送、展示通过事件机制解耦新增消费方只需监听update事件无需改动录制核心。下一篇 electron-anyproxy源码解析将继续剖析 rule 规则引擎与 Mock 机制看这些被录制的数据如何反过来支撑接口模拟与篡改敬请期待。【免费下载链接】electron-anyproxy A http/https proxy client, using to analyze and mock.项目地址: https://gitcode.com/gh_mirrors/el/electron-anyproxy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门