这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
一、问题描述
在某一次进行API接口测试的时候,发现客户端登陆失败,如下图:
二、问题排查
迷雾探索(自测问题定位)
抓包检测
这里我使用 Fiddler 进行抓包调试:
将客户端的请求复制到Apifox发送post测试:
返回正常,排除服务端本身的问题(这里埋下伏笔)
代理检查
由于本地测试没有问题,但是客户端和服务端之间有一层代理,我们据欸的那个从这里开始排查
我们使用了 tcpdump 这个工具在Ubuntu虚拟机拦截客户端发出的Post请求
TCPDump是一种在Unix/Linux系统中使用的网络抓包工具,可以捕获网络上的数据包并将其分析、存储或显示出来。它可以在命令行上运行,以捕获并显示传输到和从网络接口的流量。
TCPDump最常用于网络故障排除和分析,例如查看网络流量、检测网络瓶颈、检测和分析网络攻击、监视网络应用程序和协议等。
下面是一些常用的TCPDump命令:
# 捕获所有流经指定接口的数据包
sudo tcpdump -i eth0
# 按协议类型过滤捕获的数据包
sudo tcpdump -i eth0 icmp # 捕获ICMP协议数据包
sudo tcpdump -i eth0 tcp port 80 # 捕获TCP协议80端口数据包
# 将捕获的数据包保存到文件中
sudo tcpdump -i eth0 -w capture.pcap
# 从文件中读取和分析数据包
sudo tcpdump -r capture.pcap
# 指定捕获数据包的数量
sudo tcpdump -i eth0 -c 10 # 捕获10个数据包
在这次问题的排查中,我们使用了以下命令:
# 使用tcpdump抓取客户端发送的GET请求
tcpdump -i enp0s8 -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
# 使用tcpdump抓取客户端发送的POST请求
$ tcpdump -i enp0s8 -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504F5354'
我们首先尝试抓取客户端的GET请求,成功抓取,并且服务端有响应,确定客户端和服务端是连通的 接下来我们又尝试抓取客户端发送POST请求,这次tcpdump没有抓取到POST请求,服务端也没有日志输出
这就很奇怪了,一般来说即使服务端拦截了接口,应该也会有一个ERROR日志的
为了复现问题,也为了排查问题是否和代理和服务器的防火墙策略等有关,因为项目使用的是hertz框架,我在网上找了一个hertz的实践来模拟客户端的post行为:
可以看到,即使使用了代理,post结果是没问题的,服务端也抓到了相应的post请求:
这就很奇怪了,难道还是服务端的问题?但我明明最开始已经排查了服务端的问题了呀
第二步:百家争鸣(讨论可能的问题)
为了排查问题,我召集了小组队员来进行问题的排查:
跨域问题
有个小伙伴提到了可能是跨域请求的问题,但这个不是浏览器一般来说没有跨域问题,但为了验证小伙伴的说法我还是在本地用模拟器安装了demo APP进行测试,结果仍然是请求失败并且服务端无日志,在随后的讨论中我们也没有得到有效的错误信息
SSL证书问题
由于项目适配了HTTPS,所以小伙伴提出可能是因为服务端不信任客户端发出的SSL请求,但后来重新检查了客户端的抓包记录,发现客户端发送的是HTTP请求,所以排除了这个问题
事情到这里似乎陷入了停滞
第三步:拨云见日(解决BUG)
还记得前文埋下的伏笔吗?接下来就是见证奇迹的时刻了
在我们还在思考到底哪里出问题的时候,队友小崔仔细对比了抓包得到的url、我们自己的路由和demo客户端文档的url,并且重新检查了客户端的抓包记录,发现客户端发送的请求进行了一次307跳转,login方法后面多了一个 "/" ,导致客户端发送的post请求跳转到了一个不存在的路由,服务端自然也就无法处理了。
三、问题分析
原因
整个故障的原因,是业务请求的内容触发了客户端的某个机制将请求307重定向到了一个不存在的路由地址。那么问题来了,什么是307跳转?
307跳转
我们先来看看什么是307跳转
307跳转定义
307是HTTP协议中的一个状态码,它表示请求的资源已经被临时移动到另一个URL,但是客户端应该继续使用原始URL进行请求。307跳转与302跳转类似,不同之处在于307跳转要求客户端保持请求方法不变。
除了307跳转,HTTP状态码还有很多其他类型,下面是一些常见的状态码及其含义:
200 OK:请求成功,并返回请求的资源。
301 Moved Permanently:请求的资源已经永久移动到新的URL,客户端应该使用新的URL进行请求。
302 Found:请求的资源已经临时移动到新的URL,客户端应该使用新的URL进行请求。
304 Not Modified:请求的资源未被修改,服务器返回缓存的资源,客户端可以使用缓存的资源。
400 Bad Request:请求的语法错误,服务器无法理解。
401 Unauthorized:请求需要身份验证。
403 Forbidden:服务器拒绝请求。
404 Not Found:请求的资源不存在。
500 Internal Server Error:服务器遇到了错误,无法完成请求。
307跳转的使用场景
应用需要307跳转是因为在一些特定的场景下,服务器需要对客户端进行临时重定向。比如,当一个网站需要进行https协议的强制重定向时,就可以使用307跳转。在这种情况下,服务器可以将原始URL重定向到https协议的URL,而不需要修改客户端的请求方法。这样可以保持请求的安全性和正确性。
四、问题解决
既然问题找到了,那么解决问题就有眉目了,由于是url体哦啊转导致的问题,我们给对应的路由加上 "/" 即可
五、问题复盘
回看问题的解决历程,最耗费时间的步骤其实是问题的定位,而问题的定位涉及到对整个路由的了解和对网络知识、Linux基础用法的掌握,最后问题的解决也是依赖于在细节处发现问题的能力。
确定问题边界
由于客户端的请求得不到响应,我们首先怀疑是服务端出了问题,但在本地测试API无误后我们排除了API逻辑的问题,缩小了问题边界,以来我们所掌握的网络知识和Linux知识进行进一步的排查。
定位错误
由于已经排除了服务端的问题,可能引发问题的因素已经有迹可循了,我们需要的一步步是耐心排查,我们按照下面几个模块进行排查:
- 跨域
- HTTPS协议
- 路由
反思
这次问题的产生,是因为我们没有严格遵循文档进行开发,并且在'code review'
环节没有发现问题导致的事故。
这样的事故发生后,我们认真反思了我们的开发流程和团队协作方式,以避免类似问题再次发生。
首先,我们需要对文档的重要性有更清晰的认识。文档是我们开发过程中必不可少的一部分,它可以帮助我们更好地理解需求、规范代码开发、提高代码可读性等等。测试用的客户端是青训营直接提供的,并且我们没有源码。在没有完全熟悉客户端接口的情况下进行开发是我们犯下的一个很严重的错误。
其次,我们需要重视code review
环节。在代码审查环节,需要认真检查每一行代码,确保代码符合规范和要求。同时,要求我们自行测试代码,尽可能地发现潜在的问题。对于发现的问题,及时进行修正和反馈,并确保问题被完全解决。
此外,我们也应该在开发过程中加强团队协作和沟通。开发人员之间需要相互理解、相互配合,共同完成项目开发。同时,也需要及时沟通,发现问题及时解决,确保项目按时按质完成。
最后,我们也需要重视项目的测试环节。在测试环节,需要对代码进行全面的测试,确保代码的质量和稳定性。同时,也需要注意测试数据的准确性和完备性,避免漏测和误测。
最后
总而言之,我们首先缩小了问题的范围,随后在剩余的可能里进行一步步排查,最终解决了问题。我们深刻烦死了我们的开发流程与协作,在接下来的开发中我们会更加注意。