自推出程序员探案系列第一篇(程序员探案之"被吃掉"的串口数据)以来,引起了一些程序员探长的共鸣,也被CSDN转载。这些都是我继续写下去的动力,谢谢大家。
这不,最近探长又破了个棘手的案子。咳咳,探长要开始还原案件始终,请耐心看下文:
直击案发现场
现场图片可见,在放入redis数据时停顿了近25秒,这是什么情况,正常情况应该是下面这样的才对啊
仔细理理现场
这是用python和redis实现的一个简单消息队列,通过redis-py的驱动用rpush和lpop命令来实现消息的入队和出队,还有一个特征是这是一个新的嵌入式开发平台
案情分析
一号疑犯"redis-server"
redis-server作为主要服务提供商,自然嫌疑最大。
但排查完redis-server的各项配置,连接数、阻塞数等等指标也一切正常,没有发现任何直接证据指向它。
另外,同样的代码在另一个开发平台上远程连接"案发"现场平台的redis-server也很正常,这也旁证redis-server是清白的,暂时解除嫌疑。
二号疑犯"redis-py"
redis-py作为服务的中间商,承上启下,嫌疑也不小。
redis-py作为第三方库,查看版本,安装路径,都正常。
检索github的issue和相关案例,也未发现类似“犯罪记录”。
另外,它也有旁证。
这样,redis-py的嫌疑也解除了。
重大嫌疑人陆续被排除嫌疑,顿时又变得扑朔迷离,再次陷于僵局
摸底排查,揪出元凶
静一静,重新捋一捋手头的所有线索,功夫不负有心人,发现了些蛛丝马迹。
在redis-py源码中,创建socket连接时,发现getaddrinfo调用
打点定位,发现就是在这里阻塞耗时。
这下,"真凶"水落石出。
但疑团还没有消散,为什么其他环境正常呢?这个是socket内置模块,正常不会有这么明显的漏洞,那就是说...还有"幕后大佬"。
先了解一下getaddrinfo的作用和机制
getaddrinfo 的作用是将主机名和服务名转化为套接字地址结构的,通常情况下会优化读取/etc/hosts中的内容,再通过DNS域名服务进行通信
再通过一个简单的测试,具体看看
到此,“元凶”现身,/etc/hosts文件内容缺失
结案总结
"案件"最终告破,当然少不了程序员探长的英明神武,不过也暴露出程序员的一些问题,自己的坑还得自己填。
记录几点,以供参考:
1 对于新开发环境,特别是嵌入式环境,系统镜像里一定要保证好相关配置文件的完整性(这里就是缺少/etc/hosts)
2 /etc/nsswitch这个文件也会影响域名的解析,默认配置 hosts: files dns,这样会先读取/etc/hosts中的数据
3 对于本地服务的能不用localhost就不用,用127.0.0.1更快