时间线

  1. 大约在2020年10月,内网测试服服务端更新,发现进程A重启后,与其他进程之间的心跳协议不通,不能正常的提供服务。重启后,就正常了。
  2. 这个情况持续了很长时间。只在重启时才会出现,且发生概率很低,一个月一次的概率。所以这个问题就被搁置了。
  3. 现网部署后,发现更新时,也出现了这个情况,但是由于重启就可以解决,这个问题被归属为:重要但不紧急的范畴。
  4. 大约2021年5月,花了一些时间尝试解决这个问题。由于没有找到重现的步骤,所以等待出现问题时观察现场。后面有一次出现了,进行排查:

看日志,没有异常。重点看网络。

netstat发现进程A与进程B的tcp是连接的。

tcpdump发现进程A发出的心跳数据,进程B的tcp层接收数据了,但是进程B的业务层没有收到数据。由于A与B之间的心跳数据没有闭环,所以进程B认为进程A不存在,故进程A虽然启动成功了,但是没能正常对外提供服务。

由于内网不能一直保存现场,需要对外提供服务,重启了进程A,问题的原因还是没有找到。

  1. 2021年12月,做了一个一键编译发布的工具,便于服务端更新,提高工作效率。发现使用一键发布后,这个问题又出现了。经过多次重试,发现使用一键发布,这个问题必现。经过排查,排除了工具本身的问题。

进程B是listen端,进程A是connect端,A主动连B。底层通信组件是ZMQ。按照ZMQ设计,底层是会自动重连的。

初步怀疑是ZMQ的bug,于是把ZMQ升级到最新版本,发现问题仍然存在,确定是业务代码有问题。

通过tcpdump,netstat等工具,发现现象和之前是一样的:进程A发出的心跳数据,进程B的tcp层接收数据了,但是进程B的业务层没有收到数据。

  1. 这个问题确定是必现问题,就好解决了,继续推进。通过多次重试,发现了一个规律:

进程B是listen端,进程A是connect端,A主动连B。只要进程B重启后,进程A在大约3秒内去连B,就会出现这个问题。如果是3秒后,A再连B,就不会出现这个问题。

期间也怀疑代码多线程的问题,通过测试也排除了。

  1. 有了这个3秒的规律,于是看代码,看哪些地方会和这个3有关系。果然代码有一处跟这个相关:



    把3改为5、10来测试,发现问题和这个数字强相关。

    于是把这行代码删除。

  2. 修改代码后,重新发布,多次测试后,结论:问题解决。原因是什么呢?后面讲。

问题如何发现的

因为有可视化监控。如果没有可视化监控,这个问题是很难发现的。

这个图体现的是进程之间的心跳信息。

绿色:正常

红色:失活,失活了多长时间,可以倒推出最后一次心跳正常的时间。

问题产生原因

  1. 最开始之所以偶现,是因为更新时,手速有快慢,快的时候就撞到了这个问题。
  2. 开发了一键发布工具,重启进程就很快,故而偶现问题就找到了必现方法。
  3. 代码上的bug:执行zmq_bind() 后,套接字进入静音状态,在router模式下是丢弃数据的。需要bind后,立即调用recv,跳过静音阶段。删除代码中的sleep,问题即解决。

参考:

zmq_connect(3) - 0MQ Api

ZeroMQ史上最全的知识总结(一):常见的通讯模式

  1. 继续分析。执行zmq_bind() 后,套接字进入静音状态,sleep结束后调用recv,结束了静音状态,后续应该可以正常接收消息的,但是并没有。

在连接建立的过程中,当TCP三次握手后,StreamEngine会再一次和另一端握手,这是ZMQ应用层自己的握手协议,握手成功后,就进行msg的传递了。

原因是:静音状态下,router丢弃了dealer的握手协议。后面的数据也就不接收了。

正常的流程:tcp三次握手成功--zmq层握手成功--业务层心跳激活--业务层数据传递。

复盘沉淀

  • 得益于可视化,对发现问题提供了很大的帮助。
  • 找bug类似于找规律,多试试有好处。
  • 在线文档持续跟踪,即使时间跨度很长,也能接续起来。
  • 遇到问题时,第一时间去查看官方文档。

