- 后端
- 微服务
【免费下载链接】orleans
Cloud Native application framework for .NET
本篇技术指南聚焦于将基于 .NET 的云原生框架 Orleans 的应用从 9.x 系列升级到 10.x 系列,完整覆盖包版本集中管理、UnorderedAttribute与OrleansConstructorAttribute等源码级弃用处理、CancelRequestOnTimeout超时取消行为变更、SQL Server ADO.NET 客户端切换、序列化与持久化状态兼容性验证,以及并行集群部署与回滚演练。读完本文,你将获得一套可执行、可验证、可回滚的 Orleans 主版本升级方案。
升级起点与目标假设
在执行迁移前,先确认以下前提,避免在升级过程中混入无关变量:
- 应用运行在最新的 Orleans 9.x 补丁版本上,优先推荐Orleans 9.2.1。
- 应用及其依赖支持.NET 8 或 .NET 10。
- 解决方案中所有 Orleans 包将统一移动到同一个当前的 Orleans 10.x 补丁版本。
- 已部署的 Orleans 9.x 版本所对应的 Provider 架构(数据库表结构等)保持当前状态。
需要特别说明的是:Orleans 10 的包同时面向 .NET 8 与 .NET 10 编译。将应用重新定向到 .NET 10 可以作为一个独立的变更步骤;在首次迁移部署中继续保持 .NET 8,可以显著减少 Orleans 升级过程中的变量数量,降低排障难度。
变更总览
| 领域 | Orleans 10 影响 | 需要采取的动作 |
|---|---|---|
| 源码与分析器 | UnorderedAttribute与OrleansConstructorAttribute已标记为过时(obsolete) | 移除UnorderedAttribute;仅在确实需要 DI 构造函数选择时替换OrleansConstructorAttribute |
| 行为 | MessagingOptions.CancelRequestOnTimeout默认值改为false | 如果应用依赖超时后自动发送取消,必须显式设置该选项 |
| ADO.NET 提供程序 | SQL Server 默认改用Microsoft.Data.SqlClient及其 invariant 名称 | 移除System.Data.SqlClient,更新 invariant,并逐一测试每个 ADO.NET 提供程序 |
| 序列化与状态 | Orleans 10 不要求从 Orleans 9 重写线格式(wire-format)或 grain 状态 | 保留序列化器 ID、别名、Provider 序列化器设置以及存储类型的兼容性 |
| 托管 | 泛型宿主(generic host)的UseOrleans*与UseOrleansClient*模型保持现状 | 已在 Orleans 9 使用这些 API 的应用无需重写托管代码 |
| 放置策略 | Orleans 9.2 已把默认放置策略改为ResourceOptimizedPlacement | 保持该默认值;若需要确定性连续性,则在升级前显式注册RandomPlacement |
| 取消 | Orleans 10 为观察者(observers)和系统目标(system targets)新增取消支持 | 每个 grain 方法最多保留一个CancellationToken参数,并测试超时/取消竞态 |
| 定时器 | Orleans 10 没有新的定时器破坏性变更 | 继续使用RegisterGrainTimer*;Grain.RegisterTimer*早在 Orleans 8.2 就已过时 |
| 调用过滤器 | Orleans 10 没有新的过滤器注册模型 | 继续在ISiloBuilder或IClientBuilder上注册入站/出站过滤器 |
| 部署 | 跨主版本的混合集群不受文档化兼容性保证覆盖 | 除非你的混合版本拓扑已经过专门验证,否则请使用并行 Orleans 10 集群 |
集中管理包版本
主版本升级中最常见的故障源之一是包版本漂移——不同项目引用了不同的 Orleans 补丁版本。推荐使用 NuGetCentral Package Management(CPM)集中对齐所有包版本:
<Project> <PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <OrleansVersion>10.2.2</OrleansVersion> </PropertyGroup> <ItemGroup> <PackageVersion Include="Microsoft.Orleans.Client" Version="$(OrleansVersion)" /> <PackageVersion Include="Microsoft.Orleans.Sdk" Version="$(OrleansVersion)" /> <PackageVersion Include="Microsoft.Orleans.Server" Version="$(OrleansVersion)" /> </ItemGroup> </Project>执行迁移时应使用当前最新的稳定版 Orleans 10.x 补丁。解决方案中用到的每个 Provider 包(如聚类、持久化、提醒、流式处理的存储提供程序)都要以相同的 Orleans 版本加入同一份中央版本管理文件中,确保Microsoft.Orleans.*全家桶版本完全对齐。
处理源码级警告:两个弃用特性
Orleans 10 将两个特性标记为过时,代码编译时会出现警告,需要逐一处理。升级的第一步是消除这些警告。
移除UnorderedAttribute
UnorderedAttribute在 Orleans 10 中不产生任何效果。仓库源码 GrainAttributeConcurrency.cs 中对它的定义和注释给出了明确依据:
[AttributeUsage(AttributeTargets.Interface)] [Obsolete("Message ordering is not guaranteed regardless of whether this attribute is used. This attribute has no effect.")] public sealed class UnorderedAttribute : Attribute { }源码注释明确指出:Orleans 本来就不保证基于该属性进行消息排序,因此无论是否使用该属性,消息顺序都没有保证。请把它从 grain 接口上移除,不要试图寻找替代语义。
仅在依赖注入场景替换OrleansConstructorAttribute
OrleansConstructorAttribute在 Orleans 10 中不再被 Orleans 识别。看 Annotations.cs 中的定义即可确认:
[AttributeUsage(AttributeTargets.Constructor)] [Obsolete("Use GeneratedActivatorConstructorAttribute instead. This attribute is not recognized by Orleans.")] public sealed class OrleansConstructorAttribute : ActivatorUtilitiesConstructorAttribute { }替换规则如下:
- 如果可序列化类型需要通过依赖注入来选择构造函数,改用
GeneratedActivatorConstructorAttribute或ActivatorUtilitiesConstructorAttribute。GeneratedActivatorConstructorAttribute(见 Annotations.cs)指示生成的 activator 实现使用该构造函数进行实例化,可用于调用需要注入依赖的构造函数。 - 需要强调的是:这两个替代属性都不会为反序列化数据成员选择构造函数。反序列化走的是序列化器自身的激活路径,与 DI 构造函数选择是两条独立的机制。
另外,不要在本次清理中改动成员 ID(IdAttribute值)或构造函数可见的状态——这属于下一节要讲的序列化兼容性红线。
显式配置超时取消:CancelRequestOnTimeout
Orleans 10 将MessagingOptions.CancelRequestOnTimeout的默认值改为false。这一行为变更意味着:调用方超时后会停止等待响应,但Orleans 不会自动向目标发送取消信号。如果应用依赖“超时即取消对端执行”的旧行为,必须显式开启。
仓库源码 MessagingOptions.cs 中对该选项的注释与默认值给出了实现层证据:
/// <summary> /// Whether request cancellation should be attempted when a request times out. /// </summary> /// <remarks> /// Request cancellation may involve sending a cancellation message to the silo which hosts the target grain. /// Defaults to <see langword="false"/>. /// </remarks> public bool CancelRequestOnTimeout { get; set; }该选项在运行时确实会触发向承载目标 grain 的 silo 发送取消消息:在 SharedCallbackData.cs 与 CallbackData.cs 中,超时回调逻辑会依据CancelRequestOnTimeout决定是否发起请求取消。
需要在发起调用的客户端(Client)和 silo(Silo)两侧同时设置。迁移示例片段位于 Orleans10MigrationExamples.cs:
public static void ConfigureTimeoutCancellation(ISiloBuilder siloBuilder) { siloBuilder.Configure<SiloMessagingOptions>(options => { options.CancelRequestOnTimeout = true; }); } public static void ConfigureTimeoutCancellation(IClientBuilder clientBuilder) { clientBuilder.Configure<ClientMessagingOptions>(options => { options.CancelRequestOnTimeout = true; }); }注意:无论该选项如何设置,超时都不代表目标一定停止了执行。超时与对端完成是两个独立事件,grain 方法必须保持可安全重试(幂等或可补偿)的设计。
更新 SQL Server ADO.NET 配置
Orleans 10 的 ADO.NET 聚类(clustering)、持久化(persistence)、提醒(reminders)和流式处理(streaming)在 SQL Server 上默认改用Microsoft.Data.SqlClient。仓库中 AdoNetInvariants.cs 定义的 SQL Server invariant 名称即为:
public const string InvariantNameSqlServer = "Microsoft.Data.SqlClient";按以下步骤完成切换:
- 移除对
System.Data.SqlClient的直接包引用。 - 通过你的中央包策略引入
Microsoft.Data.SqlClient。请使用应用所支持的最新版本,不要照抄早期迁移指南中老旧的固定版本号。 - 将 Provider invariant 从
System.Data.SqlClient改为Microsoft.Data.SqlClient。 - 按需应用从当前已部署 schema 版本到目标 Orleans 版本之间所需的 Provider 迁移脚本。
- 对聚类、grain 存储、提醒、流式处理进行独立测试,逐个验证,不要一次合并验证掩盖单点故障。
迁移脚本按数据库类型存放于仓库的迁移目录中,按版本顺序依次应用:
- 聚类迁移脚本(如
SQLServer-Clustering-3.7.0.sql、PostgreSQL-Clustering-3.6.0.sql、MySQL-Clustering-3.7.0.sql、Oracle-Clustering-3.7.0.sql) - 持久化迁移脚本(如
PostgreSQL-Persistence-3.6.0.sql) - 提醒迁移脚本(如
PostgreSQL-Reminders-3.6.0.sql)
需要澄清的关键点:客户端库切换本身不会改变 grain 状态的负载格式(payload format)。但它会改变连接默认值与认证行为,因此必须在 staging 环境验证连接加密、证书、认证、重试策略与事务行为——这些变化可能来自Microsoft.Data.SqlClient与System.Data.SqlClient之间的默认配置差异,而非 Orleans 自身。
保持序列化与状态兼容
从 Orleans 9 到 Orleans 10,没有任何一个迁移步骤要求重编号IdAttribute值或重写持久化状态。升级的核心策略是“保住既有契约”:
- 不要重用或重编号
IdAttribute值。IdAttribute是序列化成员的唯一标识(见 Annotations.cs),任何成员 ID 变化都会破坏新旧版本的读取兼容。 - 当类型或程序集移动时,保持
AliasAttribute值稳定。类型别名用于在类型跨程序集移动时保持序列化身份稳定(见 Annotations.cs)。 - 不要调整 record 主构造函数参数的顺序——它被用作隐式序列化器 ID(
GenerateSerializerAttribute默认对 record 类型自动包含主构造函数参数,见 Annotations.cs)。 - 在运行时升级期间,保持已配置的 grain 存储序列化器不变。
- 用 Orleans 10 读取代表性旧状态、写入,再验证回滚构建版本仍能读取这些数据,然后才允许生产写入。
一个稳定的可序列化状态示例(片段见 Orleans10MigrationExamples.cs):
[GenerateSerializer] public sealed class CounterState { [Id(0)] public int Value { get; set; } }- 按顺序应用 ADO.NET schema 脚本,并且在应用任何不可逆脚本之前,先验证回滚兼容性。
关于版本容忍规则(version-tolerance)的完整说明,参见 Orleans 序列化配置指南。
确认托管、放置策略、定时器与调用过滤器
这部分用于逐项确认 Orleans 10 中“不需要改动”的既有能力,避免过度修改引入风险。
托管模型:无需重写
如果 Orleans 9 应用已经使用Host.CreateApplicationBuilder、UseOrleans*或UseOrleansClient*,则不需要任何托管代码重写。泛型宿主模型在 Orleans 10 中保持当前形态。
放置策略:默认已是ResourceOptimizedPlacement
Orleans 9.2 已将默认放置策略改为ResourceOptimizedPlacement。仓库源码 DefaultSiloServices.cs 中可以看到该策略被注册为默认单例:
services.TryAddSingleton<PlacementStrategy, ResourceOptimizedPlacement>();其放置决策实现位于 ResourceOptimizedPlacementDirector.cs。如果你的生产集群仍然依赖RandomPlacement,请在升级前显式声明该策略,而不是隐式依赖旧默认值:
public static void KeepRandomPlacement(ISiloBuilder siloBuilder) { siloBuilder.Services.AddSingleton<PlacementStrategy, RandomPlacement>(); }定时器:继续使用RegisterGrainTimer
Orleans 10 没有新的定时器破坏性变更,请继续使用GrainBaseExtensions.RegisterGrainTimer*;旧的Grain.RegisterTimer*API 早在 Orleans 8.2 就已过时。在从旧 API 迁移到新 API 以保持旧行为时,注意GrainTimerCreationOptions.Interleave需要设置为true——新 API 的回调默认是**非交错(non-interleaving)**的。参考示例:
public override Task OnActivateAsync(CancellationToken cancellationToken) { _timer = this.RegisterGrainTimer( callback: DoWorkAsync, options: new GrainTimerCreationOptions { DueTime = TimeSpan.FromSeconds(1), Period = TimeSpan.FromSeconds(10), Interleave = true }); return Task.CompletedTask; } private static Task DoWorkAsync(CancellationToken cancellationToken) => Task.CompletedTask;(完整片段见 Orleans10MigrationExamples.cs。)
调用过滤器:在 Orleans 构建器上注册
调用过滤器必须注册在Orleans 构建器上,而不是直接注册到IServiceCollection。入站过滤器用委托注册、出站过滤器用类型注册:
public static void ConfigureCallFilters(ISiloBuilder siloBuilder) { siloBuilder.AddIncomingGrainCallFilter(async context => { await context.Invoke(); }); siloBuilder.AddOutgoingGrainCallFilter<MyOutgoingCallFilter>(); }public sealed class MyOutgoingCallFilter : IOutgoingGrainCallFilter { public Task Invoke(IOutgoingGrainCallContext context) => context.Invoke(); }(完整片段见 Orleans10MigrationExamples.cs。)
取消支持:每个方法最多一个CancellationToken
Orleans 10 为观察者和系统目标新增了取消支持。grain 接口方法中每个方法最多保留一个CancellationToken参数,并务必测试超时与取消之间的竞态:
public interface ICancelableWorkGrain : IGrainWithStringKey { Task RunAsync(CancellationToken cancellationToken); }(片段见 Orleans10MigrationExamples.cs。)
部署并保留回滚能力
完整的部署与回滚流程详见仓库文档 Upgrade deployment and rollback(升级部署与回滚)。该文档明确了一个关键边界:Orleans 文档化的运行时兼容保证仅覆盖同一主版本家族内的 patch 与 minor 版本;跨主版本的滚动升级默认视为不受支持,除非针对确切的运行时版本、Provider、应用契约与流量模式通过了你自己的资格验证(qualification suite)。
因此,默认采用独立的 Orleans 10 并行(blue-green)集群,并保留 Orleans 9 集群及其最后兼容的状态恢复点,直到满足以下全部条件:
- Orleans 10 的客户端与 silo 已通过冒烟测试与负载测试。
- Provider 写入的数据已被证明回滚构建版本可读(双向读取验证)。
- 队列或流中不存在 Orleans 9 无法识别的类型形状的负载。
- 指标显示激活放置、调用延迟、取消、提醒与存储行为均稳定。
并行集群部署的推荐顺序(详见 deployment-and-rollback.md):
- 使用与旧状态读取验证相同版本的应用契约修订构建目标版本。
- 创建与生产集群独立的成员关系与网关发现的并行集群。
- 指向克隆的 Provider 数据或 staging 数据集,验证聚类、存储、提醒、流、定时器、过滤器、取消与放置。
- 生产环境以无写入流量起步并完成冒烟测试。
- 逐步迁移一小部分可观测的流量。
- 仅当延迟、失败、激活、存储、提醒、流与取消指标稳定后,再增加流量。
- 在任何可能产生并发激活或冲突写入的共享状态切换前,先停止旧集群的写入。
- 在回滚窗口过期前,保留旧部署与恢复点。
两个独立集群不应同时运行在同一 grain 存储或提醒表上,除非 Provider 与应用已为该拓扑做过专门设计。
升级检查清单
- 升级到最新的 Orleans 9.x 补丁并消除构建警告。
- 将所有
Microsoft.Orleans.*包对齐到同一个当前 10.x 补丁。 - 首次部署保持 .NET 8,或将 .NET 10 重定向单独认证。
- 移除
UnorderedAttribute,替换有效的OrleansConstructorAttribute用法。 - 显式设置
CancelRequestOnTimeout。 - 如使用 SQL Server,替换
System.Data.SqlClient及其 invariant。 - 保留序列化器 ID、别名与 grain 存储序列化器设置。
- 确认放置策略、定时器交错与调用过滤器注册方式。
- 验证 Provider 架构与代表性持久化状态。
- 准备并演练并行集群部署与回滚。
延伸阅读
- 升级部署与回滚(并行集群序列、回滚前置条件与步骤)
- Orleans 序列化配置指南(版本容忍规则)
- 迁移代码示例片段:Orleans10MigrationExamples.cs
- ADO.NET 迁移脚本:聚类 · 持久化 · 提醒
- 后端
- 微服务
【免费下载链接】orleans
Cloud Native application framework for .NET
相关推荐
terraform-aws-eks 升级指南:从 v19.x 迁移到 v20.x 的不兼容变更、集群访问管理与状态迁移实战
terraform aws eks 升级指南:从 v19.x 迁移到 v20.x 的不兼容变更、集群访问管理与状态迁移实战 本指南以官方升级文档 docs/UP
云原生IaC容器编排集群管理Orleans 大版本升级部署与回滚指南:并行集群迁移的安全边界与实践
Orleans 大版本升级部署与回滚指南:并行集群迁移的安全边界与实践 导读 本文基于 deployment and rollback.md https://l
后端微服务FastAPI-Users 从 9.x 到 10.x 版本迁移指南:关键变更与最佳实践
FastAPI Users 从 9.x 到 10.x 版本迁移指南:关键变更与最佳实践 前言 FastAPI Users 是一个优秀的 FastAPI 用户认证
后端认证鉴权Web框架
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考