如何在基于gRPC的微服务中处理非确定性故障导致的任务丢失?
问题场景
存在两个微服务A和B:
- A通过gRPC调用向B传输数据
- B执行长时间运行的任务,完成后发布包含结果的事件,供A及其他服务消费
当调用发起时B处于运行状态,但因非确定性故障在处理数据过程中崩溃重启,A如何仍能获取任务结果?
补充说明:若使用Kafka这类消息队列,消息会被保留至删除或超时,此类问题自然解决;但如果不依赖消息队列,A无法直接触发流程重试,B也无法追踪未处理的任务。
无消息队列下的解决方案
- 任务持久化+幂等保障:B接收到A的gRPC请求后,第一时间将任务元数据(请求ID、业务数据、处理状态)写入持久化存储(如关系型数据库、本地磁盘文件),标记状态为「处理中」。B崩溃重启后,启动流程优先扫描持久化存储,将所有「处理中」的任务重新执行。同时A需保证请求的幂等性,通过唯一请求ID避免重复发送导致B重复处理。
- 主动轮询+状态查询接口:为B新增一个基于请求ID的任务状态查询gRPC接口。A发送请求后,启动定时轮询逻辑,定期向B查询对应任务的状态。若发现B出现崩溃重启,A可根据查询结果判断:若B已持久化任务,则无需重发请求,只需等待结果;若任务未被持久化,则重新发起请求。
- 本地事件存储+重启补发:B完成任务后,先将结果事件写入本地持久化存储,再对外发布事件。B崩溃重启后,优先检查本地存储中已完成但未发布的事件,重新执行发布操作。同时A可维护一个未收到结果的请求列表,定期核对是否有遗漏的结果事件。
- 轻量分布式追踪+补偿逻辑:引入OpenTelemetry这类轻量分布式追踪组件,记录A的请求链路和B的任务处理链路。A通过追踪数据发现任务异常后,触发补偿逻辑:要么向B查询任务状态,要么在确认B未完成任务时重新发起请求。
内容的提问来源于stack exchange,提问作者DividedByZero
相关产品推荐
相关产品推荐