复盘报告:心跳数据丢失,从发现到解决历经一年多的bug的更多相关文章

  1. Apache coredump 问题发现与解决记录

    目录 Apache coredump 问题发现与解决记录 背景 发现问题 解决问题 方法 1 方法 2 总结 Linux 程序编译链接动态库版本问题 ldd 命令 动态库的编译和 soname 线上 ...

  2. 我是怎么发现并解决项目页面渲染效率问题的(IE调试工具探查器的使用)

    #我是怎么发现并解决项目页面渲染效率问题的(IE调试工具探查器的使用) ##背景 之前的项目中,有很多的登记页面,一般都有100-200甚至更加多的字段,而且还涉及到字典.日期及其他效果的显示,载入时 ...

  3. 【Unity游戏开发】记一次解决 LuaFunction has been disposed 的bug的过程

    一.引子 RT,本篇博客记录的是马三的一次解决 LuaFunction has been disposed 的bug的全过程,事情还要从马三的自研框架 ColaFrameWork 说起.最近,马三在业 ...

  4. 解决JavaScript浮点数(小数) 运算出现Bug的方法

    解决JS浮点数(小数) 运算出现Bug的方法例如37.2 * 5.5 = 206.08 就直接用JS算了一个结果为: 204.60000000000002 怎么会这样, 两个只有一位小数的数字相乘, ...

  5. 全志tina v3.0系统编译时的时间错误的解决(全志SDK的维护BUG)

    全志tina v3.0系统编译时的时间错误的解决(全志SDK的维护BUG) 2018/6/13 15:52 版本:V1.0 开发板:SC3817R SDK:tina v3.0 1.01原始编译全志r1 ...

  6. 服务器被疑似挖矿程序植入,发现以及解决过程(建议所有使用sonatype/nexus3的用户清查一下)

    此次服务器被植入挖矿程序发现起来较为巧合,首先是上周三开始,我通过sonatype/nexus3搭建的仓库间歇性崩溃,但是每次重新start一下也能直接使用所以没有彻底清查,去docker logs里 ...

  7. 快速发现并解决maven依赖传递冲突

    此文已由作者翟曜授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 最近在测试过程中,遇到了几次maven传递依赖冲突的问题,所以记录下解决的过程,遇到类似问题供参照. 问题现象 ...

  8. 一个有趣的 ”Validation of viewstate MAC failed” 错误的发现和解决

    在ASP.NET里面,View State使用较为广泛.它作为一个隐藏字段,可以帮助服务端”记住“客户端的改变,这样客户端 收到服务器对PostBack的响应后,仍然可以展现在PostBack之前设定 ...

  9. 数据处理之以OLEDB方式读取Excel数据丢失的原因及解决方法

    1.引言 在应用程序的设计中,经常需要读取Excel数据或将Excel数据导入转换到其他数据载体中,C#读取Excel的方式有两种,一种是通过OLEDB方式读取,另一种为通过COM组件方式读取.近段时 ...

随机推荐

  1. 任务日历关联(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 有时候吧,一件大事是由N件小事组成的,而这N件小事当中,不是每件事都可以在周末停下来的,当然也不是所有的事都必须在周末完成 ...

  2. 嵌入式实验一:LED灯点亮

    实验一:LED灯程序 一. 实验环境 开发机环境 ​ 操作系统:ubuntu 12.04 ​ 交叉编译环境:arm-linux-gcc 4.3.2 ​ 6410板子内核源码:linux-3.0.1 目 ...

  3. java 数据类型:集合接口Collection之List~ArrayList:remove移除;replaceAll改变原有值;sort排序;迭代器listIterator();

    什么是List集合: 特点: 元素有序可重复的集合. 集合中每个元素都有其对应的顺序索引. List集合默认按元素的添加顺序设置元素的索引,索引从0开始.   List接口的常用方法: List可以使 ...

  4. 三、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-配置项目并实现IM登录

    项目文章索引 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展面板的 ...

  5. JAVA使用多线程进行数据处理

    import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.Log ...

  6. 创建Ubuntu server 服务器git项目

    服务器端: mkdir project.git cd project.git git init --bare cd .. p.p1 { margin: 0; font: 11px Menlo; col ...

  7. 【Android开发】微信精选,文章资讯类App开发记录总结

    缘起 微信精选的App开发来源是在聚合数据上看到了有免费的微信精选的数据接口,无限调用.相对于其他的诸如违章查询,医药查询,NBA赛事等等,我感觉还是微信文章精选这个数据接口离我最近,所以想着拿着个数 ...

  8. 从头造轮子:python3 asyncio 之 run(2)

    前言 书接上文,本文造第二个轮子,也是asyncio包里面非常常用的一个函数run 一.知识准备 ● 相对于run_until_complete,改动并不大,就是将入口函数重新封装了一下,基础知识主要 ...

  9. 【python】PyQt5 QAction 添加点击事件

    def test(): #your function ui.yourQActionName.triggered.connect(lambda:test()) #添加lambda: 就不报错了

  10. C++输出控制小数点后位数的方法

    以C++输出小数点两位数为例 setprecision(n)使用方法总结 首先要记住写头文件 #include <iomanip> //不要忘了头文件 以下是控制小数位数的三种写法 //t ...