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 流系统在复杂的分布式环境中能够可靠、高效地处理消息投递。

相关推荐
唐青枫17 分钟前
C#.NET ThreadLocal 深入解析:线程独享数据、性能收益与实战边界
c#·.net
曹牧28 分钟前
Spring:@RequestMapping注解,匹配的顺序与上下文无关
java·后端·spring
阿丰资源2 小时前
SpringBoot+Vue实战:打造企业级在线文档管理系统
vue.js·spring boot·后端
Rust研习社2 小时前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
0xDevNull2 小时前
Spring Boot 自动装配:从原理到实践
java·spring boot·后端
IT_陈寒3 小时前
SpringBoot配置加载顺序把我坑惨了
前端·人工智能·后端
Moment3 小时前
面试官:给 llm 传递上下文,有哪几个身份 role ❓❓❓
前端·后端·面试
snakeshe10103 小时前
SpringBoot 多人协作平台实战(5):从零开始集成 MyBatis ORM 连接 MySQL 数据库
后端
SamDeepThinking3 小时前
中小团队需要一个资源微服务
后端·微服务·架构
超梦dasgg4 小时前
Spring AI 智能航空助手项目实战
java·人工智能·后端·spring·ai编程