记一个折磨了我一天半的 Bug

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 一杯茶,一根烟,一个 Bug 一天根本改不完。

最近开始学习后台开发,虽然与我以前从事的 Android 开发一样都是使用 Java 语言,但是技术栈完全不同,有太多的必备的「新」概念要去学习,而在对它们,以及别人写的代码有充分的了解之前,就可能会遇上这种一杯茶,一根烟,一个 Bug 一天根本改不完的情况。

最近遇见的这个 Bug 是在修改项目遗留的问题时偶然发现的,简而言之就是这样:

服务 A 在从外界接收到推送的一条数据后,将数据插入到库里,然后通过 MQ 推送一条消息给 服务 B服务 B 会根据收到的消息进行一些处理,其中包括远程调用 服务 A 的方法去查询这条数据,但是在测试环境总是报查询不到这条数据。

遇到问题之后,先进行了一些排查:

  • 怀疑传参或者数据插库没有成功,于是将查询参数打印出来,手动复制参数到库里去查——有数据;

  • 怀疑实际执行的 SQL 有问题,于是请同事帮忙配置 MyBatis 在日志里输出 SQL,原样复制出来去库里查——有数据;

  • 在本地连接测试环境数据库,代码里下断点调试——能正常取到数据;

图片

纳闷了一阵以后,继续排查:

  • 怀疑测试环境程序数据库连接有问题,于是测试了一些其它查库的功能——数据正常;

  • 怀疑测试环境的包有问题,于是请运维同事将 jar 包从容器里拷贝下来,核对配置——没问题;

  • 怀疑测试环境远程调用失败了,于是在远程调用处加日志——没有异常;

图片

  • 怀疑测试环境注册了多余的 服务 A 的节点,于是去 Dubbo Admin 里核对节点——数量正常,网段正常;

  • 怀疑测试环境的部署的 服务 A 的某个节点部署有问题,于是请运维同事一个一个 telnet 上去手动执行远程调用——能正常取到数据;

  • 在一条失败 case 之后,马上向 服务 B 手动再次推送相同的消息——能取到数据;

图片

直到我终于留意到一个现象:从日志来看,服务 A 插库与 服务 B 远程调用 服务 A 的方法的时间只相差 1 毫秒。会不会是一切发生得太快了,库里还查不到刚刚写入的数据?抑或者查询的时候插库还根本没有生效?

带着这个疑惑我终于认真去看插库并发消息那块的代码了,于是就看到这样一段代码:

@Override
@Transactional(...)
public boolean doSomething() {
    ...

    // 插入数据

    // 发送消息

    ...
}

是的没错,插入数据和发送消息写在了一个事务里面。虽然我对数据库了解不多,但对事务的特性还是有所了解——发送消息的时候,数据库里确实还没有刚刚插入的数据,事务提交后才会生效,也就是说,服务 B收到消息后远程调用回 服务 A 想查找刚刚插入的数据,能否查到全凭运气,取决于此时事务已经执行完。

问题时序示意:

图片

要确保消息发出时数据库里已经存在数据了也很简单,将事务粒度控制一下,只包含插入数据这块即可,插入成功了再发送消息。

@Override
public boolean doSomething() {
    ...

    // 事务开始

    // 插入数据

    // 事务结束

    if (插入数据成功) {
        // 发送消息
    }

    ...
}

正常时序示意:

图片

总结:

  1. 在理解别人写的逻辑的时候不要做预设,你认为别人不可能犯如此低级的错误而直接排除在外的情况,可能恰好是问题所在;

  2. 在排查可能是时序导致的问题时,少用断点调试,用日志更合适;

  3. 本地调试时尽量将场景模拟完整一点,从中途某一环开始则有可能越过问题触发条件而无法复现。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
缓存 JavaScript 小程序
接手前同事代码,特别烂,各种BUG,看麻了。。。
接手前同事代码,特别烂,各种BUG,看麻了。。。
|
Python
遇到bug不要慌,先发个文章看看
遇到bug不要慌,先发个文章看看
128 0
|
Java 中间件 程序员
最网最全bug定位套路,遇见bug再也不慌了
最网最全bug定位套路,遇见bug再也不慌了
318 0
|
XML 数据格式
解决Bug:OnErrorNotImplementedException
解决Bug:OnErrorNotImplementedException
447 0
解决Bug:OnErrorNotImplementedException
|
存储 算法 Java
10 个让人头疼的 bug
那个谁,今天又写 bug 了,没错,他说的好像就是我。。。。。。 作为 Java 开发,我们在写代码的过程中难免会产生各种奇思妙想的 bug ,有些 bug 就挺让人无奈的,比如说各种空指针异常,在 ArrayList 的迭代中进行删除操作引发异常,数组下标越界异常等。
10 个让人头疼的 bug
|
网络虚拟化
【俺修复的印象最深的bug】一名在校网工处理的一个无语的网络Bug
【以及经过脱敏处理,无重要信息泄露】本人在校大学生,网络水平还行,是学校信息中心常驻外援工程师,hhhhhhhhhhhhh。 某次在食堂吃晚饭的时候一个电话把我call过去,说新配置一新机房网络,网联不通,弄了一下午了看不出问题。
1660 0
【俺修复的印象最深的bug】一名在校网工处理的一个无语的网络Bug
|
移动开发 程序员
我修复的印象最深的一个bug
如果提到程序员,我们绝大多数人可能会说,程序员每天的时间除了开发需求就是在查bug。在我以前,肯定会不以为然,但自从我成为一名程序员之后,我才深有体验,这句话其实说得没错。
|
程序员 PHP
如何激怒一个程序猿(2):又在写bug啊
在山的这边海的那边有一群程序员,他们老实又胹腆,他们聪明又有钱。他们一天到晚坐在那里熬夜写软件,饿了就咬一口方便面~~哦苦命的程序员,哦苦命的程序员,只要一改需求他们就要重新搞一遍,但是期限只剩下最后两天~~ 
17466 0
表白这件事,比解 bug 要难多少?
今天是个粉红色日子,我们来聊聊和技术无关的“技术活”
3096 0