前言
欢送关注同名公众号《熊的猫》,文章会同步更新,也可疾速退出前端交换群!
周一一大早就接到了测试的 Bug 反馈,其实也是用户的反馈:
【测试】
:挪动端偶然会呈现 操作异样,请刷新重试!
的提醒,然而从新刷新又好了,用户说好不容易填了数据一刷新就徒劳功夫了,而且在测试环境也能复现,不过目前不是那么好复现了,这是之前复现时的截图,你先看看
【低微前端】
:()好,我看看!毕竟没得选
这是之前()接手的一个 React 老我的项目,其中的 申请 是通过自定义封装 XMLHttpRequest 的形式来实现的,没有应用 React CLI 的形式,而是本人基于 webpack 构建工具搭建的一个我的项目。被迫
【忠告 】看待老我的项目外围就是要足够尊重,千万不要吐槽它(
),老我的项目很小气的
一不小心就能给你 惊喜 ,还可能是 有限的惊喜!!!
大抵的复现步骤,如下:
就是在 A 页面 和 B 页面 间来回进行 上一步 、 下一步 操作,而后再就会呈现申请异样的状况。
有了以上信息,咱们就能够开始 BUG 的摸索之路 ,上面就逐渐进行剖析, 欢送一起探讨!
无需入侵代码的调试形式
为了更好的复现问题和调试 H5 挪动端 ,咱们通常会应用一些 挪动网页前端开发工具 ,例如 vconsole
,然而这意味着咱们还得去批改 代码内容 和 我的项目依赖 ,而且 vconsole
的交互也不太敌对(),那么除此之外还有没有什么其余方法能够实现 无入侵的便捷调试 呢? 懂的都懂
那天然是有的了,最罕用的就是 抓包(如 whistle,具体用法可见 Whistle 帮忙文档
)、Chrome DevTools 近程调试 两种形式,这里也简略介绍一下它们的应用形式。
Chrome DevTools 近程调试手机端
这里的近程调试手机端用 Android 零碎来演示,IOS 零碎步骤是统一的,只是会有些细节差别,自行查找一下即可。
连贯 手机 和 电脑
只须要应用 数据线 把 手机端 和 电脑端 连接起来,同时将手机中的 开发人员选项 中的 USB 调试 选项开启,通常插入 USB 数据线后都会自动弹出选项框来让你进行抉择 USB 调试 模式,但局部手机的弹窗中可能没有和 USB 调试 相干的内容,如下:
此时你能够点击手机 设置,而后应用其搜寻性能疾速搜寻定位,如下:
拜访 Chrome DevTools 近程调试界面
通过 chrome://inspect/#devices 拜访调试界面,而后你就能够应用 微信拜访指标页面 或者 手机浏览器拜访指标页面,接着期待调试界面加载到对应的信息后,就能够点击对应的 inspect 进行调试了,具体如下:
whistle 抓包
这里的抓包用 Android 零碎来演示,IOS 零碎步骤是统一的,只是会有些细节差别,自行查找一下即可。
一键装置 Whistle(Mac 和 Windows)
npm i -g whistle && w2 start --init
一行命令实现如下操作:
- 装置 Whistle
-
启动 Whistle
- 设置零碎代理,或不代理的白名单域名
- 装置根证书
拜访 Whistle 界面
启动胜利后,会在终端输入可拜访的地址,默认为如下三个:
挪动端装置 CA 证书
在 whistle 界面点击 HTTPS 选项,在手机端扫码并下载对应的 CA 证书,目标是在代理时可能失常拜访 https 协定头 的站点,而且当初的站点大多都是应用 https 协定,因而最好操作这一步。
手机端下载 CA 证书 结束后,就须要 受权装置 或 手动装置 ,能够在手机 设置 中疾速搜寻查找,而后按批示装置最近下载文件即可:
保障手机端和电脑端处于同一网段
也就是保障 手机端 连贯的 WIFI 要和 电脑端 正在应用的网络是统一的即可。
设置手机端网络代理
保障是同一网段后,就须要设置代理了:
-
找到以后连贯的 WIFI,长按而后批改网络
-
配置代理信息
- 服务器主机名 就是填写你的电脑的 IP,当胜利启动 Whistle 后输入的信息中会蕴含该内容,也可本人通过 ipconfig 命令查看
- 服务器端口 就是 Whistle 代理设置的端口,默认为 8899,如果你自定义端口保持一致即可
电脑端敞开防火墙
通过上述操作后,针对大部分人来讲可能还是无奈实现代理,因为 手机端的代理申请 被 电脑端的防火墙 拦挡了,此时就须要将防火墙临时敞开即可。
防火墙不容许敞开怎么办?
有些小伙伴的办公电脑可能为了平安不容许你 间接敞开防火墙 ,因而你要查看防火墙对应的 白名单端口 有哪些,接着将 本来的 Whistle 代理端口 切换到 合乎的端口 即可,没有的话能够本人增加 白名单端口。
值得注意的是,你切换了新的 Whistle 代理端口 后,你的 CA 证书 须要重新安装,最好是电脑端和手机端都重新安装,因为咱们要保障手机端在通过代理申请拜访代理服务时是可信赖的。
Http Status = 0
定位提醒起因
确定提醒起源
首先会提醒这个信息,那么得先确定这个提醒的起源,到底是后端返回的,还是前端自定义的,于是把 提醒文本 在我的项目中一搜寻就匹配到了,这显然是前端自定义的提醒:
剖析提醒起因
从代码逻辑上看很显著,就是当申请遇到谬误时,就会触发 error 事件,于是就会向外返回提醒文本并进行提醒,并且还会输入相应的相干信息。
配合日志定位
但值得注意的是:提醒内容蕴含了 xhr.status,再看看理论提醒内容:
再看看 监控日志,如下:
哦豁!哦豁!哦豁!
xhr.status = 0!!!
说实话我还是 第一次 遇到这种 状态码,这未免引起我的趣味,这不得持续理解理解!
Whistle 抓包 + Chrome DevTools 近程调试信息汇总
Whistle 抓包异样信息
Chrome DevTools 近程调试信息
联合以上抓取到的信息,咱们大抵失去相干的信息就是:
-
ERR\_CONTENT\_FAILED
- 这个谬误兴许你没有见过,但它在这可 不是一个无关联的谬误 ,因为响应头的中
content-type
值为application/json; charset=utf-8
,而异样接口显然返回了 不合乎编码格局的内容 ,因而产生了ERR_CONTENT_FAILED
谬误,即 属于同一个问题的不同体现 罢了
- 这个谬误兴许你没有见过,但它在这可 不是一个无关联的谬误 ,因为响应头的中
- XMLHttpRequest 申请异样触发
xhr.onerror
,但具体是什么异样未知,导致xhr.status = 0
什么场景下 Http Status = 0?
XMLHttpRequest.status
XMLHttpRequest.status
是 XMLHttpRequest 响应 中的一个 无符号短整型 的数字状态码,即其值就是对应的是规范的 HTTP status codes
,而 HTTP 响应状态码 又被归为以下五大类:
- 信息响应 (
100
–199
) - 胜利响应 (
200
–299
) - 重定向音讯 (
300
–399
) - 客户端谬误响应 (
400
–499
) - 服务端谬误响应 (
500
–599
)
看着没有问题啊,然而你有没有发现 状态码 0 不在这常见的五大类中!!!
XMLHttpRequest.status 为啥是 0?
实际上在两种状况下 XMLHttpRequest.status = 0
:
- 在 申请实现前,
status
的值为0
- 如果 XMLHttpRequest 出错,浏览器返回的
status
也为0
申请未实现
申请未实现时 XMLHttpRequest.status = 0
的状况间接看代码示例就晓得了,如下:
var xhr = new XMLHttpRequest();
console.log('UNSENT', xhr.status); // UNSENT(未发送)0
xhr.open('GET', '/server', true);
console.log('OPENED', xhr.status); // OPENED(已关上)0
xhr.onprogress = function () {console.log('LOADING', xhr.status); // LOADING(载入中)200
};
xhr.onload = function () {console.log('DONE', xhr.status); // DONE(实现)200
};
xhr.send(null);
但这显然不合乎当初的场景,因为它是在 xhr.onerror
曾经被触发。
XMLHttpRequest 出错
这里又会分为几种状况,其实在,具体如下:
-
申请停止,例如基于 xhrInstance.abort() 将申请停止
-
产生跨域
-
谬误的 URL 或 协定头
- 服务端提前结束响应,即未失常进行响应
- 网络断开,网络异样导致操作过程申请无奈失常发送等
- …
前端问题?后端问题?
置信不少前端同学看到诸如下图所示的 AJAX\_ERROR 时,就间接撒手不管了,交给对应的后端去看,失常来说的确没问题,然而总归要排查起因(),例如这里存留的疑难点是:不然凭啥说不是你的问题
- PC 和 Mobile 应用的同一个接口,PC 端各个 申请失常 ,只有 Mobile 端有 异样申请
- Mobile 端我的项目在 本地启动 (即开发环境和已部署的测试服务),而后以浏览器的形式拜访我的项目,并按 复现步骤 进行操作时是 失常申请 ,并不会有 异样申请 的状况呈现
排除前端嫌疑
为了证实不是前端的问题,咱们就须要 列举出可能由前端引发问题的状况,而归纳起来就是一种状况,那就是 ” 申请被终止发送 “:
-
手机端的 webview 存在 缓存 Ajax 申请 的机制,当 webview 检测到某个 Ajax 申请缓存可用时,会将新的申请 勾销 掉,此时 xhr.status = 0
- 这个是在查问材料过程中看到的一种可能,也好验证,那就是 革除缓存即可,但理论尝试后发现有效,证实不是此状况
-
手机端 网络异样,申请未能正确发送
- 这种状况也是不对的,因为除了用户在生产上出现异常申请外,咱们在 测试环境 也可能 复现
除此之外,认真看 Whistle 抓包 后果,异样申请的 result = 200,证实前端申请曾经失常收回,只是 后续响应过程呈现问题!
排除后端嫌疑
后端可能引发问题的状况,总结起来也是一种状况,那就是 ” 提前结束响应 “:
-
对接口申请频率有限度,例如频繁申请同一个接口时,多余申请可能就会被疏忽
- 而后端基本没有对申请做任何限度,并且再进行响应时,都会有 输入日志记录 ,在查找对应的日志后发现,对应的 异样申请并不在日志记录中,因而不是这种状况
-
响应过程呈现编码谬误,因为在抓包过程中咱们看到了,响应体 body 中是乱码的,不合乎响应头中
content-type: application/json; charset=utf-8
的编码格局- 基于测试环境的后端日志输入,发现不存在异样申请的状况,因为即使是编码谬误,也会有日志记录,因而也不是这种状况
以上状况阐明,当产生异样申请时,基本没有进入到后端的 Control 层,因而后端嫌疑也排除了。
交由两头链路进行排查
既然排除了 前端 / 后端 的嫌疑,那么剩下的可能就是 两头链路 的问题了,用户在手机端拜访指标站点时的 链路,如下:
- 手机 -> 网关 -> Nginx -> 应用服务 -> Nginx -> 网关 -> 手机
而目前看 应用服务 返回的是没有问题的,因而剩下的就交由 网关 和 运维 去进行排查了, 跨部门合作 会有一些工夫上不对等的问题(),后续具体起因会同步到此处。 懂的都懂
【后续
】排除运维嫌疑
上面是一段对话,这里只表白大抵的意思:
- 【
前端 A
】@运维 C
,下面的问题起初服务端加过日志看过,前端收到乱码,服务端返回的是失常的,还有服务本地部署,通过 whistle 将测试环境的接口转发到本地服务,也不会呈现乱码的状况 - 【
运维 C
】@前端 B
,一起帮忙看一看 - 【
前端 B
】上次和前端 A
一起看过了, 查到乱码的数据是服务端返回的, 其余的就没法查上来了,看样子挪动端的接口, 应该通过了 好几层的代理,所以当初想看下响应从服务端进去后,通过 ngnix 的时候是否失常 - 【
前端 A
】是的,当初的想法就是追随 响应门路 的返回一层一层去排查 - 【
运维 C
】挪动端测试环境是 iis,不是 ng 代理
总结一下,意思就是只有 生产环境 有 ng 代理, 测试环境 是没有 ng 代理 的,那当初的状况是: 生产环境可复现,测试环境可复现 ,因而不应该是 ng 代理 的问题, 那么只有一种可能:网关
。
静等 网关
排查中 ……
最初
欢送关注同名公众号《熊的猫》,文章会同步更新,也可疾速退出前端交换群!
以上就是本文的内容了,大抵通过:呈现问题 —> 复现问题 —> 排查 / 定位问题 —> 验证、排除嫌疑 —> 跨部门合作 等过程。
兴许你感觉一开始就间接交给 后端、网关、运维 去排查就好了,毕竟一通操作下来发现不是本人的问题,还节约了工夫等等。
然而要明确的是当咱们须要把某个问题交给 其余部门 进行排查 / 定位时,并不是咱们轻易说一句就能够了,因为大家都有很多事件要做,对你紧急的事件在其余部门中的优先级并不一定是最高的,此时还须要 部门和部门的负责人沟通协调,而在这之前最有必要的是先确保咱们这一方是真的不存在问题的,而后还得把你的信息同步给其余部门共事,不便他们更疾速的理解状况,更好、更快的实现相互合作和解决问题。