从service bus队列接收消息时出现SessionCannotBeLocked异常
Azure Service Bus会话队列SessionCannotBeLocked异常解决方案
请求的会话'343747143130383837004500'无法被接受,可能已被其他接收器锁定。TrackingId:429fae51-488b-4365-b0aa-06127a47b428_B2, SystemTracker:maxeeservicebus:queue:maxeemessages~255, Timestamp:2021-11-10T06:19:54 TrackingId:1ffb82129f4a44d9a03c2f3a812606e5_G27, SystemTracker:gateway7, Timestamp:2021-11-10T06:19:54 (SessionCannotBeLocked)content: 3437471431303838370045000000000001
该异常触发的核心是Azure Service Bus会话模式的独占特性,同一时间同一个session id仅允许被一个客户端接收器持有锁,锁定期间其他接收器无法访问该会话的所有消息。
可按照以下步骤排查解决:
- 排查多实例消费的争抢问题:如果消费端是多实例部署,未做会话分配逻辑的情况下多个实例会争抢同一个session触发异常。可以设置
SessionIdleTimeout参数让长时间空闲的会话自动释放锁,或者开启Service Bus内置的会话负载均衡特性,让不同实例自动分配不同的session处理,避免重复争抢。 - 优化会话锁的释放逻辑:检查消费端代码是否存在拿到会话锁后异常退出、未主动释放锁的情况,锁会直到默认过期时间(默认1分钟)才会自动释放,该时间段内所有新的会话请求都会失败。可以在消费逻辑外层增加try-finally块,确保处理完成后主动调用
CloseSessionAsync释放锁,同时可根据业务处理耗时调整SessionLockDuration参数,设置合理的锁过期时长。 - 改用官方推荐的会话处理组件:针对已分区的会话队列,手动指定session id接收消息的逻辑容易出现重复请求的问题,建议改用
SessionProcessor类处理会话消息,该组件内部已经实现了锁自动续期、异常重试、会话自动分配等能力,无需手动处理锁相关的底层逻辑。 - 增加针对性重试策略:如果是短时间锁占用导致的临时异常,可以在消费端针对
SessionCannotBeLocked错误码配置指数退避重试策略,等待几十毫秒到几秒后再重新请求会话,大部分场景下重试即可解决问题。
内容的提问来源于stack exchange,提问作者Imran Ahmad Mughal
相关产品推荐
相关产品推荐

