Orleans ADO.NET 提供程序配置指南:为集群、持久化、提醒与流式传输接入关系型数据库
2026/9/24 17:18:04 网站建设 项目流程
  • 后端
  • 微服务

【免费下载链接】orleans

Cloud Native application framework for .NET

项目地址:https://gitcode.com/gh_mirrors/or/orleans
点击查看免费下载

本文是 Orleans 官方配置文档(configuring-ado-dot-net-providers.md)的深度实践版,系统讲解如何用 ADO.NET 提供程序让 Orleans 的集群成员管理(Clustering)、Grain 持久化(Grain Storage)、提醒(Reminders)、Grain 目录(Grain Directory)与流式传输(Streaming)共用一套关系型数据库。读完本文,你将掌握:各能力对应的 NuGet 包与配置位置、数据库脚本的安装顺序与定制原则、SQL Server / PostgreSQL / MySQL / MariaDB / Oracle 的完整配置方法、基于DbDataSource的高级连接源注入方式,以及声明式配置与生产运维要点。

ADO.NET 提供程序与运行时能力总览

Orleans 的 ADO.NET 提供程序使用一个关系型数据库承载一种或多种运行时能力。每种能力对应独立的 NuGet 包,并可在不同端(Silo 或外部客户端)上配置:

能力配置位置
集群(Clustering)Microsoft.Orleans.Clustering.AdoNetSilo 与外部客户端
Grain 存储(Grain storage)Microsoft.Orleans.Persistence.AdoNetSilo
提醒(Reminders)Microsoft.Orleans.Reminders.AdoNetSilo
Grain 目录(Grain directory)Microsoft.Orleans.GrainDirectory.AdoNetSilo
流式传输(Streaming)Microsoft.Orleans.Streaming.AdoNetSilo 与外部客户端

安装原则:只安装应用实际用到的能力包,同时引用对应的数据库驱动包(driver package)。例如只做集群 + 持久化,就只安装 Clustering 与 Persistence 两个包,并额外引用Microsoft.Data.SqlClient等驱动。

从源码看,这些包之间的依赖是解耦的:集群能力通过 AdoNetHostingExtensions.cs 向 DI 容器注册IMembershipTable(Silo 侧)或IGatewayListProvider(客户端侧)实现;Grain 存储通过 AdoNetGrainStorageSiloBuilderExtensions.cs 提供AddAdoNetGrainStorage/AddAdoNetGrainStorageAsDefault;提醒服务通过 SiloBuilderReminderExtensions.cs 提供UseAdoNetReminderService。各能力按需注册,互不强制。

准备数据库:先运行主脚本,再运行能力脚本

每个提供程序目录旁都存放着对应的 SQL 脚本。正确的安装顺序是:先运行主脚本(Main)建立基础表与查询注册表,再运行该能力自己的脚本。以 SQL Server 上同时启用集群与持久化为例,依次执行:

  1. src/AdoNet/Shared/SQLServer-Main.sql
  2. src/AdoNet/Orleans.Clustering.AdoNet/SQLServer-Clustering.sql
  3. src/AdoNet/Orleans.Persistence.AdoNet/SQLServer-Persistence.sql

其他数据库与能力的脚本对应关系如下(完整清单见 adonet-configuration.md):

脚本类型SQL ServerPostgreSQLMySQL/MariaDBOracleSQLite
主脚本SQLServer-Main.sqlPostgreSQL-Main.sqlMySQL-Main.sqlOracle-Main.sqlSqlite-Main.sql
集群SQLServer-Clustering.sqlPostgreSQL-Clustering.sqlMySQL-Clustering.sqlOracle-Clustering.sql
持久化SQLServer-Persistence.sqlPostgreSQL-Persistence.sqlMySQL-Persistence.sqlOracle-Persistence.sqlSqlite-Persistence.sql
提醒SQLServer-Reminders.sqlPostgreSQL-Reminders.sqlMySQL-Reminders.sqlOracle-Reminders.sql
Grain 目录SQLServer-GrainDirectory.sqlPostgreSQL-GrainDirectory.sqlMySQL-GrainDirectory.sql
流式传输SQLServer-Streaming.sqlPostgreSQL-Streaming.sqlMySQL-Streaming.sql

