- CMS
- 后端
- Web框架
【免费下载链接】OrchardCore
Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
导读
Auto Setup(OrchardCore.AutoSetup)是 Orchard Core 框架内置的一个基础设施级功能模块,它让应用(Application)与其多租户(Tenant)站点能够在首次收到请求时自动完成安装,无需人工打开安装向导填写表单。本文以官方模块文档为主体,结合仓库内模块源码、Web 宿主工程与单元测试,完整讲解appsettings.json配置参数、User Secrets 与环境变量注入、功能启用方式、以及多实例共享数据库场景下的分布式锁保证,帮助你在开发、CI/CD 与生产交付中实现"零手工介入"的站点初始化。
模块定位与核心机制
AutoSetup 模块位于 src/OrchardCore.Modules/OrchardCore.AutoSetup,从其 Manifest.cs 可以看到它被归类为Infrastructure类别,依赖OrchardCore.Setup模块,描述为"允许自动安装应用/租户"。
它本质上是一个按需(on-demand)安装机制:不是应用启动时就同步安装所有站点,而是在某个租户的 Shell 处于未初始化(Uninitialized)状态、且首个请求到达时,由中间件(Middleware)触发安装流程。核心执行链路由 AutoSetupMiddleware.cs 与 AutoSetupService.cs 构成:
- 中间件根据当前请求对应的
ShellSettings名称,在配置的Tenants列表中匹配TenantSetupOptions; - 若 Shell 未初始化,先尝试获取分布式锁(保证多实例环境下的原子性),再次确认 Shell 仍为未初始化后调用
IAutoSetupService.SetupTenantAsync; - 安装成功后:若当前是
Default根租户,则提前为其余租户创建 Shell 配置(不安装),其余租户之后在各自首次请求时按需安装; - 成功响应会重定向(
302)回站点根路径,失败则返回503 Service Unavailable。
JSON 配置参数:在 appsettings.json 中声明安装清单
AutoSetup 的全部参数都定义在配置节OrchardCore:OrchardCore_AutoSetup之下(配置节名硬编码于 Startup.cs 的ConfigSectionName常量)。官方文档给出的appsettings.json完整示例:
{ "OrchardCore": { "OrchardCore_AutoSetup": { "AutoSetupPath": "", "Tenants": [ { "ShellName": "Default", "SiteName": "AutoSetup Example", "SiteTimeZone": "Europe/Amsterdam", "AdminUsername": "admin", "AdminEmail": "info@orchardproject.net", "AdminPassword": "OrchardCoreRules1!", "DatabaseProvider": "Sqlite", "DatabaseConnectionString": "", "DatabaseTablePrefix": "", "RecipeName": "SaaS" }, { "ShellName": "AutoSetupTenant", "SiteName": "AutoSetup Tenant", "SiteTimeZone": "Europe/Amsterdam", "AdminUsername": "tenantadmin", "AdminEmail": "tenant@orchardproject.net", "AdminPassword": "OrchardCoreRules1!", "DatabaseProvider": "Sqlite", "DatabaseConnectionString": "", "DatabaseTablePrefix": "tenant", "RecipeName": "Agency", "RequestUrlHost": "", "RequestUrlPrefix": "tenant", "FeatureProfile": "my-profile" } ] } } }顶层参数
| 参数 | 说明 |
|---|---|
AutoSetupPath | 触发每个租户 AutoSetup 的 URL。若为空,则在该租户的首个请求(如/、/tenant-prefix)时自动触发安装 |
Tenants | 需要安装的租户列表 |
每个租户的参数
| 参数 | 说明 |
|---|---|
ShellName | 租户的技术名称(Shell / Tenant 名)。不能为空,且只能包含字符(源码校验规则为^\w+$正则,不允许空格)。默认租户必须使用"Default" |
SiteName | 站点名称 |
AdminUsername | 租户超级用户的用户名 |
AdminEmail | 租户超级用户的邮箱 |
AdminPassword | 租户超级用户的密码 |
DatabaseProvider | 数据库提供程序(如Sqlite、SqlServer、Postgres等,需与项目注册的提供程序一致) |
DatabaseConnectionString | 连接字符串 |
DatabaseTablePrefix | 数据库表前缀,可用于在同一数据库中安装多个租户(如示例中租户使用tenant前缀以与默认站点隔离) |
RecipeName | 租户安装使用的 Recipe(配方)名称,如SaaS、Agency、Blank等 |
RequestUrlHost | 租户绑定的主机名(Host) |
RequestUrlPrefix | 租户的 URL 前缀 |
FeatureProfile | 可选,租户默认使用的功能配置文件(Feature Profile)名称;仅在使用"Feature Profiles"功能时适用,详见 Tenants 模块文档 |
!!! note -Tenants数组必须包含ShellName等于Default的根租户。 - 每个租户都是按需安装(在租户的首次请求时安装)。 - 若提供了AutoSetupPath,则必须用它来触发每个租户的安装,例如: -/autosetup—— 触发根租户(Root tenant)的安装; -/mytenant/autosetup—— 自动安装mytenant。
源码中的参数校验规则
结合 AutoSetupOptions.cs 与 TenantSetupOptions.cs,配置在启动时会被IValidatableObject校验,以下规则值得注意:
AutoSetupPath若不为空,必须以/开头;Tenants列表不能为空,且有且仅有一个IsDefault(即ShellName为Default)的租户;ShellName必须匹配^\w+$(非空、纯单词字符、无空格),且非默认租户不得与Default冲突;RequestUrlPrefix不能包含多于一个路径段(不能含/);SiteName、AdminUsername、AdminEmail、AdminPassword、RecipeName、SiteTimeZone均为必填;DatabaseProvider必须是已注册的有效提供程序;若该提供程序要求连接字符串(HasConnectionString),则DatabaseConnectionString必填;LockOptions.LockExpiration与LockOptions.LockTimeout必须大于零。
此外,从源码可以看到租户配置还支持一个文档表格未列出的DatabaseSchema字段(对应OrchardCore.Data的 Schema 概念),在TenantSetupOptions与安装上下文SetupContext中均会传递,可视为实现层面的补充能力。
敏感信息处理:User Secrets 与环境变量
如果你的 JSON 配置包含敏感信息(如管理员密码),或不想将其提交到仓库(例如并非整个开发团队都使用 AutoSetup),官方文档推荐使用User Secrets或环境变量代替。
使用 User Secrets(本地开发)
User Secrets 仅在本地开发时可用,以 JSON 文件形式存储。你可以把整个配置节原样搬进secrets.json;也可以逐项通过命令行设置(这会扁平化secrets.json中的已有结构):
cd src/OrchardCore.Cms.Web dotnet user-secrets init dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:ShellName" "Default" dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:SiteName" "AutoSetup Example" dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:SiteTimeZone" "Europe/Amsterdam" dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:AdminUsername" "admin" dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:AdminEmail" "info@orchardproject.net" dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:AdminPassword" "OrchardCoreRules1!" dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:RecipeName" "SaaS" dotnet user-secrets set "OrchardCore:OrchardCore_AutoSetup:Tenants:0:DatabaseProvider" "Sqlite"如果你基于 Orchard Core 完整源码工作(如贡献代码),由于 OrchardCore.Cms.Web.csproj 预配置了UserSecretsId,上述设置对所有源码副本都生效——这对参与 Orchard Core 开发非常有用。如果想去掉该行为,只需删除对应副本OrchardCore.Cms.Web.csproj中的UserSecretsId元素即可。
使用环境变量(服务器与本地均可用)
环境变量在服务器和本地机器上都可用;但如果你有多个项目,必须加前缀以避免冲突。配置键使用双下划线__作为层级分隔符:
"OrchardCore__OrchardCore_AutoSetup__AutoSetupPath": "" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__ShellName": "Default" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__SiteName": "AutoSetup Example" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__SiteTimeZone": "Europe/Amsterdam" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__AdminUsername": "admin" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__AdminEmail": "info@orchardproject.net" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__AdminPassword": "OrchardCoreRules1!" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__DatabaseProvider": "Sqlite" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__DatabaseConnectionString": "" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__DatabaseTablePrefix": "" "OrchardCore__OrchardCore_AutoSetup__Tenants__0__RecipeName": "SaaS" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__ShellName": "AutoSetupTenant" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__SiteName": "AutoSetup Tenant" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__SiteTimeZone": "Europe/Amsterdam" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__AdminUsername": "tenantadmin" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__AdminEmail": "tenant@orchardproject.net" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__AdminPassword": "OrchardCoreRules1!" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__DatabaseProvider": "Sqlite" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__DatabaseConnectionString": "" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__DatabaseTablePrefix": "" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__RecipeName": "Agency" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__RequestUrlHost": "" "OrchardCore__OrchardCore_AutoSetup__Tenants__1__RequestUrlPrefix": "tenant"本地快速启动验证
出于测试目的,你可以把上述环境变量加入OrchardCore.Cms.Web项目launchSettings.json中名为web的 profile,然后启动:
dotnet run --launch-profile web启用 Auto Setup 功能
要启用 Auto Setup 功能,需要在 Web 项目的启动文件中注册对应 Setup 特性:
public void ConfigureServices(IServiceCollection services) { services .AddOrchardCms() .AddSetupFeatures("OrchardCore.AutoSetup"); }AddSetupFeatures扩展方法定义于 OrchardCoreBuilderExtensions.cs,用于在默认租户上注册一组用于安装、配置实际租户的特性。需要说明的现状是:
- 该特性在源码自带的默认项目(OrchardCore.Cms.Web/Program.cs)中默认启用(源码中直接链式调用了
.AddSetupFeatures("OrchardCore.AutoSetup")); - 但在应用模板(application templates)生成的自定义项目中默认不启用,以避免自定义项目出现意外行为。因此基于模板新建的项目需要手动添加上述代码。
多实例场景:使用分布式锁保证原子安装
如果多个 OrchardCore 实例共享同一个数据库同时启动,就可能出现并发触发安装的竞态,因此需要一个分布式锁来保证自动安装的原子性。
此时应在启动文件中同时启用Redis Lock特性与 AutoSetup 特性:
public void ConfigureServices(IServiceCollection services) { services .AddOrchardCms() .AddSetupFeatures("OrchardCore.Redis.Lock", "OrchardCore.AutoSetup"); }同时务必通过环境变量或配置文件设置 Redis 连接字符串:
"OrchardCore__OrchardCore_Redis__Configuration": "192.168.99.100:6379,allowAdmin=true"分布式锁的源码行为
从 AutoSetupMiddleware.cs 可以看到,锁获取失败时会抛出TimeoutException(信息形如Fails to acquire an auto setup lock for the tenant: {ShellName});成功获取锁后,中间件还会通过IShellSettingsManager.LoadSettingsAsync复查该租户是否已被其他实例安装——若已被安装则重新加载 Shell 上下文并返回503。锁名称统一为AUTOSETUP_LOCK,具体获取逻辑见 DistributedLockExtensions.cs。
值得注意的实现细节:若当前注入的锁是本地锁(ILocalLock),则超时与过期时间直接取TimeSpan.MaxValue;只有真正的分布式锁才使用下面配置的超时/过期参数,未配置时默认 60 秒。这些行为都被 AutoSetupMiddlewareTests.cs 中的单元测试覆盖(如未初始化 Shell 执行安装、安装失败返回 503、锁获取失败抛出超时异常、已初始化 Shell 跳过安装等)。
可选锁参数
锁配置参数可选,可通过环境变量或配置文件设置:
| 参数 | 说明 | 默认值 |
|---|---|---|
LockTimeout | 获取分布式自动安装锁的超时时间(毫秒) | 60 秒 |
LockExpiration | 分布式安装锁的过期时间(毫秒) | 60 秒 |
"OrchardCore__OrchardCore_AutoSetup__LockOptions__LockTimeout": "10000" "OrchardCore__OrchardCore_AutoSetup__LockOptions__LockExpiration": "10000"对应配置类为 LockOptions.cs,位于AutoSetupOptions.LockOptions之下(参见 AutoSetupOptions.cs)。
安装流程与源码佐证
中间件如何按路径触发
Startup.cs 的Configure方法只在 Shell 未初始化时挂载安装逻辑,并且会先做配置校验:
- 若
AutoSetupPath为空,则直接app.UseMiddleware<AutoSetupMiddleware>()——即对所有请求生效,命中即触发安装; - 若
AutoSetupPath非空,则使用app.MapWhen仅在该路径前缀匹配时挂载中间件——即/autosetup、/mytenant/autosetup这类显式触发地址。
配置存在但校验失败时,会记录错误日志"AutoSetup did not start, configuration has following errors: ..."并跳过中间件注册。
安装上下文如何组装
AutoSetupService.cs 负责把TenantSetupOptions转换为SetupContext:从ISetupService.GetSetupRecipesAsync()中按RecipeName匹配 Recipe,并把管理员账号、数据库提供程序、连接字符串、表前缀、站点名称、时区等写入SetupContext.Properties(键来自SetupConstants)。对于Default根租户还会同步RequestUrlHost/RequestUrlPrefix。安装完成后根据setupContext.Errors是否为空判定成败并记录对应日志。
其余租户的设置何时创建
根租户安装成功后,中间件会遍历Tenants列表,为其他租户调用CreateTenantSettingsAsync——该方法通过 IShellSettingsManager 创建未初始化的ShellSettings(写入连接字符串、表前缀、Schema、数据库提供程序、随机Secret、RecipeName、FeatureProfile等)并注册到 Shell Host。这样,后续每个租户在首次请求时才真正触发各自的安装(on-demand),实现"根租户先装、子租户按需装"的渐进式初始化。
延伸阅读
如需了解空站点(Empty Site)的手动安装流程与 Setup 模块的更多细节,可参考:
- OrchardCore.Setup —— 设置空站点
- Tenants 模块文档(Feature Profiles 说明)
另外,模块的完整单元测试位于 test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs,是理解中间件各分支行为(跳过安装、执行安装、安装失败、锁获取失败)的最佳参考。
- CMS
- 后端
- Web框架
【免费下载链接】OrchardCore
Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
相关推荐
OrchardCore AutoSetup 无人值守自动安装指南:环境变量驱动的一键租户初始化
OrchardCore AutoSetup 无人值守自动安装指南:环境变量驱动的一键租户初始化 导读 AutoSetup(无人值守安装)是 OrchardCor
CMS后端Web框架如何在现有应用中用 vanilla tRPC 客户端通过 httpBatchLink 完成首次类型安全请求
如何在现有应用中用 vanilla tRPC 客户端通过 httpBatchLink 完成首次类型安全请求 如果你的应用不是 React 或 Next.js 环
后端RPC框架前端OrchardCore 功能测试实战:AutoSetup 无值守建站与 playwright-cli 浏览器自动化验证
OrchardCore 功能测试实战:AutoSetup 无值守建站与 playwright cli 浏览器自动化验证 本篇指南讲解如何在 OrchardCor
CMS后端Web框架
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考