记录一次kafka问题的排查

456 阅读3分钟

事情经过是这样的,开发了一个新交易系统B,代替原来的系统A,但是新系统不会马上全面替换A,二者会并存一段时间。由于设计B的时候为了不与A混淆就新定义了消息b1, 但是遗漏了系统A有个订单提交的消息a1被其他组监听着,所以在不对其他组造成影响的情况下 我需要在对B1做适配A1,以便不会对其他监听照成印象。

因为设计b1并没考虑兼容a1,所以消息体上有差距,可能无法完全转换成a1,所以跟其他业务员方识别了一波,消费端具体使用了哪些字段,必须保证这些字段有值,其他字段可以先不处理。

然后一顿键盘啪啪啪,并且信心满满的发了测试环境。

在验证的发现有点不对劲了。

1.还原案发现场

通过日志发现a1的消费服务S1在不断消费,实际上测试环境不会有这么多消息的。而且日志呈现每毫秒几条的态势。系统操作接口响应开始变慢,并且超时。

为什么会有这么对消息呢?开始本地代码调试。结果发现,转换消息的地方并不是发一次结束了,而是一直在发。这点通过日志也得到了验证,大量的消息内容是一样的。 最后通过一位同事的提醒,发现是消息的handler 方法写的有问题。

一般写法

 void handler(Event a){

   //do something

}

我的写法

void handler(Event a){

  //do something

messageConversion(a);

}

void messageConversion(Event a){

   //转换消息

   //广播消息b1

}

以上这段代码,大家可以略过,由于公司的消息并不是直接调用kafka,而是经过一层封装,导致编译运行都没有出错,但是执行逻辑并没有按照预想的顺序。反而进入了一种循环发送的异常情况下。

在我找到问题并完成修复这短短时间内,尽然积压了200w左右的消息。

由于积压的消息多,导致服务性能大大下降,服务接口已经开始超时。

秉承着谁挖的坑谁来填,这个积压消息比较解决掉。

2.快速紧急处理

找到问题后,现在需要做的就是重置偏移量跳过这些消息,将位移调制当前最新位置,因为是测试环境并没有上云服务,没有界面操作,只能用命令

bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --reset-offsets--topic t1 --to-latest --execute

处理完后,日志消费记录立马停了下来,并且服务接口响应也恢复正常。

3.总结教训

用法问题:这个坑也是第一次踩到,但是也暴露出自研组件的问题。比如在寻找handler的时候应该加一些校验,当同一个消息发现有多个handler的时候必须明确指定哪一个处理,或者抛出异常

发布流程操作:还是要先在本地测试,再转测试环境(这次轻敌大意了)