并非每种能力都支持每种数据库,provider 目录中是否存在对应脚本,是判断该 Orleans 版本是否支持某数据库的权威依据。例如 Grain 目录与流式传输目前没有 Oracle 脚本;SQLite 仅覆盖本地持久化场景(Sqlite-Main.sqlSqlite-Persistence.sql)。配置前务必核实所选能力在目标数据库上有对应脚本。

[!IMPORTANT] 应使用与应用部署的 Orleans 包同一版本发布的脚本。

OrleansQuery:脚本与查询的契约机制

主脚本不只是建表。以 SQLServer-Main.sql 为例,它会创建一个OrleansQuery表(QueryKey+QueryText两列),用于注册 Orleans 运行时会用到的全部 SQL 语句;各能力脚本随后通过INSERT INTO OrleansQuery写入自己的查询定义。主脚本头部注释明确了这一契约:

  • Orleans按列名和类型读取结果按参数名和类型写入,因此脚本必须保留输入/输出的名称与类型;
  • 允许针对具体厂商做部署级调优,只要不破坏接口契约;
  • 各厂商脚本应尽量保留一致的约束名,便于排查问题;
  • ETag 是不透明的版本列,实现类型不限(SQL Server 脚本用整数实现);
  • 返回 TRUE/FALSE 的查询按“>0 为真、=0 为假”解释,异常会触发 Orleans 重试。

例如 SQLServer-Clustering.sql 创建OrleansMembershipVersionTable(以DeploymentId为主键、维护Version)与OrleansMembershipTable(记录每个 Silo 的地址、端口、代数、状态、心跳时间等),并把UpdateIAmAlivetimeKeyInsertMembershipVersionKey等查询写入OrleansQuery。运行期 provider 只通过OrleansQuery中的语句访问数据库。

生产库布局与 Schema 定制

脚本创建的是未限定名称(unqualified)的表,落在数据库用户的默认 schema 下,provider 查询也以未限定名引用这些对象。Orleans 没有提供选择 schema 或 filegroup 的配置项。如果生产库需要专用 schema、filegroup、分区或其他存储布局,必须把定制放进数据库部署流程中自行实现,并保持以下要素与 Orleans 兼容:

  • 表名、列名、参数名;
  • OrleansQuery中存储的查询及其返回结果形状(result shape)。

脚本只是起点 schema,不是放之四海皆准的生产布局。定制后的脚本与查询,应在应用启动路径之外完成应用与验证(例如先用预发布集群验证),不要把“让 Silo 在运行时自行建表”当作常规手段,也不要给 Silo 授予 schema-owner 级别的权限。schema 变更应作为受控的部署步骤执行。

配置 SQL Server

SQL Server 使用Microsoft.Data.SqlClient驱动与Microsoft.Data.SqlClientinvariant。以下示例来自官方示例片段 HostingExamples.cs(adonet_siloadonet_client两段),在同一 Silo 上同时启用集群、提醒与 Grain 存储:

var builder = Host.CreateApplicationBuilder(args); var connectionString = builder.Configuration.GetConnectionString("orleans") ?? throw new InvalidOperationException( "Connection string 'orleans' is required."); builder.UseOrleans(siloBuilder => { siloBuilder.UseAdoNetClustering(options => { options.Invariant = "Microsoft.Data.SqlClient"; options.ConnectionString = connectionString; }); siloBuilder.UseAdoNetReminderService(options => { options.Invariant = "Microsoft.Data.SqlClient"; options.ConnectionString = connectionString; }); siloBuilder.AddAdoNetGrainStorageAsDefault(options => { options.Invariant = "Microsoft.Data.SqlClient"; options.ConnectionString = connectionString; }); });

外部客户端与 Silo 使用同一个集群数据库

builder.UseOrleansClient(clientBuilder => { clientBuilder.UseAdoNetClustering(options => { options.Invariant = "Microsoft.Data.SqlClient"; options.ConnectionString = connectionString; }); });

[!IMPORTANT]System.Data.SqlClient不是 SQL Server 的 Orleans invariant。必须引用Microsoft.Data.SqlClient包并使用Microsoft.Data.SqlClientinvariant。

