zmq 多路复用poll无法收包的问题(朴素的比对法解决问题)

来源:互联网 发布:锐捷冒充mac地址上网 编辑:程序博客网 时间:2024/05/17 12:05

     最近项目中使用ZMQ相关的库作为通讯组件,前期用得还算是比较顺利,API使用很简单而且易上手。用了是稳定的4.1.2版本C++版本。

     近期忽然发现,一个服务,使用多路复用zmq::poll无法收到包。问题表现:

     1)自己的机器上能正常使用poll收到包,没有问题。(自己的机器使用docker镜像环境在跑,代码在git上拉下来)

     2)同事的机器上的相同的代码下,无法收到poll包。(同事的机器,直接跑)

     比对之后,怀疑是使用ZMQ版本问题,于是在同事机器上也搭好了docker环境,再试,还是一样的结果。

     于是开始进行排查问题。

     排查过程(一系列莫名其妙的问题)

     A)进行抓包分析,发现ZMQ的发送端没有把数据包发出来,奇怪的是,改了接收端逻辑,不使用多路复用,使用阻塞式收包方式,居然能收到包。

     疑问:包发不出来,应该跟发送相关,跟接收是啥关系?

     B)GDB单步调试,发送的时候,发送端的状态总是返回非法,在最深处,发现是在一个getsockopt中返回一个EAGAIN错误。一脸茫然。

     C)加了monitor到里面去查看连接状态,只看到状态不正确,但定位不到具体原因。

     D)另外,再在出问题的机器上,使用之前写好的单独进程的DEMO代码进行测试,看能否使用IO多路复用方式进行收包。奇迹了,居然是可以的。

     表象结论:

     机器上这样跑是可以的,到了ZMQ使用到项目中,却无法进行zmq::poll方式收包。但却能使用recv阻塞式收包。这种问题,看似使用经验没办法进行解释,说不过去。

     

      排解办法:

      当两个现象放你面前的时候,一种是正常,一种是异常,当经验无法帮助你更快找到答案的情况下,记住,用最朴素的办法,比对的方法。两个不同的输入A(正常)和A1(异常),导致两个不同的输出B(正常)和B1(异常),那区别在于输入,你只需要将A1往A去演化。

      在你的演化过程中,必然有一个区别,会异致结果的不同。

      在这个思路的指导下,我把项目中的代码,一点点的修改,慢慢趋近于DEMO代码。最后代码也一样的情况下,还是结果异常。最后发现makefile不同,那就把makefile也一点点修改,改成一样。最后在最小的范围内找出了区别,那就是makefile中,多了一个编绎选项-I导致结果不同。 忽然眼前一亮,进到这个-I选项带着的路径上,顿时菊花一紧,发现一个zmq.h文件躺在那里,千万个草泥马奔过,貌似找到了祸根。是

       结果分析:其他同事,在库里面提了另一个zmq.h版本上去,导致编绎的时候,有两个zmq.h版本在项目里面。有时调试的时候,代码跳来跳去的原因也因此得以解释。

       避免:编绎的结果使用静态库,调试的时候,相关信息能直接打出来,使用动态库的时候,相对信息不太完整。另外,在经验范围内无法解释的问题时,一定要沉得住气,静下心来,用最朴素的方式去解决,不要总想着有什么经验可循。。


阅读全文
0 0