Files
2026-11-03 12:17:49 +08:00

102 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 独立功能插件
`Modules/` 使用 IModule,存放商城业务模块;`Plugins/` 使用 IPlugin,存放共用 API 宿主的独立功能。
公共项目 `Core/MAX.Plugins` 不依赖商城业务或数据库库,提供:
- `IPlugin`:唯一 Id、Priority、服务注册和管道装配生命周期。
- `PluginBase`:保存插件上下文、配置校验、默认管道实现;派生类只需实现 RegisterServices,按需重写 ConfigureApplication。
- `PluginContext`:插件目录、宿主环境、隔离的 Configuration 和必需配置校验。
宿主扫描加载插件,按 Priority 降序注册,显式注册 MVC Application Parts;IModule/IStartup 与 IPlugin 分开执行,禁止同一入口同时实现两套生命周期。
## 生成和部署
在仓库根目录执行,宿主无需引用具体插件:
```powershell
dotnet build Store.API/Store.Api.csproj -c Release
dotnet build Plugins/CloudProduct/Store.CloudProduct.csproj -c Release
dotnet build Plugins/Store.ImageCache/Store.ImageCache.csproj -c Release
dotnet Bin/Store.Api.dll --contentRoot "$PWD/Bin"
```
API 输出到根目录 Bin;插件生成后自动复制到 Bin/Plugins/<项目名>/。生成过程按相对路径和 SHA-256 清理宿主已提供的重复文件;插件自己的 appsettings*.json 始终保留。
宿主后生成时也会去重;同名但内容不同的依赖保留,由加载器检查版本兼容性。
Debug/Release 共用 Bin,部署前请统一使用 Release。整体拷贝 Bin 部署,需要兼容的 .NET/ASP.NET Core 运行时。
```text
Bin/
Store.Api.dll
MAX.Plugins.dll
appsettings.json
Plugins/
Store.CloudProduct/
Store.CloudProduct.dll
Store.CloudProduct.deps.json
appsettings.json
Store.ImageCache/
Store.ImageCache.dll
Store.ImageCache.deps.json
appsettings.json
```
每个部署子目录只放一个插件入口。构建会清理重命名前的旧入口文件;其他过期依赖或旧目录需要自行清理。
插件扫描配置 Plugins:Path 默认 Plugins,相对 AppContext.BaseDirectory,也支持绝对路径;可通过 Plugins__Path 覆盖。
MSBuild 属性 StoreHostOutputPath 可覆盖生成目录,应使用以分隔符结尾的绝对路径。
插件仅启动时加载,更新后重启,不支持卸载、热更新、进程隔离或冲突依赖版本隔离。
## 配置隔离
各插件只读取自身目录,按以下顺序覆盖:
1. appsettings.json(必需)。
2. appsettings.<EnvironmentName>.json(可选,例如 appsettings.Development.json)。
3. 前缀 Plugins__<Id>__ 的环境变量,例如 Plugins__CloudProduct__Search__Url。
宿主配置、其他插件配置不会并入插件配置,插件配置也不会修改宿主 IConfiguration。
配置在启动时加载,修改后重启。缺失文件、格式错误或缺失必需项时,错误包含插件身份及上下文信息。
原有配置键保持不变;原始数据相对路径改为相对于 CloudProduct 插件目录,绝对路径不变。
插件通过 Context.Configuration 读取配置。业务服务可使用按插件 Id 注册的上下文,或在插件注册时将配置绑定到专属 Options:
```csharp
public ExampleService([FromKeyedServices("CloudProduct")] PluginContext context)
{
var url = context.RequireConfiguration("Search:Url");
}
```
业务数据库和 OpenSearch 保留在各自插件内;Hangfire、认证、日志由宿主管理。
CloudProduct 的搜索启动检查使用 BackgroundService,网络错误记录日志,不阻断 HTTP 启动。
### 宿主 Hangfire 配置
宿主通过 MAX.Framework 的 AddStoreHangfire 注册共享存储和 Worker,在认证、授权中间件之后调用 UseStoreHangfire 挂载 `/hangfire`。插件只注册自己的 Job 和定时任务。
宿主 appsettings.json 必须提供 `Hangfire:ConnectionString`、`Hangfire:Dashboard:User` 和 `Hangfire:Dashboard:Pass`。可用环境变量 `Hangfire__ConnectionString`、`Hangfire__Dashboard__User`、`Hangfire__Dashboard__Pass` 覆盖。原 `Plugins__CloudProduct__Hangfire__Dashboard__*` 配置需迁移至宿主。
初始连接指向原 CloudProduct 任务库,继续使用 `Hangfire_` 表和已有任务。部署时将实际 CloudProductConnection 对应的任务库连接填入宿主配置,保留原 Job 程序集、类型、方法和定时任务 ID。Hangfire 使用独立 FreeSql 单例,云商品业务仍使用插件的 CloudProductConnection。数据库恢复后,定时任务注册失败的实例需重启以重新注册。
## 新增插件
在 Plugins 下创建类库,引用 Core/MAX.Plugins 和需要的共享业务框架,提供有无参构造函数的 PluginBase 派生类以及唯一 Id。
提供 appsettings.json,将 appsettings*.json 设置为复制到生成和发布目录。Plugins 下的公共构建配置自动携带依赖并复制到宿主目录。
无需修改 Store.API;入口程序集名称需符合 StoreHubAppTypeFinder.cs 中的过滤规则。
如需完整独立发布产物,可分别 dotnet publish -o 到自定义目录;自定义发布目录不执行 Bin 下的共享文件去重。
## 验证
```powershell
dotnet run --project Tests/PluginLoadingSmoke -- configuration
dotnet run --project Tests/PluginLoadingSmoke -- hangfire
dotnet run --project Tests/PluginLoadingSmoke -- "$PWD/Bin/Plugins"
dotnet run --project Tests/PluginLoadingSmoke -- "$PWD/Bin/Plugins/Store.ImageCache" image
dotnet run --project Tests/PluginLoadingSmoke -- <空目录或不存在目录> empty
dotnet run --project Tests/PluginLoadingSmoke -- <缺依赖或版本冲突目录> failure
```
配置验证覆盖同名键隔离、环境文件和环境变量覆盖、必需文件和配置项缺失。
加载验证覆盖两个插件的控制器、DI、数据库服务注册和业务服务构造,不连接数据库或启动后台任务。
真实启动还需数据库和 OpenSearch;外部服务不可达应结合日志判断对应功能状态。