生产环境重复消费消息的问题
- 问题
生产环境由用户反映同一张发票收到几十条短信和相关邮件
分析
用户收到短信和邮件是发生在平台推送发票的环节,通过查看线上日志,将问题定位在IInvoiceService#recvInvoice处,在dubbo调用方时抛出TimeoutException。
查看此方法的代码,这个方法的核心业务是发送短信,发送邮件,修改数据。由于这些方法都是同步调用,而且其中涉及到很多网络IO操作,耗时过长是必然的现象。
由于rpc调用抛出了异常,而rpc调用本身则是在消息队列消费过程,消息队列接收到这个异常,就会重试这个消息,但是由于每次重试都会超时,那么就造成业务上的死循环。而dubbo服务的提供者并没有因为调用方抛出异常就停止执行,所以每一次都会给客户发送短信和邮件,就会导致客户重复收到短信和邮件-
思考
通过上面的分析,问题已经很明确,超时导致了异常,异常导致了重试。这其中涉及了两个中间件,dubbo和rocketmq。 解决方案
1.dubbo服务调用中涉及网络IO的操作,可以考虑同步变异步,容忍失败
2.dubbo服务做幂等性处理
3.rocketmq消息消费过程中必须严格控制异常,正确理解返回值的业务意义
4.rocketmq消息消费要做好消息重复消费的控制