从源码看,UseAdoNetClustering在 Silo 侧注册 AdoNetClusteringTable 作为IMembershipTable实现,在客户端侧注册 AdoNetGatewayListProvider 作为IGatewayListProvider实现(见 AdoNetHostingExtensions.cs)。也就是说,客户端只读网关列表,不直接参与成员表写入。

Invariant是必填项,Orleans 用它选择数据库特有的查询与行为,而不是仅靠连接字符串自动推断。各能力 Option 类(如 AdoNetClusteringSiloOptions.cs)都包含ConnectionStringDataSourceInvariant三个核心属性,其中连接字符串与数据源属性带有[Redact]标记,日志输出时会自动脱敏。

配置其他数据库:PostgreSQL、MySQL/MariaDB 与 Oracle

PostgreSQL、MySQL/MariaDB 与 Oracle 的 Orleans 配置形状与 SQL Server 完全一致,只需同时替换三样东西:驱动包、invariant、SQL 脚本。官方对应关系如下:

数据库驱动包Orleans invariant
SQL ServerMicrosoft.Data.SqlClientMicrosoft.Data.SqlClient
PostgreSQLNpgsqlNpgsql
MySQL/MariaDBMySql.DataMySql.Data.MySqlClient
OracleOracle.ManagedDataAccess.CoreOracle.DataAccess.Client

此外,Orleans 还识别开源 MySQL 驱动MySqlConnector(invariant 为MySql.Data.MySqlConnector)。完整的 invariant 支持列表可以在源码 AdoNetInvariants.cs 中确认,共六项:Microsoft.Data.SqlClientNpgsqlMySql.Data.MySqlClientMySql.Data.MySqlConnectorOracle.DataAccess.ClientSystem.Data.SQLite

