Orleans 流系统握手机制时序图

时序图说明

以下时序图展示了 Orleans 流系统中握手机制的完整流程,包括正常情况和异常情况的处理。

1. 正常握手流程

流代理(PullingAgent) 消费者(Consumer) 缓存(QueueCache) 存储(Storage) GetSequenceToken(subscriptionId) 查询上次处理位置 返回 lastProcessedToken 返回 StreamHandshakeToken GetCacheCursor(streamId, token) 返回 Cursor Cursor.MoveNext() (移动到下一个未处理消息) 保存 LastToken = requestedHandshakeToken 握手成功,开始消息投递 流代理(PullingAgent) 消费者(Consumer) 缓存(QueueCache) 存储(Storage)

2. 新订阅握手流程

流代理(PullingAgent) 新消费者(NewConsumer) 缓存(QueueCache) GetSequenceToken(subscriptionId) 返回 null (新订阅,无历史状态) GetCacheCursor(streamId, cacheToken) 返回 Cursor (从缓存位置开始) 保存 LastToken = null 握手成功,从缓存位置开始投递 流代理(PullingAgent) 新消费者(NewConsumer) 缓存(QueueCache)

3. 异常处理流程

流代理(PullingAgent) 消费者(Consumer) 错误协议(ErrorProtocol) GetSequenceToken(subscriptionId) 抛出异常 (网络问题/消费者不可用) 检查 IsShutdown return false (停止处理) ErrorProtocol(consumerData, exception) 记录错误,决定是否标记为故障 返回 faultedSubscription 状态 return false (停止处理该消费者) GetCacheCursor(streamId, cacheToken) (备用方案) 握手完成,使用备用位置 alt 订阅被标记为故障 订阅正常 alt 代理正在关闭 代理正常运行 流代理(PullingAgent) 消费者(Consumer) 错误协议(ErrorProtocol)

4. 重试机制流程

流代理(PullingAgent) 消费者(Consumer) 重试执行器(RetryExecutor) ExecuteWithRetries(GetSequenceToken, INFINITE_RETRIES) GetSequenceToken(subscriptionId) 返回 StreamHandshakeToken 返回结果 抛出异常 检查重试条件 等待退避时间 GetSequenceToken(subscriptionId) (重试) 抛出异常 alt 满足重试条件 不满足重试条件 alt 成功 失败 流代理(PullingAgent) 消费者(Consumer) 重试执行器(RetryExecutor)

5. 消息投递流程

流代理(PullingAgent) 消费者(Consumer) 缓存(QueueCache) Cursor.GetCurrent() (获取当前消息) 返回 StreamMessage DeliverMessage(message, sequenceToken) 处理消息 返回处理结果 Cursor.MoveNext() (移动到下一个消息) 返回是否还有更多消息 继续投递下一条消息 等待新消息或定期握手 alt 还有更多消息 没有更多消息 流代理(PullingAgent) 消费者(Consumer) 缓存(QueueCache)

6. 故障恢复流程

流代理(PullingAgent) 重启消费者(RestartedConsumer) 存储(Storage) 恢复上次处理状态 返回 lastProcessedToken GetSequenceToken(subscriptionId) 返回恢复的 StreamHandshakeToken GetCacheCursor(streamId, recoveredToken) Cursor.MoveNext() (从恢复位置的下一个开始) 保存恢复状态 握手成功,从恢复位置继续投递 流代理(PullingAgent) 重启消费者(RestartedConsumer) 存储(Storage)

7. 状态同步流程

流代理(PullingAgent) 消费者(Consumer) 存储(Storage) 处理消息完成 更新 lastProcessedToken 确认状态已保存 定期握手检查 GetSequenceToken(subscriptionId) 返回当前状态 比较当前状态与 LastToken 继续正常投递 调整投递位置 从新位置开始投递 alt 状态一致 状态不一致 流代理(PullingAgent) 消费者(Consumer) 存储(Storage)

8. 关键设计决策说明

8.1 为什么使用无限重试?

  • 可靠性优先:握手失败意味着消息投递失败
  • 网络不稳定:分布式环境中网络问题很常见
  • 消费者重启:消费者可能暂时不可用

8.2 为什么需要 MoveNext()?

  • 避免重复:令牌指向已处理的消息
  • 连续性保证:确保从下一个未处理消息开始
  • 状态一致性:保持消费者和代理状态同步

8.3 为什么需要备用方案?

  • 容错性:握手失败时系统仍能工作
  • 降级策略:从已知安全位置开始
  • 系统可用性:避免因握手失败导致整个系统停止

8.4 为什么保存 LastToken?

  • 下次握手参考:为下次握手提供基准
  • 状态追踪:监控消费者状态变化
  • 性能优化:减少重复的状态查询

9. 性能优化点

  1. 异步处理:所有操作都是异步的,避免阻塞
  2. 状态缓存:缓存常用状态信息,减少存储访问
  3. 批量操作:支持批量消息投递
  4. 智能重试:使用退避算法避免过度重试
  5. 资源管理:及时释放不需要的资源

10. 监控指标

  • 握手成功率:成功握手次数 / 总握手次数
  • 握手延迟:从开始握手到完成的时间
  • 重试次数:平均重试次数
  • 错误率:握手失败的比例
  • 消息投递延迟:从握手完成到开始投递的时间

这个握手机制确保了 Orleans 流系统在复杂的分布式环境中能够可靠、高效地处理消息投递。

相关推荐
骄马之死8 小时前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
z落落8 小时前
C# 泛型方法(原理、类型推断、多泛型参数)+泛型效率(普通类型 VS Object装箱 VS 泛型)
开发语言·c#
GoGeekBaird9 小时前
Anthropic技能"(Skills)的经验分享
后端
王码码20359 小时前
多台服务器怎么统一看状态?Beszel 轻量监控,搭起来不费事
运维·服务器·后端·安全·阿里云·接口·web
郑洁文10 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
rockey62710 小时前
基于AScript的SQL脚本语言发布啦!
sql·c#·.net·script·expression·动态脚本
指令集梦境11 小时前
Cursor + Spring Boot实战:从零写一个RESTful API
spring boot·后端·restful
z落落11 小时前
C# 四种特殊类:抽象类、密封类、静态类、部分类
开发语言·c#
码云之上12 小时前
聊聊如何设计一个高效、稳定的 Node.js 接入层
前端·后端·node.js
IT_陈寒13 小时前
Vite项目build后路由404了?你可能漏了这个小配置
前端·人工智能·后端