尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

HAR文件打开与分析方法:从接口超时到耗时拆解实战指南

HAR文件打开与分析方法:从接口超时到耗时拆解实战指南 昨天测试同事在群里发过来一个.har文件说要排查线上接口超时的问题。我保存下来双击浏览器没有任何反应用记事本打开又是满屏乱码一样的 JSON直接蒙了。类似的事情估计不少人都遇到过别人把一个抓包文件丢过来你第一反应是这玩意儿怎么打开打开之后又该看什么。HAR 文件本质上是一份 HTTP 请求的黑匣子记录浏览器、抓包工具都能生成但生成容易分析难。这篇文章就来说清楚 HAR 文件怎么打开、打开之后怎么入手分析以及面对别人丢过来的大文件时有哪些真正有用又少有人讲的实操技巧。1. 先搞明白 HAR 文件内部长什么样HAR 全称 HTTP Archive虽然扩展名是.har但它就是一个 JSON 格式的文本文件。这一点弄清楚了后面所有打开方式都好理解了你能打开 JSON你就能打开 HAR。1.1 从顶层结构看它记录了什么把 HAR 文件用任意文本编辑器打开你会看到一层层的嵌套结构。最顶层是一个log对象里面固定有versionHAR 规范的版本号和creator哪个工具生成的。但真正关键的是entries数组里面装着每一个 HTTP 请求的完整记录。每个 entry你可以理解成一整个 HTTP 事务的快照包含request请求方法、URL、请求头、查询参数、Cookie以及 POST 的表单数据或 JSON 请求体。response响应状态码、响应头、响应体内容、重定向地址等。timing请求各阶段花费的时间包括 DNS 解析、TCP 建连、等待响应TTFB、内容下载等。startedDateTime/time请求发起时间和总耗时。cache浏览器缓存命中情况。我用一个类比来帮你记住HAR 就像店铺的安防录像加收银小票二合一每一笔交易的来龙去脉、花了多少时间、结果如何都在里面而且是格式化归档好的。1.2 一个条目的核心字段值多少钱举个最朴素的接口排查场景。以下是一个 entry 里 response 部分的典型内容{ response: { status: 500, statusText: Internal Server Error, headers: [ { name: Content-Type, value: application/json; charsetutf-8 } ], content: { size: 183, mimeType: application/json, text: {\code\:50001,\msg\:\订单服务超时\,\data\:null} }, redirectURL: }, timing: { blocked: 0.5, dns: 1.2, connect: 15.8, send: 0.3, wait: 3210.4, receive: 2.1 } }status告诉你业务结果content.text里往往直接躺着服务端返回的错误信息——很多有用信息根本不用猜HAR 里早就存好了。timing.wait是等待服务器响应的时间如果这一项高达好几秒那大概率问题出在服务端处理上而不是网络传输。注意content.text这字段并不是所有工具导出 HAR 时都会带。Chrome 导出时只要响应体还能从浏览器内存里拿到就会带上去但你从 Charles、Fiddler 这类抓包工具导出的 HAR响应体是否完整取决于抓包时有没有配置完整保存响应。所以拿到别人发来的文件第一件事应该是检查content.text有没有内容。2. 打开 HAR 文件的三类方式与选型逻辑打开方式没有唯一答案取决于你现在手头有什么工具、要干什么事。我这里按看界面、看结构、看原始数据三个层次分别说。2.1 浏览器 Network 面板直接拖入这应该是日常最推荐的方式。Chrome DevTools 的 Network 面板有一个导入/导出按钮位置在网络面板的工具栏左侧点开后选择Import找到你的.har文件加载。更快的办法是直接把.har文件拖进 Network 面板空白区域Chrome 会自动识别并加载。导入之后整个文件里的所有 HTTP 请求会被当作一次页面加载记录来展示你能看到请求列表、耗时瀑布图、请求头和响应体体验和自己在 DevTools 里抓包几乎一模一样。Firefox 的开发者工具箱 Network 面板也支持导入 HAR操作逻辑类似。这种方式最适合分析别人发来的页面访问记录尤其是要看请求顺序、并行关系、资源加载瀑布图时。2.2 在线解析器与本地可视化工具网上有一些 HAR 在线分析工具比如 Google 官方的 HAR Analyzer把文件上传之后会自动生成一个可交互的网页面板可以按域名、MIME 类型、状态码筛选请求还能自动汇总每个域名的耗时分布。如果你的环境里不方便打开浏览器 DevTools 的导入功能在线工具是个不错的备选。但这里我特别提醒一句HAR 里通常包含 Cookie、Authorization 请求头、请求体里的用户隐私数据上传到任何第三方网站之前务必脱敏或确认数据不敏感。我自己处理客户环境的数据时基本不使用在线工具除非文件是我自己刚生成的、确定不含敏感字段。本地可视化工具也不多主要是许愿意自己搭个静态页面的团队可以用 har-viewer 之类的开源项目在本地跑起来但本质上和浏览器导入差别不大。多数场景用不上。2.3 用编辑器看原始 JSON既然 HAR 是 JSON那 VS Code、Sublime、Notepad 都可以直接打开。但大文件比如超过 50MB直接拖进普通编辑器大概率会卡死这时候有两个更好用的办法VS Code 自带对大 JSON 的格式化与折叠支持打开后可以折叠所有字段再逐层展开体验比记事本强太多。命令行用jq做筛选例如只想看所有请求的 URL 和状态码cat chrome.har | jq .log.entries[] | {url: .request.url, status: .response.status}用编辑器打开的方式最适合别人发来的文件很大、你用浏览器导入也卡同时又不想写完整脚本只想快速瞄一眼某个具体字段时。3. 从 HAR 里定位接口故障的完整实战链路工具只是入口分析才是重头戏。假设你拿到一份测试发来的 HAR要回答这页面/接口究竟哪里出了问题我会按下面这条链路来走每一步都能落地。3.1 第一关按状态码和耗时筛出可疑请求先把 HAR 导入 Chrome Network 面板点击Status列按状态码排序。4xx 和 5xx 的请求一眼就能揪出来。不过也别只看红字很多业务接口返回 HTTP 200但响应体里code字段是失败。这时候要遍历一遍请求名重点看XHR/Fetch类型的请求逐个点开看响应体。接着点Timing列或者在瀑布图上点击列头排序按总耗时排一下。耗时最高的那几个请求通常就是拖慢整个页面的元凶。3.2 第二关逐阶段拆解耗时瀑布图Chrome 导入 HAR 后点击任何一个请求在 Timing 标签页里能看到详细的耗时拆分。我之前排查过一个接口 3 秒才返回的问题拆开 timing 后发现wait只有 200ms真正的大头在stalled阻塞等待发起请求的时间和queueing请求排队时间。这背后往往意味着浏览器有连接数限制、前面某个大文件把连接占满了或者页面同时发出了大量请求造成拥塞。如果只看总耗时很容易误判成服务端慢再去服务端排查半天纯属浪费时间。不同 timing 字段排查方向参考耗时字段含义重点排查方向blocked请求等待发起前的时间浏览器并发限制、代理配置dnsDNS 解析时间DNS 服务器、本地 hostsconnectTCP 建连时间网络链路、机房负载send发送请求体时间上传带宽、请求体大小wait等待服务端响应时间服务端处理、网关超时receive接收响应体时间响应体大小、下载带宽3.3 第三关比对正常与异常两份 HAR这是一个非常好用但很多人忽略的方法。让测试在正常环境和故障环境各导出一份 HAR然后对两份文件做 diff。手动对比太费眼我一般写个简单脚本把两份 HAR 的请求清单method URL status 耗时分别提出来再按 URL 做 join看看差异import json def load_reqs(path): with open(path, r, encodingutf-8) as f: har json.load(f) return { e[request][url]: { status: e[response][status], time: round(e.get(time, 0), 2) } for e in har[log][entries] } a load_reqs(正常.har) b load_reqs(异常.har) for url in b: if url not in a: print(f异常环境新增请求: {url}) elif b[url][status] ! a[url][status]: print(f状态码变化: {a[url][status]} - {b[url][status]} | {url}) elif b[url][time] - a[url][time] 500: print(f耗时增加 {b[url][time] - a[url][time]}ms | {url})这个脚本的思路就是求差集 找突变输出结果往往直接指向出问题的那个接口或资源。3.4 第四关直接重放请求验证当前状态有时候看完 HAR 里的响应还不够因为那是某个时刻的快照你要确认现在这个问题还在不在。最直接的办法是把这个请求复制成 cURL 命令然后在终端重新跑一遍。Chrome Network 面板右键某个请求选择 Copy - Copy as cURL粘贴到终端执行就能看到当前真实的响应。如果已经安装了 Postman 或 Apifox也可以直接导入 HAR 文件每个请求会自动解析成可参数化的接口用例。但要注意导入后请求头里的 Cookie 是旧的很可能已经过期重放前需要手动更新认证信息。4. 处理别人 HAR 文件时绕不开的几个实际问题别人发来的文件从来不会像自己抓的那么顺手。文件巨大、字段缺失、数据敏感、时间对不上都是家常便饭。我把自己踩过的一些坑列出来提前避开能省很多时间。4.1 大文件卡死别硬开先过滤再导入Chrome 导入 100MB 以上的 HAR 文件内存占用会飙升甚至标签页崩溃。超过 200MB 的文件我基本不指望 DevTools 能正常打开。我的做法是先用脚本按域名或关键字把 entries 过滤到一个较小的子集再另存成一个瘦身版 HAR 去用浏览器看import json with open(large.har, r, encodingutf-8) as f: har json.load(f) # 只保留指定域名的请求 keep_domains [api.example.com] entries har[log][entries] filtered [ e for e in entries if any(d in e[request][url] for d in keep_domains) ] har[log][entries] filtered with open(large_filtered.har, w, encodingutf-8) as f: json.dump(har, f, ensure_asciiFalse)瘦身之后的文件可能是原来的 1/10再导入浏览器就不会卡了。如果只是需要统计信息那完全不用导入浏览器写脚本直接解析 JSON 更靠谱。4.2 隐私数据与合规风险拿到文件先做一次脱敏这个问题要在分析之前就处理而不是分析之后。HAR 里的敏感信息主要有三处请求头里的Authorization、Cookie、X-Token等认证信息请求体里的用户名、手机号、密码、身份证号等业务数据URL 查询参数里可能带的 session、token。给第三方看之前至少要把认证字段打码。脱敏脚本很简单遍历 entries 里每个 request 的 headers匹配到敏感 header name 就替换掉。响应体里的业务数据没法全自动处理但至少要有意识地不对外传播原始文件。这不是小题大做很多公司数据泄露就是从一个没删干净的 HAR 文件开始的。4.3 时间字段与服务器时区问题HAR 里的startedDateTime是 ISO 8601 格式带时区偏移。Chrome 导出的是本地时间加时区偏移比如2025-01-15T10:30:00.12308:00但如果你用脚本去解析时不注意时区直接用 UTC 字符串对比很容易出现请求时间对不上的错觉。我建议所有时间分析统一转成毫秒时间戳来处理from datetime import datetime dt datetime.fromisoformat(2025-01-15T10:30:00.12308:00) ts_ms int(dt.timestamp() * 1000)这样无论 HAR 来自哪个时区、哪个工具都能放在同一把时间尺上横向比较。4.4 HAR 的边界什么情况它无能为力HAR 不是网卡抓包它本质上是浏览器应用层行为记录的导出。所以有几类问题在 HAR 里是看不出来的TCP 重传、丢包这类网络层问题要用 Wireshark 的 pcap 文件。WebSocket 的帧级通信HAR 里只有握手请求后续帧不会记录。HTTP/2 多路复用的底层帧调度HAR 也体现不了。服务端内部调用链、数据库查询耗时HAR 完全无法覆盖。如果别人以为发一个 HAR 就能让你把所有问题查到底你要心里清楚它的分析边界在哪别在 HAR 上死磕。5. 把 HAR 变成可复用的分析资产脚本二次加工分析完一份 HAR 只解决当下一个问题。我自己的习惯是遇到有价值的 HAR尤其那些能复现线上问题的会把它转成几种更友好的格式方便后续复盘和建立基线。5.1 用 Python 汇总成接口清单把 HAR 转成一张接口清单表包含每个请求的 URL、域名、状态码、耗时、响应大小分析接口性能时特别好用import json, csv def har_to_csv(har_path, csv_path): with open(har_path, r, encodingutf-8) as f: har json.load(f) with open(csv_path, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([URL, 域名, 方法, 状态码, 总耗时ms, 响应大小B, TTFB ms]) for e in har[log][entries]: req e[request] res e[response] t e.get(timing, {}) writer.writerow([ req[url], req[url].split(/)[2], req[method], res[status], round(e.get(time, 0), 2), res.get(bodySize, 0), round(t.get(wait, 0), 2) ]) har_to_csv(session.har, interfaces.csv)生成的 CSV 拖进 Excel 或导入数据库过滤排序就非常顺手了。5.2 统计耗时 Top 与失败率想知道这个页面总体健康状况看平均数和聚合没有意义要看 Tail Latency尾部延迟。我通常把耗时数据画一个简单的分布直方图看看 P50、P95、P99 分别是多少import json, statistics def pct(sorted_data, p): k (len(sorted_data) - 1) * p import math f math.floor(k) c math.ceil(k) if f c: return sorted_data[int(k)] return sorted_data[f] (sorted_data[c] - sorted_data[f]) * (k - f) with open(session.har, r, encodingutf-8) as f: har json.load(f) api_times sorted(e[time] for e in har[log][entries] if api in e[request][url] and e[response][status] 400) print(f请求数: {len(api_times)}) print(fP50: {pct(api_times, 0.5):.0f}ms) print(fP95: {pct(api_times, 0.95):.0f}ms) print(fP99: {pct(api_times, 0.99):.0f}ms)这些数据比平均耗时 600ms有价值得多。你一看 P95 和 P50 差距很大就知道有些请求明显掉队了再顺着 URL 去查是什么接口受什么因素影响。5.3 自动隐藏敏感字段的导出脚本如果你经常需要转发 HAR 给外部协作者或者贴到工单里一个永远能用的脱敏脚本是刚需。核心逻辑很简单遍历所有 header 和 URL 参数把需要保护的 key 对应的 value 替换成固定占位符然后导出一个可对外版的 HAR。import json, copy SENSITIVE_HEADERS {authorization, cookie, set-cookie, token, x-token} def sanitize_har(src_path, dst_path): with open(src_path, r, encodingutf-8) as f: har json.load(f) for e in har[log][entries]: for h in e[request].get(headers, []): if h[name].lower() in SENSITIVE_HEADERS: h[value] *** for h in e[response].get(headers, []): if h[name].lower() in SENSITIVE_HEADERS: h[value] *** query e[request].get(queryString, []) for q in query: if q[name].lower() in (token, sign, sessionid): q[value] *** with open(dst_path, w, encodingutf-8) as f: json.dump(har, f, ensure_asciiFalse, indent2) sanitize_har(source.har, sanitized.har)这个脚本虽然粗糙但挡掉了最常见的泄密路径。日常够用了真要很严格再做深度清洗。我自己处理 HAR 文件最多的场景其实是线上接口偶发超时现场复现困难。测试能做的就是把故障瞬间的 HAR 导出来你拿着这一份快照一步步看耗时分布、看状态码分布、看参数携带情况往往能找到比日志更直接的线索。那一次 3 秒超时问题的根因最后就是通过对比正常和异常 HAR 的timing.wait差异锁定了一个网关超时阈值配置错误。再告诉你一个小技巧拿到一个陌生的 HAR 文件别急着分析先看一眼creator字段里的工具名和版本号。不同工具导出的 HAR 在字段完整度上差别很大心里有数之后再看内容能少走不少弯路。分析完如果要长期保存建议统一转成 CSV 或导入数据库归档比囤一堆.har文件实用得多。
返回列表