invariant 并不仅是字符串标记。从 DbConstantsStore.cs 可以看到,每个 invariant 都绑定了一组数据库常量:标识符转义字符(SQL Server 用[]、PostgreSQL 用""、MySQL 用`)、是否原生支持命令取消、是否为同步 ADO.NET 实现(MySQL 与 Oracle 标记为同步实现,执行时会被包装到线程池任务中),以及命令拦截器(Oracle 使用专门的OracleCommandInterceptor,用于改写 LIMIT 之类的语法差异)。这正是“invariant 决定数据库特定查询与行为”的底层机制。

配置 PostgreSQL 的示意:

builder.UseOrleans(siloBuilder => { siloBuilder.UseAdoNetClustering(options => { options.Invariant = "Npgsql"; options.ConnectionString = connectionString; }); });

MySQL/MariaDB 只需把Invariant改为MySql.Data.MySqlClient、Oracle 改为Oracle.DataAccess.Client,并分别选用对应的脚本。

使用 DbDataSource 作为连接源

每个 ADO.NET 提供程序的 Option 类型都接受连接字符串DbDataSource二选一。DbDataSource适合连接字符串无法表达驱动级配置的场景,例如需要定期刷新的认证令牌(token)。

配置原则与行为约束:

  • 恰好配置一个连接源。Orleans 会拒绝同时提供ConnectionStringDataSource、或两者都缺失的配置——这一点同时体现在配置验证器(AdoNetGrainStorageOptionsValidator)与运行时工厂 RelationalStorage.CreateInstance 中,两者都会抛出“必须二选一”的异常;
  • 即使使用数据源,仍然必须设置Invariant,因为 Orleans 要据此选择数据库特有的查询与行为;
  • 将数据源注册为singleton,并通过 provider 的OptionsBuilder配置重载解析;命名 provider 可以解析不同的keyed 数据源(keyed data source);
  • 生命周期归属:数据源由依赖注入容器或应用拥有并负责保持存活,Orleans 只打开与释放单个连接,不会释放数据源本身

从 RelationalStorage.cs 的OpenConnectionAsync可以看到两种路径的分流:配置了DbDataSource时调用_dataSource.OpenConnectionAsync(...),否则通过DbConnectionFactory.CreateConnection(invariant, connectionString)手工创建连接再OpenAsync

声明式配置(Declarative Configuration)

安装 ADO.NET 提供程序包后,会自动注册AdoNet这个声明式 provider 类型。这样便可以在配置文件(如appsettings.json)中直接声明,而无需编写代码。例如在一个应用中同时启用 AdoNet 集群、提醒与默认 Grain 存储:

{ "Orleans": { "ServiceId": "orders", "ClusterId": "orders-production", "Clustering": { "ProviderType": "AdoNet", "Invariant": "Microsoft.Data.SqlClient", "ConnectionString": "..." }, "Reminders": { "ProviderType": "AdoNet", "Invariant": "Microsoft.Data.SqlClient", "ConnectionString": "..." }, "GrainStorage": { "Default": { "ProviderType": "AdoNet", "Invariant": "Microsoft.Data.SqlClient", "ConnectionString": "..." } } } }

声明式配置与代码配置最终汇聚到同一套 Option 与 provider 构建器:从 AdoNetClusteringProviderBuilder.cs 与 AdoNetGrainStorageProviderBuilder.cs 的源码结构看,它们正是声明式配置(ProviderType: AdoNet)到UseAdoNetClustering/AddAdoNetGrainStorage的桥梁。

[!IMPORTANT] 连接字符串属于机密信息,应存放在密钥提供程序(secret provider)或部署环境变量中,而不是提交到版本库的配置文件里。

生产运维指导

  • 保持ClusterOptions.ServiceId稳定:Orleans 依据它读取应用所属的行(成员表、存储表按DeploymentId隔离)。变更 ServiceId 会使其读取不到预期数据。
  • 连接池规模:按“Silo 进程数 + 客户端进程数”的总量规划数据库连接池大小,避免连接池耗尽。
  • 安全基线:启用连接加密(如 SQL Server 的Encrypt=True),使用最小权限的数据库身份;能使用托管身份(managed identity)的场景优先使用托管身份。
  • 监控指标:持续监控数据库延迟、限流(throttling)、死锁与连接池耗尽。
  • 故障演练:在负载下测试数据库故障转移与滚动部署行为。
  • 备份策略:Grain 状态备份必须遵循应用的恢复目标(RPO/RTO);成员表(membership)行是瞬态数据,不能替代状态备份。
  • schema 升级:从旧版本升级时,检查并应用各 providerMigrations目录下的升级脚本(当前仓库中可见的如 SQLServer-Clustering-3.7.0.sql、PostgreSQL-Persistence-3.6.0.sql、PostgreSQL-Reminders-3.6.0.sql 等)。升级流程建议为:按恢复策略备份数据 → 新库先跑主脚本 → 再跑各能力脚本 → 旧 schema 升级时依次审查并执行Migrations下的脚本 → 用同驱动、同数据库引擎版本的预发布集群验证。

关于 Azure SQL 的托管身份

如果连接的是 Azure SQL,Microsoft 建议使用**托管身份(managed identities for Azure resources)**作为认证方式——它是当前最安全的认证流程之一(详见 managed-identities.md 中的官方说明)。配合上文介绍的DbDataSource方案,可以在数据源层完成基于托管身份/令牌的认证配置,从而避免在连接字符串中存放静态凭据。

延伸阅读与源码导航

  • 官方配套参考文档:ADO.NET database configuration(脚本与 invariant 总表)
  • 官方代码示例片段:HostingExamples.cs(adonet_silo/adonet_client/named_providers
  • 共享存储层(invariant 常量、连接工厂、查询执行器、数据库常量表):src/AdoNet/Shared
  • 各能力源码目录:集群 src/AdoNet/Orleans.Clustering.AdoNet、持久化 src/AdoNet/Orleans.Persistence.AdoNet、提醒 src/AdoNet/Orleans.Reminders.AdoNet、Grain 目录 src/AdoNet/Orleans.GrainDirectory.AdoNet、流式传输 src/AdoNet/Orleans.Streaming.AdoNet
  • 后端
  • 微服务

【免费下载链接】orleans

Cloud Native application framework for .NET

项目地址:https://gitcode.com/gh_mirrors/or/orleans
点击查看免费下载
上一篇:SDWebImage 手动安装指南:从源码构建 Framework、静态库与子工程集成的完整实践
下一篇:Agent Skills 开源仓库贡献指南:从 Mintlify 文档站搭建到 AI 协作披露的完整实践

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询