Sparkdo.Hosting.MicrosoftExtensions
0.0.1-preview.3
dotnet add package Sparkdo.Hosting.MicrosoftExtensions --version 0.0.1-preview.3
NuGet\Install-Package Sparkdo.Hosting.MicrosoftExtensions -Version 0.0.1-preview.3
<PackageReference Include="Sparkdo.Hosting.MicrosoftExtensions" Version="0.0.1-preview.3" />
<PackageVersion Include="Sparkdo.Hosting.MicrosoftExtensions" Version="0.0.1-preview.3" />
<PackageReference Include="Sparkdo.Hosting.MicrosoftExtensions" />
paket add Sparkdo.Hosting.MicrosoftExtensions --version 0.0.1-preview.3
#r "nuget: Sparkdo.Hosting.MicrosoftExtensions, 0.0.1-preview.3"
#:package Sparkdo.Hosting.MicrosoftExtensions@0.0.1-preview.3
#addin nuget:?package=Sparkdo.Hosting.MicrosoftExtensions&version=0.0.1-preview.3&prerelease
#tool nuget:?package=Sparkdo.Hosting.MicrosoftExtensions&version=0.0.1-preview.3&prerelease
Sparkdo.Runtime.Hosting.MicrosoftExtensions
Sparkdo.Runtime.Hosting.MicrosoftExtensions 将 Sparkdo Runtime 接入 .NET Generic Host、Microsoft 依赖注入、IConfiguration、健康检查和 OpenTelemetry。它以 RuntimeHost 为唯一运行时生命周期所有者:启动时完成首次 Catalog 发布,运行中可从配置生成新输入并重协调,关闭时按 Generic Host 的时限执行排空与失败关闭。
这个包适用于常规 .NET 服务、后台进程和控制台应用。它不替 Runtime Core 注入 Microsoft.Extensions.* 依赖;所有框架相关逻辑都位于这一外层适配包。
何时选择此包
| 场景 | 推荐入口 |
|---|---|
已有 IHostApplicationBuilder,首次输入由应用直接提供 |
IServiceCollection.AddSparkdoRuntime(...) |
首次输入与后续更新都来自 IConfiguration |
配置驱动的 AddSparkdoRuntime(...) |
SecretProvider 输入、初始 Host 绑定或自定义重启处理器 |
AddSparkdoRuntimeWithConfiguration(...) |
| 单一控制台进程需要处理信号、配置重载和建议退出码 | RuntimeConsoleConfigurationHost |
| 不使用 Generic Host 或 Microsoft DI | 使用 Sparkdo.Runtime.Hosting |
安装
dotnet add package Sparkdo.Runtime.Hosting.MicrosoftExtensions
源代码方式引用时:
<ProjectReference Include="../Sparkdo.Runtime.Hosting.MicrosoftExtensions/Sparkdo.Runtime.Hosting.MicrosoftExtensions.csproj" />
该包会传递引用 Sparkdo.Runtime.Hosting、配置适配层与控制台适配层,以及所需的 Microsoft.Extensions.* 和 OpenTelemetry 抽象包。应用仍须自行提供 IRuntimeRegistrationTable 和运行时输入或输入绑定。
Generic Host 最小接线
下面的组合根适用于输入在应用启动前已经准备好的场景。registrations 必须是应用实际提供的 IRuntimeRegistrationTable:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Sparkdo.Runtime;
using Sparkdo.Runtime.Hosting;
using Sparkdo.Runtime.Hosting.MicrosoftExtensions;
var builder = Host.CreateApplicationBuilder(args);
IRuntimeRegistrationTable registrations = GetApplicationRegistrations();
builder.Services.AddSparkdoRuntime(
registrations,
options: new RuntimeOptions(),
initialInputs: CatalogInputs.Empty);
// AddSparkdoRuntime 已登记 RuntimeHost 的 IHostedService;此调用用于显式校验组合顺序。
builder.UseSparkdoRuntime();
using var app = builder.Build();
await app.RunAsync();
GetApplicationRegistrations() 代表应用组合根中的实际注册表提供方式,不是该包提供的 API。AddSparkdoRuntime 已经登记 RuntimeHost 和对应 IHostedService;UseSparkdoRuntime 是幂等的显式接线点,但必须在 AddSparkdoRuntime 之后调用,否则会抛出 InvalidOperationException。
启动后可从容器取得同一实例:
var runtimeHost = app.Services.GetRequiredService<RuntimeHost>();
if (runtimeHost.Status == RuntimeHostStatus.Started && runtimeHost.Runtime is { } runtime)
{
// 使用 runtime。
}
不要自行创建第二个 RuntimeHost。同一 IServiceCollection 只能注册一个 Sparkdo RuntimeHost,重复注册会抛出 InvalidOperationException。
配置驱动的首次输入与重载
配置重载入口把 IConfiguration 与一组 RuntimeConfigurationBinding 连接为首次 CatalogInputs 和后续候选输入:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Sparkdo.Runtime;
using Sparkdo.Runtime.Configuration;
using Sparkdo.Runtime.Hosting.MicrosoftExtensions;
static IHost BuildHost(
string[] args,
IRuntimeRegistrationTable registrations,
IEnumerable<RuntimeConfigurationBinding> bindings)
{
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSparkdoRuntime(
registrations,
builder.Configuration,
bindings,
options: new RuntimeOptions());
builder.UseSparkdoRuntime();
return builder.Build();
}
每个 RuntimeConfigurationBinding 明确描述一个输入路由:Route、Kind、Schema、Source、配置键 Key、必填性 Required 与来源 Origin。绑定不是按配置树自动发现的;应用应只为已注册 Capability/Input 声明明确、稳定的路由。
当前 Microsoft 配置适配仅接受 json InputKindId。非机密配置值必须是有效 JSON;缺少必填值、重复路由、无效键、超出输入限制或与已注册输入定义不匹配都会使绑定被拒绝。不要把未验证的配置正文写入日志。
机密引用、Host 绑定与重启处理器
需要 SecretProvider 输入或自定义宿主控制时,使用高级入口:
using System.Collections.Immutable;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Sparkdo.Runtime;
using Sparkdo.Runtime.Configuration;
using Sparkdo.Runtime.Configuration.MicrosoftExtensions;
using Sparkdo.Runtime.Hosting;
using Sparkdo.Runtime.Hosting.MicrosoftExtensions;
static void AddConfiguredRuntime(
IServiceCollection services,
IRuntimeRegistrationTable registrations,
IConfiguration configuration,
IEnumerable<RuntimeConfigurationBinding> bindings,
HostBindingSnapshot? initialHostBindings,
IRuntimeHostRestartHandler restartHandler,
ImmutableArray<RuntimeConfigurationSecretBinding> secretBindings,
IRuntimeConfigurationSecretReferenceResolver secretReferenceResolver)
{
var startupOptions = new RuntimeConfigurationHostStartupOptions(
InitialHostBindings: initialHostBindings,
RestartHandler: restartHandler,
SecretBindings: secretBindings,
SecretReferenceResolver: secretReferenceResolver);
services.AddSparkdoRuntimeWithConfiguration(
registrations,
configuration,
bindings,
options: new RuntimeOptions(),
startupOptions);
}
对于每条 InputSourceScope.SecretProvider 路由,必须提供唯一的 RuntimeConfigurationSecretBinding,并提供 IRuntimeConfigurationSecretReferenceResolver。解析器只能返回目标机密存储中的引用键,不能返回或记录机密正文。同步配置重载不适合 SecretProvider;高级入口会使用可取消的异步解析路径。
InitialHostBindings 会参与首次发布,后续 RuntimeHost 更新会保留已接受的 Host 绑定快照。RestartHandler 用于接收 RuntimeReason 并请求最外层宿主重启;处理器必须实际请求停止或替换进程,不能用无操作实现吞掉重启信号。
Generic Host 生命周期
调用 AddSparkdoRuntime 后,容器中会有:
| 注册项 | 作用 |
|---|---|
RuntimeHost 单例 |
当前进程唯一的运行时宿主。 |
IRuntimeRegistrationTable 单例 |
应用提供的注册表。 |
IRuntimeHostRestartHandler |
使用显式处理器;未提供时使用基于 IHostApplicationLifetime 的默认处理器。 |
RuntimeHostHostedService |
在 Generic Host 启动和停止阶段调用 RuntimeHost。 |
RuntimeConfigurationReloadHostedService |
仅配置入口注册;合并配置变更并提交候选 Catalog。 |
| 健康检查和 OpenTelemetry 注册 | 由 AddSparkdoRuntimeObservability 自动登记。 |
启动顺序如下:
- Generic Host 启动
RuntimeHostHostedService。 - 服务调用
RuntimeHost.StartAsync,创建 Runtime、创建首次 Catalog 并提交首次重协调。 - 只有首次发布成功,Generic Host 才继续正常运行;此时
RuntimeHost.Status为Started,CurrentRevision非空。 - 配置入口在 Runtime 成功首次发布后处理已合并的配置变更,使用当前
CatalogRevision调用UpdateCatalogIfCurrentAsync,避免旧配置快照覆盖较新的发布。
首次启动被拒绝时,托管服务会记录结构化原因并抛出 InvalidOperationException,因此 IHost.StartAsync 或 RunAsync 会失败。异常的 Data 包含 runtime.host.start-result 和 runtime.reason-code,供最外层启动诊断使用;应用不应依赖文本消息解析原因。
配置重载中的绑定失败、Catalog 拒绝、非成功重协调或宿主不可用会触发失败关闭:Runtime 不再对外可用,并请求 IHostApplicationLifetime.StopApplication()。配置监听器合并高频变更,且启动窗口内到达的变更会在首次发布后处理,不会丢失为一条抢跑更新。
停止与重启
Generic Host 停止时,适配器会从 HostOptions.ShutdownTimeout 中为其他停止参与者预留时间,再调用 RuntimeHost.StopAsync。停止结果不是 RuntimeStopStatus.Stopped、内部停止预算耗尽,或 Generic Host 的关闭令牌先到期时,宿主都会进入失败关闭;不能把该实例重新标记为健康或继续接纳流量。
重协调返回 RestartRequested 或 Quarantined 时,RuntimeHost 调用 IRuntimeHostRestartHandler。默认处理器会先将 Runtime 失败关闭,再调用 IHostApplicationLifetime.StopApplication()。该调用只请求当前 Host 停止,并不会自行启动新进程;生产部署必须由服务管理器、编排平台或外部监督器根据退出和健康状态创建替换实例。
如果停止请求没有被宿主确认,或重启处理器抛出异常,适配器会执行有界失败关闭并保留失败状态。不要在自定义重启处理器中返回成功后继续让原进程提供服务。
健康检查与 OpenTelemetry
AddSparkdoRuntime 会自动调用 AddSparkdoRuntimeObservability。该方法可安全重复调用;它登记日志、Metrics、OpenTelemetry 源和健康检查,但不配置任何导出器。应用仍应在自己的组合根中配置 OTLP、Prometheus 或其他导出器。
健康检查
两个健康检查按稳定标签注册:
| 标签常量 | 标签值 | 健康含义 |
|---|---|---|
RuntimeHostHealthCheckTags.Liveness |
live |
除 Failed 和 Stopped 外为健康,表示宿主生命周期仍存活。 |
RuntimeHostHealthCheckTags.Readiness |
ready |
仅当状态为 Started、Runtime 非空且 CurrentRevision 非空时健康,表示可以接纳业务流量。 |
应用可以通过 HealthCheckService 按标签执行检查:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Sparkdo.Runtime.Hosting.MicrosoftExtensions;
var healthChecks = app.Services.GetRequiredService<HealthCheckService>();
var readiness = await healthChecks.CheckHealthAsync(
registration => registration.Tags.Contains(RuntimeHostHealthCheckTags.Readiness),
cancellationToken);
该包不会替 ASP.NET Core 映射 HTTP 健康检查端点;Web 应用应在自身的 Web 管道中按 live 和 ready 标签映射对应端点。
遥测信号
适配器注册的 ActivitySource 与 Meter 名称均为 Sparkdo.Runtime.Hosting。生命周期操作会产生:
| 信号 | 名称 | 说明 |
|---|---|---|
| Activity | sparkdo.runtime.host.start |
首次启动操作。 |
| Activity | sparkdo.runtime.host.stop |
停止和排空操作。 |
| Counter | sparkdo.runtime.host.operations |
生命周期操作计数。 |
| Histogram | sparkdo.runtime.host.operation.duration |
生命周期操作耗时,单位为秒。 |
| Observable Gauge | sparkdo.runtime.host.readiness |
就绪状态,1 为就绪,0 为未就绪。 |
Counter 与 Histogram 使用低基数标签:sparkdo.runtime.operation、sparkdo.runtime.outcome 和 sparkdo.runtime.host.status。不要把租户、配置正文、机密引用或高基数输入值附加到这些信号。
控制台与配置一体化宿主
RuntimeConsoleConfigurationHost 适合不使用 Generic Host、但需要同一控制台进程处理配置首次绑定、配置重载、信号、停止与建议退出码的程序:
using Microsoft.Extensions.Configuration;
using Sparkdo.Runtime;
using Sparkdo.Runtime.Configuration;
using Sparkdo.Runtime.Hosting.MicrosoftExtensions;
static async Task<int> RunConsoleAsync(
IRuntimeRegistrationTable registrations,
IConfiguration configuration,
IEnumerable<RuntimeConfigurationBinding> bindings,
CancellationToken cancellationToken)
{
await using var host = new RuntimeConsoleConfigurationHost(
registrations,
configuration,
bindings,
new RuntimeConsoleConfigurationHostOptions(
RuntimeOptions: new RuntimeOptions(),
ShutdownTimeout: TimeSpan.FromSeconds(30)));
var result = await host.RunWithResultAsync(cancellationToken);
return result.SuggestedExitCode;
}
该类型不会直接调用 Environment.Exit;调用方负责把 ConsoleRuntimeRunResult.SuggestedExitCode 交给进程入口。配置重载要求 HostRestart 时,结果保留建议退出码 75;调用方取消的正常终止建议为 0;不可恢复的宿主或配置失败建议为 1。控制台宿主在成功首次发布后才处理已合并的配置变更,并在处置时为重载工作和控制台停止共享一个总关闭预算。
RuntimeConsoleConfigurationHostOptions 还提供 InitialHostBindings、StopOptions、SecretBindings、SecretReferenceResolver 与 Logger。机密输入的约束与 Generic Host 高级配置入口相同。
依赖与边界
该包负责把 Runtime 接入 Microsoft 生态,但不负责:
- 生成或维护应用的
IRuntimeRegistrationTable; - 定义业务 Capability、输入路由、Schema 或配置来源身份;
- 选择并配置 OpenTelemetry 导出器;
- 映射 Web 健康检查端点;
- 自行拉起新的进程或实现部署平台的重启策略。
将这些决策保留在应用组合根和部署层,可使 Runtime 的更新、健康状态与外部监督器行为保持一致。
验证
在仓库根目录执行:
dotnet build src/runtime/src/Sparkdo.Runtime.Hosting.MicrosoftExtensions/Sparkdo.Runtime.Hosting.MicrosoftExtensions.csproj --configuration Release
dotnet test src/runtime/test/Sparkdo.Runtime.Specification.Tests/Sparkdo.Runtime.Specification.Tests.csproj --configuration Release --filter "FullyQualifiedName~RuntimeHostingAdapterTests"
测试覆盖 Generic Host 启停、启动拒绝传播、配置首次绑定与重载、重启退出码、关闭预算、健康检查与 OpenTelemetry 生命周期信号。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Configuration (>= 10.0.8)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Configuration.EnvironmentVariables (>= 10.0.8)
- Microsoft.Extensions.Configuration.UserSecrets (>= 10.0.8)
- Microsoft.Extensions.DependencyInjection (>= 10.0.8)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Diagnostics (>= 10.0.8)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.8)
- Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions (>= 10.0.8)
- Microsoft.Extensions.FileProviders.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Hosting (>= 10.0.8)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Logging (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Options (>= 10.0.8)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.8)
- OpenTelemetry (>= 1.16.0)
- OpenTelemetry.Extensions.Hosting (>= 1.16.0)
- Sparkdo.Configuration (>= 0.0.1-preview.3)
- Sparkdo.Configuration.MicrosoftExtensions (>= 0.0.1-preview.3)
- Sparkdo.Console (>= 0.0.1-preview.3)
- Sparkdo.Hosting (>= 0.0.1-preview.3)
- Sparkdo.Runtime.Contracts (>= 0.0.1-preview.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1-preview.3 | 43 | 8/26/2026 |
| 0.0.1-preview.2 | 53 | 8/25/2026 |
| 0.0.1-preview.1 | 55 | 8/25/2026 |