‹  返回课程

多线程网络程序有什么好的调试方法?

课文
阅读量:301
技术范畴
从网络报文、程序日志、assert手段以及外部工具等几方面下手,实现对多线程网络程序发生错误之后,如何纠出问题所在;并且也提及了避免或减少此类问题出现才真正的王道。
课前导言
C++所写的程序往往拥有较好的性能,因此常用于写网络后台程序,以应对大并发压力。但经验不足的新手,容易在程序员犯一些并发错误。有什么办预防此类问题,或在出问题之后快速分析错误逻辑所在位置呢?
多线程网络程序有什么好的调试方法?
多线程网络程序出现并发冲突时,常用的调试方法

当大并发上来时,可能会碰上多线程资源访问冲突的问题,比如该加锁的未加锁。

这类问题往往你一单步跟踪,它就不出问题了。甚至并发的压力一小,也不出问题了。可是压力一大,又往往日志一片混乱。处理这类问题,要学会几个常规的调试小窍门。

一是,记得为你的上层业务的网络报文,加一个全局唯一的id,比如一个uuid(容易实现,但比较浪费,因为uuid长)。回头出错时,可简单写个工具,从日志中挖出这个任务的独立的完整过程。

二是,当然一些错误有时必须交叉看所有日志,反倒才有帮助。所以日志一定要有线程id,甚至要有相关的socket连接编号,客户端的ip加端口加一个time_t通常可用作这个编号。还要有至少精确到毫秒的时间。如果问题逻辑居然跨多台主机(这很常见),建议在现场搞一台时间服务器 ,确保各台网络服务器至少在秒级上保持一致。许多看似穿越的bug,就是源于某些逻辑需依赖时间次序,可是却有某台主机奇怪地停留在1970年的时光里造成……

三是,强调下,一个好的log机制一定是调试多线程网络程序的基础工具。它至要保证,打到屏幕上或文件的日志,不会因为并发而混乱(就是保证一条日志输出的完整性,别夹杂另一条日志的部分),并且最好支持在屏幕上彩色显示,一定要有级别(信息,警告,错误,失败,调试,临时)控制,并且最好是可在运行期调换级别,一定要能方便地输出前面说的各类id及时间,最好也支持必要时依据当前调用的函数栈级自动处理缩进,还最好要有信息详细级别控制,也会有不想看线程id或时间的时候。 (服务端开源C++日志库推荐:spdlog,https://github.com/gabime/spdlog

四是,要学会正确使用assert。测试阶段该死就让它死,有利于找到问题,所有该自杀不自杀,非要带病运行的,都是作(zhuo,第一声)。因为C++多线程程序很调皮,它最喜欢让带病程序时好时抽。

五是,当程序段错误了,一定要学会让留它下core文件,太多太多看似头大的问题,用gdb来个现场恢复,立刻水落石出。并且几乎都是并发问题。

六是,别忘了有tcptrace这样的工具,你的调试器再强,它也是只调一个节点上的一个网络相关进程,两个程序网络通信,到底是谁说错话呢?。用tcptrace中间一插手,清清楚楚,当然你不要程序逻辑还没正确,就开始上ssl追求安全。这也是一个必须的做法:你的要支持ssl的网络交互的实现,一定要实现成有可方便地切换回不带ssl的机制。 反正学个python,花点时间把你负责的网络模块的上下家,都写出来,当然不需要内部逻辑,只需要能互相喂数据,这样妈妈再也不用担心你自己测试不了自己的网络节点程序了,特别是当你的上家是一个猪一样的队友而下家是孙猴子一样精的时候;自行搞定上下家的输入输出,不仅是不加班的利器,而且可有效保障同事间和谐友爱。python不会也没关系,用c++也可。如果上家是个纯粹的客户端,网上找找就有通用的。

最后,又看了眼题目,发现自己的回答全是错的。因为这些恐怕都不是多线程网络程序的好的调试方法。好的调试方法就是不需要调试

评论:

评论

课后导言
再次强调:正确地组织逻辑,避免并发冲突才是使用C++写后台网络服务的“王道”。