0%

Py-spy解决Python程序Hang住问题

背景

​ 已经集成的接口自动化测试 Job 在周期性定时运行的时候,会很小概率出现一直卡在那里,原本应该3min就执行完成的任务,偶尔过了半个小时还没结束。(( ̄3 ̄)直觉告诉我这个地方肯定有问题。。。

​ 但由于复现的概率较小,一个月可能出现一次,所以开始并没有什么太大的线索(仅靠一些猜测并不切实际)。

​ 终于!!!在某一个阳光明媚的大好日子,它重现了

排查过程

  1. 赶紧先登录到服务器上看看进程情况,发现此时存在脚本发起的2个 Worker CPU占用100%(由于用的 Pytest + Pytest-xdist 分布式插件执行用例),当时第一反应是死循环了??

    process_hang_1.png
  2. 通过perfps或者 pstack 打印对应的pid, 看到的结果并没有什么太大用,反而误导我以为是代码里面的一个文件锁导致该问题

    process_hang_2.png
  3. 网上查询了一通后,发现一个神奇的工具一一 py-spy (更多使用方法见 官网

    安装后使用命令 :选定一个异常的进程,执行命令: py-spy top --pid 19785 打印结果如下,很明显看出来当前Cpu都卡在 check_retry_status 方法上面。

    process_hang_3.png
  4. 查看该代码,发现该方法中存在一个while循环,并且很凑巧的是。。。╮(╯3╰)╭ 里面没有兜底

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 具体代码如下,过于相信传进来的 retry_flag 一定是1/2, 如果出现不是这两个值的时候,此时这个方法则进入了死循环。。。
    def check_retry_status(cls, uid, atk, order_id, retry_flag, devuuid):
    max_count = 5
    while max_count > 0:
    if retry_flag == 2:
    retry_flag = functionA(xxx, ...)
    max_count -= 1
    elif retry_flag == 1:
    return

    raise Exception("验证充值订单失败")
  5. 到这个地方,就很明显定位到了问题,在此处加上兜底并且加上对应日志记录functionA(第三方依赖)到底返回的是什么。( 因为首次传入的 retry_flag 也是来自于functionA)

总结

​ 写代码要谨慎。。。特别是结果来自第三方依赖的时候。。。一定要进行兜底!!!

​ (emm… 兜一下总比不兜强)

------------- 本 文 结 束 感 谢 您 的 阅 读 -------------