一次go协程不够的线上问题
2023-08-07 本文已影响0人
鸿雁长飞光不度
1. 事故产生:
昨天晚上线上出现了一次事故,payment服务瞬间收到了大量的退款请求,是上游业务方执行批量脚本引起的,payment收到退款请求以后发送异步消息,payment自己会消费这个异步消息,在消费的过程中会用grpc请求调用tpw服务发起退款,但是tpw服务的因为数据库配置不高,并且请求qps过大,峰值达到了500qps,导致payment的退款异步消息处理超时,进入了死信队列,同时因为payment异步消息处理超时,导致goroutine被阻塞了,同时也影响到了其他的异步任务的执行。
2. 反思和改进:
2.1 限流
缺乏合理的限流策略
- payment服务应该有一个合理的限流策略,防止业务方无脑调用
- tpw应该根据自身的承受能力,限制来自payment的调用
2.2 队列
- 协程池分离
不同类型的消息协程池要分开,确保不会不同类型的消息不相互响应,至少确保边缘业务不能影响主流业务。 - 重试不能固定
消息超时后重试的时间不能固定,本次就是固定10s,相当于10s后,又一次大流量调用tpw接口,造成的结果还是失败,可以设置一个范围内的随机值。 - 重试队列需要分开
目前所有的消息重试队列是公用的,重试消息量大的时候会影响到其他的业务,每个类型的消息需要配置自己的重试队列。
2.3 监控报警
此前已经基于日志配置了消息消费监控,能够清楚的观察到消息的消费速度、平均耗时,正是基于已有的监控迅速定位了具体耗时的消息类型。