配置与选项
本章讲应用与框架怎样读配置:.NET 原生配置源与选项、XiHan:<领域> 配置节、挂载的配置目录与热更新、资源绑定、远程配置与密钥。适用于编写特性、准备部署配置的开发者。
完整 API 见 Configuration.Abstractions 与 Configuration.Nacos 包页。
配置模型
框架不另造配置模型。应用与框架都读 Microsoft.Extensions.Configuration 的 IConfiguration,配置源仍是 appsettings.json、appsettings.<环境>.json、环境变量与命令行这些 .NET 原生来源,没有「默认配置包」。Configuration.Abstractions 只定义两个 Provider 契约(远程配置客户端与密钥库)和把它们接进 IConfigurationBuilder 的配置源。
框架包的选项是带 ConfigurationSection 常量的 record(KernelOptions、LocalizationOptions、FileSystemObjectStorageOptions 等),由各自的静态方法 FromConfiguration(IConfiguration) 逐键读取,不经反射绑定,因而在 Native AOT 下照常工作。特性在装配时读取一次并登记为单例:AddXiHan 返回之后再改 XiHan:* 下的键,要重启才对框架生效。命名存储实例是例外,它的定义在首次取用时才从 XiHan:ObjectStorage:Stores:<name> 读取(见对象存储)。
AddXiHan 在调用时就求解能力图谱、解析绑定、装配全部特性,所以远程配置、密钥这类配置源必须在 AddXiHan 之前加入 builder.Configuration,否则框架的选项与绑定读不到它们。
配置节命名
框架的配置节一律以 XiHan:<领域> 开头,领域词取自规范术语表(Kernel、Persistence、Caching、Localization、ObjectStorage、Configuration 等)。实现包的配置在领域节下再加一段实现名,例如 XiHan:Caching:Redis、XiHan:ObjectStorage:FileSystem;领域节本身放抽象层的选项,例如 XiHan:Localization:DefaultLocale。特性清单的 Contributes.Config 声明它在本领域里读取的配置的最近公共节:只读自己子节的写子节(Caching.Hybrid 写 XiHan:Caching:Hybrid),同时读领域节下的公共选项的写领域节(Caching.Redis 还读 XiHan:Caching:Idempotency,写 XiHan:Caching),见 RFC-0002「配置节」。
| 写法 | 例子 |
|---|---|
| JSON | { "XiHan": { "Kernel": { "StopTimeoutSeconds": 25 } } } |
| 配置键 | XiHan:Kernel:StopTimeoutSeconds |
| 环境变量 | XiHan__Kernel__StopTimeoutSeconds=25 |
时长类的键带单位后缀(StopTimeoutSeconds、RefreshIntervalSeconds、MultipartExpiryHours),在代码里对应 TimeSpan 属性。值不合法(负数、无法解析的枚举或布尔值)时 FromConfiguration 抛出 ArgumentException,应用在启动期失败。
应用自己的配置节用自己的名字,不放进 XiHan 下,例如 KubernetesApp 示例的 Sample。
应用自己的选项
应用的选项照常用 IOptions<T> / IOptionsMonitor<T> 绑定。需要随配置文件变化而更新的值,注入 IOptionsMonitor<T> 并读 CurrentValue。下面的代码取自 KubernetesApp 示例,略去了与配置无关的部分:
// BannerOptions.cs
namespace KubernetesApp;
public sealed class BannerOptions
{
public const string Section = "Sample";
public string Banner { get; set; } = "Hello from XiHan";
}// Program.cs
using KubernetesApp;
using Microsoft.Extensions.Options;
using XiHan.Framework.Hosting.AspNetCore;
using XiHan.Framework.Profiles.Full;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<BannerOptions>(builder.Configuration.GetSection(BannerOptions.Section));
// AddXiHan 先装载 XIHAN_CONFIG_PATH 目录里的 JSON 文件并监听变化
builder.AddXiHan(xihan => xihan.UseFullProfile());
var app = builder.Build();
app.UseXiHan();
// 挂载文件里的 Sample:Banner 改了,CurrentValue 随之变化,不必重启
app.MapGet("/", (IOptionsMonitor<BannerOptions> banner) => banner.CurrentValue.Banner);
app.Run();{
"Sample": {
"Banner": "Hello from appsettings.json"
}
}挂载的配置目录与热更新
环境变量 XIHAN_CONFIG_PATH 指向一个目录时(Kubernetes 里是 ConfigMap 的挂载点),Hosting.AspNetCore 与 Hosting.CommandLine 的 AddXiHan 把其中的 JSON 文件作为配置源插在 appsettings.{环境}.json 之后,并以 reloadOnChange: true 监听变化。找文件的规则在内核的 ConfigurationDirectory.Resolve:
- 只取目录顶层的
*.json,跳过以.开头的条目(ConfigMap 挂载工具放置的..data等)。 appsettings.json最先装载,其余文件按文件名的序数顺序随后装载,后装载的覆盖先装载的同名键。- 目录不存在或环境变量为空时什么都不加。
这些文件紧接构建器里最后一个 appsettings 文件源(appsettings.json 或 appsettings.{环境}.json)插入。WebApplication.CreateBuilder 与 Host.CreateApplicationBuilder 的配置源因此从低到高是:
| 顺序 | 配置源 |
|---|---|
| 1 | appsettings.json |
| 2 | appsettings.{环境}.json |
| 3 | XIHAN_CONFIG_PATH 目录里的 JSON 文件 |
| 4 | 用户机密(仅开发环境) |
| 5 | 环境变量 |
| 6 | 命令行参数 |
| 7 | 应用自己添加的配置源(远程配置、密钥等),按添加顺序 |
后者覆盖前者:挂载文件覆盖 appsettings;同一个键同时出现在挂载文件与环境变量里时,环境变量的值生效。xihan pack 用环境变量写的 XiHan__Kernel__StopTimeoutSeconds 因此不会被 ConfigMap 里的同名键改掉。构建器里没有 appsettings 文件源(应用关掉了默认配置)时,目录里的文件追加在末尾。文件列表在启动时确定,运行中新增的文件要重启才装载;已装载文件的内容变化会触发 IConfiguration 的重载令牌,IOptionsMonitor<T> 随之更新。
ConfigMap 更新要用轮询监视
kubelet 更新 ConfigMap 时切换的是符号链接,默认的文件系统通知收不到变化。容器里要设 DOTNET_USE_POLLING_FILE_WATCHER=1;xihan pack 按应用清单的 config 生成 ConfigMap 时会一并写入它与 XIHAN_CONFIG_PATH(挂载点缺省 /etc/xihan)。
热更新只作用于读 IConfiguration 或 IOptionsMonitor<T> 的代码。框架包的选项在装配时已经读完,改挂载文件里的 XiHan:* 键不会改变正在运行的特性。部署侧的生成规则见部署与打包。
资源绑定
特性需要的外部资源(数据库连接、Redis、消息代理、对象存储端点)在清单的 Bindings 里按名字声明,宿主在装配时解析出 BindingValue(名字、类型、主值与其余属性),特性用 context.GetBinding(name) 或 context.TryGetBinding(name) 取用。这样同一个能力包在本地、Compose 与 Kubernetes 里不改代码,只换绑定的来源。
内核的 BindingResolver.Resolve 按下面的顺序收集绑定:
- 环境变量
SERVICE_BINDING_ROOT指向的目录(Service Binding 规范)。每个子目录是一个绑定,目录名是绑定名;目录里每个文件是一个属性,文件名是属性名、内容修剪首尾空白后是值;type文件是类型,uri文件既是主值也保留为属性;以.开头的文件跳过。AppBuilder.UseServiceBindingRoot(directory)可以在代码里改用别的目录。 - 配置节
XiHan:Bindings:<name>。节本身的标量值或子键value是主值,子键type是类型,其余子键是属性。
同名时配置整体覆盖目录来源,不逐属性合并。
{
"XiHan": {
"Bindings": {
"cache": "localhost:6379",
"db": {
"type": "connection:relational",
"value": "Host=localhost;Database=orders;Username=dev;Password=dev-password"
}
}
}
}环境变量写法是 XiHan__Bindings__db__value、XiHan__Bindings__db__type,Compose 与 Aspire 的生成产物就是这样注入的。
清单里 required: true 的绑定在 AddXiHan 构建时校验:缺失,或来源声明了类型而与清单不一致,都抛出 KERNEL_HOSTING_001,应用不会启动。来源没有声明类型(空字符串)时不比对类型。可选绑定由特性自己用 TryGetBinding 处理。
框架内置包声明的绑定都是可选的。绑定来自部署环境,给出的连接信息(主值)与凭据(下表的属性)逐项覆盖 Provider 配置节里的同类键:绑定里有这一项就用绑定的,没有就读配置节的;前缀、超时、分组等不是连接与凭据的键照读配置节。绑定的主值或属性为空白时不算给出;凭据属性与主值互不依赖,绑定只给凭据、连接来自配置节也照样覆盖凭据;两者都没有连接时装配失败。属性名区分大小写,按表里的写;凭据不进日志与错误消息(RFC-0016「资源绑定与配置节」):
| 绑定名 | 类型 | 声明它的包 | 用法 |
|---|---|---|---|
db | connection:relational | Persistence.EntityFrameworkCore、Persistence.SqlSugar | 交给应用传入特性的配置委托,主值是连接字符串 |
cache | cache:distributed | Caching.Redis | 主值覆盖 XiHan:Caching:Redis:Configuration;属性 username、password 覆盖连接字符串里的 user、password |
queue | queue | Messaging.RabbitMQ | 主值覆盖 XiHan:Messaging:RabbitMQ:Configuration;属性 username、password 覆盖 AMQP URI 里的用户名与密码 |
stream | stream | Messaging.Kafka | 主值覆盖 XiHan:Messaging:Kafka:BootstrapServers;属性 security.protocol、sasl.mechanism、sasl.username、sasl.password 覆盖 Properties 里的同名键(只认这四项) |
nacos | configuration:remote | Configuration.Nacos | 主值覆盖 XiHan:Configuration:Nacos:ServerAddresses;属性 username、password 覆盖 Username、Password |
objectstorage | blob | ObjectStorage.S3 | 主值(服务端点)与属性 region、accessKey、secretKey、forcePathStyle 覆盖 XiHan:ObjectStorage:S3 里的同名设置 |
表里六种绑定类型 xihan pack 都认识:应用清单 xihan.app.json 按上表的绑定名声明后,Compose 与 Aspire 产物会起对应的依赖服务并把主值注入 XiHan__Bindings__<绑定名>__value(blob 的依赖服务是 S3 兼容的 RustFS,另注入 accessKey、secretKey 两个属性,其余服务的凭据在主值里或没开认证),Kustomize 产物不在集群里起依赖服务(Kafka、Nacos 也不起),只按 Service Binding 规范挂 Secret,示例 Secret 以注释列出各类型可单独给出的凭据键(见部署)。
应用自己的特性声明绑定的写法:
using Microsoft.Extensions.DependencyInjection;
using XiHan.Framework.Kernel;
using XiHan.Framework.Kernel.Hosting;
using XiHan.Framework.Primitives;
using XiHan.Framework.Primitives.Manifests;
namespace Billing;
public sealed class BillingFeature : IFeature
{
public Manifest Manifest { get; } = new()
{
Id = "xihan.billing.ledger",
Package = "Billing",
Version = "1.0.0",
Primitives = 1,
Stability = Stability.Experimental,
Kind = ManifestKind.Capability,
Requires = [new CapabilityRequirement(KernelCapabilities.Hosting, KernelCapabilities.Version)],
// 必需绑定:缺失时 AddXiHan 抛出 KERNEL_HOSTING_001,启动前就暴露
Bindings = [new Binding("ledger", "connection:relational")],
Entry = typeof(BillingFeature).FullName,
};
public void Configure(FeatureContext context)
{
var ledger = context.GetBinding("ledger");
context.Services.AddSingleton(new LedgerConnection(ledger.Value ?? throw new InvalidOperationException("Binding 'ledger' has no value.")));
}
}
public sealed record LedgerConnection(string ConnectionString);清单字段与能力声明的完整说明见能力包与清单。
远程配置
configuration.remote@1 的契约是 IRemoteConfigurationClient.FetchAsync(namespace, knownVersion):按命名空间取整份带版本的文档 ConfigurationDocument,键已经展平成 A:B:C 形式;knownVersion 非空且远端没有变化时返回无值,实现可以长轮询。AddXiHanRemoteConfiguration(client, options) 把客户端接进配置:
- 构建配置时同步加载一次。
IConfigurationProvider.Load是同步契约,取值在线程池上执行并等待,受LoadTimeout(缺省 10 秒)约束。 - 首次加载失败——客户端返回失败结果、超过
LoadTimeout(CONFIGURATION_UNAVAILABLE_001,原因load timeout)或客户端抛出异常(同一个码,原因是异常消息)——时先回调OnError;Optional为false(缺省)时随后抛出带错误码的FrameworkException(客户端抛出的异常是它的内部异常),启动失败,为true时该源为空。 - 不论首次加载成败,之后都按
PollInterval(缺省 30 秒,null关闭轮询)带已知版本轮询;首次失败时已知版本为空,第一次成功的轮询装入整份文档。拿到新版本就整体替换这个源的数据并触发重载令牌,IOptionsMonitor<T>随之更新。 - 轮询失败(返回失败结果或抛出异常)只回调
OnError,保留最后一份成功的数据。
客户端的归属看用哪个重载:AddXiHanRemoteConfiguration(client, options) 传入的客户端由调用方持有,配置根释放时不释放它;AddXiHanRemoteConfiguration(clientFactory, options) 每次构建 Provider 按工厂新建一个客户端,配置根释放时随之释放(实现 IDisposable 时)。配置构建期自建、没有别人持有的客户端用工厂重载。
Prefix 把文档挂到某个配置节下,为空时挂在根。OnError 是唯一的报告渠道,因为配置在日志之前构建;回调自己抛出的异常被丢弃,不改变首次加载的结果,也不终止轮询。
| 选项 | 类型 | 缺省 | 说明 |
|---|---|---|---|
Namespace | string | 构造参数 | 远程命名空间,Nacos 里是 dataId |
Prefix | string? | null | 挂载的配置节 |
PollInterval | TimeSpan? | 30 秒 | 轮询周期,null 关闭,必须为正 |
Clock | TimeProvider | 系统时钟 | 轮询计时用的时钟;测试换成可推进的时钟(如 FakeTimeProvider),轮询由用例触发 |
LoadTimeout | TimeSpan | 10 秒 | 首次加载的超时,必须为正 |
Optional | bool | false | 首次加载失败时是否继续启动(该源为空,照常轮询) |
OnError | Action<Error>? | null | 加载或轮询失败时的回调,它抛出的异常被丢弃 |
Nacos
框架提供的远程配置 Provider 是 Configuration.Nacos:直接调用 Nacos 的 HTTP 配置接口(v1,与 Nacos 2.x 兼容),命名空间参数就是 dataId,版本是服务端给出的内容 MD5,knownVersion 非空时先长轮询监听,服务端报告变化才取整份文档。下面把 dataId 为 orders 的 JSON 文档挂到 Orders 节下,服务地址等连接设置从 XiHan:Configuration:Nacos 读:
using XiHan.Framework.Configuration.Abstractions.Remote;
using XiHan.Framework.Configuration.Nacos;
using XiHan.Framework.Hosting.AspNetCore;
using XiHan.Framework.Profiles.Standard;
var builder = WebApplication.CreateBuilder(args);
// 必须在 AddXiHan 之前:框架在 AddXiHan 里读取选项与绑定
builder.Configuration.AddXiHanNacos(
NacosOptions.FromConfiguration(builder.Configuration),
new RemoteConfigurationOptions("orders")
{
Prefix = "Orders",
PollInterval = TimeSpan.FromSeconds(15),
OnError = static error => Console.Error.WriteLine($"Nacos: {error.Code}"),
});
builder.Services.Configure<OrderLimits>(builder.Configuration.GetSection("Orders"));
builder.AddXiHan(xihan => xihan.UseStandardProfile());
var app = builder.Build();
app.UseXiHan();
app.Run();
public sealed class OrderLimits
{
public int MaxItems { get; set; } = 100;
}{
"XiHan": {
"Configuration": {
"Nacos": {
"ServerAddresses": "http://localhost:8848",
"Group": "DEFAULT_GROUP",
"Format": "Json"
}
}
}
}AddXiHanNacos 经工厂重载自建客户端(自带 HTTP 客户端),用在配置构建期,随配置根释放。另装 NacosConfigurationFeature 时,运行期容器里会登记 IRemoteConfigurationClient,供其他组件按需取文档。连接选项、长轮询与登录的细节见包页。
密钥
configuration.secrets@1 的契约是 ISecretStore.GetAsync(names[]):按名字批量读取,只读,逐项返回 SecretLookup(Name, Result<SecretValue>),顺序与入参一致,重复项各自作答,空集合返回空。写入与轮换属于运维工具,不在应用契约里。
- 密钥名
SecretName的文法是^[A-Za-z0-9][A-Za-z0-9._/-]{0,255}$,不含..与//,不以/结尾,大小写敏感;不合法在构造时抛出ArgumentException。 SecretValue.ToString()固定返回***(SecretValue.Redacted),值不会经字符串插值进入日志或异常消息。读值用Value。- 单条读取用扩展方法
store.GetAsync(name, cancellationToken),它转调批量方法。
AddXiHanSecrets(store, options) 把密钥映射到配置键:Mappings 是配置键到密钥名的字典,构建配置时一次批量读取。失败分两类:逐项失败(不存在、无权限等)每项回调一次 OnError;整体失败——超过 LoadTimeout、密钥库抛出异常、返回的条数与请求不一致——回调一次 CONFIGURATION_UNAVAILABLE_002。首次读取有失败时,Optional 为 false(缺省)随后抛出 FrameworkException(逐项失败列出失败的配置键,密钥库抛出的异常是它的内部异常),为 true 时跳过失败的项,整体失败时该源为空。不论首次读取成败,RefreshInterval 非空时都周期性重读:逐项失败的项保留旧值,整体失败保留全部旧值并回调。OnError 自己抛出的异常同样被丢弃,不终止重读。
| 选项 | 类型 | 缺省 | 说明 |
|---|---|---|---|
Mappings | IReadOnlyDictionary<string, SecretName> | 构造参数 | 配置键 → 密钥名,至少一项 |
LoadTimeout | TimeSpan | 10 秒 | 首次读取的超时 |
RefreshInterval | TimeSpan? | null | 周期重读的间隔,null 不重读 |
Clock | TimeProvider | 系统时钟 | 重读计时用的时钟;测试换成可推进的时钟,重读由用例触发 |
Optional | bool | false | 首次读取缺失或失败的项是否跳过(整体失败时该源为空,照常重读) |
OnError | Action<Error>? | null | 每个失败的项回调一次,整体失败回调一次,它抛出的异常被丢弃 |
框架没有提供密钥库 Provider(Vault、Key Vault 等),应用按自己的密钥来源实现 ISecretStore,并让测试项目继承 Configuration.Conformance 的 SecretStoreConformance 验证语义。下面的实现从一个目录读文件,每个密钥一个文件:
using XiHan.Framework.Configuration.Abstractions;
using XiHan.Framework.Configuration.Abstractions.Secrets;
using XiHan.Framework.Primitives;
namespace Orders.Secrets;
public sealed class DirectorySecretStore(string root) : ISecretStore
{
public async ValueTask<IReadOnlyList<SecretLookup>> GetAsync(IReadOnlyList<SecretName> names, CancellationToken cancellationToken)
{
var results = new List<SecretLookup>(names.Count);
foreach (var name in names)
{
cancellationToken.ThrowIfCancellationRequested();
// SecretName 的文法已排除 ".." 与开头的 "/",拼出的路径不会跳出根目录
var path = Path.Combine(root, name.Value);
Result<SecretValue> result;
try
{
result = File.Exists(path)
? new SecretValue((await File.ReadAllTextAsync(path, cancellationToken)).Trim())
: Error.NotFound(ConfigurationErrors.SecretNotFound, ConfigurationMessages.SecretNotFound, MessageArguments.Of(("name", name.Value)));
}
catch (IOException exception)
{
result = Error.Unavailable(ConfigurationErrors.SecretsUnavailable, ConfigurationMessages.SecretsUnavailable, MessageArguments.Of(("reason", exception.Message)));
}
results.Add(new SecretLookup(name, result));
}
return results;
}
}// Program.cs:密钥源同样要在 AddXiHan 之前加入,绑定 db 的主值才能取到它
builder.Configuration.AddXiHanSecrets(
new DirectorySecretStore("/run/secrets"),
new SecretsConfigurationOptions(new Dictionary<string, SecretName>
{
["XiHan:Bindings:db:value"] = "orders/db-connection",
})
{
RefreshInterval = TimeSpan.FromMinutes(5),
});选项打印时遮蔽凭据
框架的选项与携带凭据的记录在 ToString() 里把凭据打印成 ***(Redaction.Mask),值为 null 时打印为空,看得出有没有配置、看不到值;访问密钥 ID(S3 的 AccessKey)是访问密钥的一半,同样遮蔽;与口令同在一个记录里的登录用户名(Redis 的 User、RabbitMQ 的 UserName、Nacos 的 Username)是登录凭据的另一半,也遮蔽(ADR-0090);端点与令牌文件路径照常打印,排查连接问题要用到它们,要核对连的是哪个用户,直接读选项对象的属性。不带凭据的记录里的用户名(如观测的 RuntimeInfo.UserName,运行进程的系统账户)照常打印;持久化驱动异常消息里连接串的 Username= / User Id= 也照常保留——用户名的遮蔽到此为止,已定(ADR-0093,维持 ADR-0084)。连接串整串遮蔽,与持久化驱动消息的脱敏范围一致(只遮整串连接串与口令类的值)。字典与列表照记录的缺省只打印类型名,不展开内容。
| 记录 | 遮蔽的成员 |
|---|---|
RedisCachingOptions | Configuration(连接字符串)、User、Password |
RabbitMQMessagingOptions | Configuration(AMQP URI)、UserName、Password |
NacosOptions | Username、Password |
S3ObjectStorageOptions | AccessKey(访问密钥 ID)、SecretKey |
AIProviderOptions | ApiKey |
KubernetesSchedulingOptions | Token |
JwtOptions | Secret |
HostedBlobUrlOptions | Secret |
PrincipalRecord(Security.InMemory) | ApiKey |
TenantShard | ConnectionString |
BindingValue | Value(绑定的主值) |
应用自己的选项若是记录且带凭据,照样手写 PrintMembers 并用 Redaction.Redact,参考上表各类型的写法。
进入 IConfiguration 的密钥是明文
遮蔽只作用于 SecretValue 对象与上表记录的 ToString()。映射进配置之后,configuration["XiHan:Bindings:db:value"] 返回的是原始字符串;不要把整个配置节序列化进日志或诊断端点。
失败与错误码
| 错误码 | 含义 | 出现在 |
|---|---|---|
KERNEL_HOSTING_001 | 必需绑定缺失或类型不匹配 | AddXiHan 构建时、FeatureContext.GetBinding |
CONFIGURATION_NOTFOUND_001 | 远程配置的命名空间不存在 | IRemoteConfigurationClient.FetchAsync |
CONFIGURATION_NOTFOUND_002 | 密钥不存在 | ISecretStore.GetAsync 的逐项结果 |
CONFIGURATION_UNAVAILABLE_001 | 远程配置不可达或超时(首次加载超时、客户端抛出异常也归此类) | IRemoteConfigurationClient.FetchAsync、首次加载 |
CONFIGURATION_UNAVAILABLE_002 | 密钥库不可达或超时(密钥库抛出异常、返回条数与请求不一致也归此类) | ISecretStore.GetAsync、首次读取 |
CONFIGURATION_DENIED_001 | 没有读取该密钥的权限 | ISecretStore.GetAsync 的逐项结果 |
CONFIGURATION_VALIDATION_001 | 远程文档不是声明的格式 | IRemoteConfigurationClient.FetchAsync |
远程配置与密钥的首次加载失败且不可选时,FrameworkException 的错误码就是上表里对应的码,客户端或密钥库抛出的异常是它的内部异常;轮询与重读的失败只经 OnError 报告。选项值不合法、密钥名或命名空间为空属于编程错误,构造时抛出 ArgumentException。
配置节一览
下表列出各包在代码里读取的配置节(ConfigurationSection 常量与 FromConfiguration 读取的键)。XiHan:Providers:<能力 ID> 指定某个能力由哪份清单提供,原理见能力包与清单。
| 配置节 | 所属包 | 用途 |
|---|---|---|
XiHan:Providers | Kernel | <能力 ID> → 清单 ID,指定能力的提供者 |
XiHan:Bindings | Kernel | 资源绑定,见上文「资源绑定」 |
XiHan:Kernel | Kernel | StartTimeoutSeconds、StopTimeoutSeconds、FailurePolicy、UseBuiltInMiddleware |
XiHan:Kernel:Resilience | Kernel | Resilience 阶段的默认策略,Operations:<操作 ID> 按操作覆盖 |
XiHan:Persistence:InMemory | Persistence.InMemory | MaxEntitiesPerType |
XiHan:Persistence:EntityFrameworkCore | Persistence.EntityFrameworkCore | EnsureCreated、HealthProbeIntervalSeconds |
XiHan:Persistence:SqlSugar | Persistence.SqlSugar | InitTables、CommandTimeoutSeconds、Replicas:*(从库的权重与健康探测)、HealthProbeIntervalSeconds |
XiHan:Persistence:Snowflake | Persistence.Abstractions | 雪花标识:WorkerId、Epoch、LeaseTimeToLiveSeconds、ClockDriftToleranceMilliseconds |
XiHan:MultiTenancy | MultiTenancy.Abstractions | DefaultTenant、RequireTenant、TenantClaim、ValidateAgainstStore |
XiHan:MultiTenancy:InMemory | MultiTenancy.InMemory | MaxTenants |
XiHan:MultiTenancy:Tenants | MultiTenancy.InMemory | 从配置装载的租户(DisplayName、IsEnabled、Properties) |
XiHan:MultiTenancy:Database | MultiTenancy.Database | CacheSize、CacheTimeToLiveSeconds、MaxListedTenants |
XiHan:Security | Security.Abstractions | RequireAuthentication、RoleClaim |
XiHan:Security:Outbound | Kernel | 出站地址策略:AllowLoopback、AllowPrivateNetwork、AllowedNetworks、AllowedHosts |
XiHan:Security:InMemory | Security.InMemory | 开发用主体与授予(Principals、Grants) |
XiHan:Security:Database | Security.Database | CacheSize、CacheTimeToLiveSeconds |
XiHan:Security:Jwt | Security.Jwt | Issuer、Audience、Secret、ClockSkewSeconds、NameClaim |
XiHan:Security:OpenIdConnect | Security.OpenIdConnect | Authority、Audience、元数据地址与刷新间隔 |
XiHan:Security:Ip2Region | Security.Ip2Region | xdb 数据文件路径 V4Database、V6Database |
XiHan:Caching:InMemory | Caching.InMemory | MaxEntries、DefaultTimeToLiveSeconds |
XiHan:Caching:Redis | Caching.Redis | Configuration、KeyPrefix、DefaultTimeToLiveSeconds、PublishChanges、HealthProbeIntervalSeconds |
XiHan:Caching:Hybrid | Caching.Hybrid | LocalCapacity、LocalTimeToLiveSeconds |
XiHan:Caching:Remote | Caching.Remote | TimeoutMilliseconds |
XiHan:Caching:Idempotency | Caching.Abstractions | 幂等记录的 TimeToLiveSeconds、InProgressTimeToLiveSeconds |
XiHan:Messaging | Messaging.Abstractions | MaxAttempts、DeadLetterSuffix、InstanceId |
XiHan:Messaging:Outbox | Messaging.Abstractions | 发件箱的 PollIntervalSeconds、BatchSize、MaxAttempts、RetryDelaySeconds、MaxRetryDelaySeconds、DispatchedRetentionSeconds |
XiHan:Messaging:InMemory | Messaging.InMemory | MaxQueuedMessages |
XiHan:Messaging:RabbitMQ | Messaging.RabbitMQ | Configuration、QueuePrefix、PrefetchCount、HealthProbeIntervalSeconds |
XiHan:Messaging:Kafka | Messaging.Kafka | BootstrapServers、GroupId、TopicPrefix、HealthProbeIntervalSeconds、RedeliveryDelaySeconds、Properties:<key> |
XiHan:Scheduling | Scheduling.Abstractions | 调度引擎与领导选举:轮询、租约、并发、错过阈值、历史保留 |
XiHan:Scheduling:InMemory | Scheduling.InMemory | MaxRuns |
XiHan:Scheduling:Database | Scheduling.Database | HealthProbeIntervalSeconds |
XiHan:Scheduling:Kubernetes | Scheduling.Kubernetes | Lease 选举:Lease、Namespace、Holder、ApiServer |
XiHan:Workflow | Workflow.Abstractions | 引擎:锁超时、子流程深度、表达式缓存、保留天数 |
XiHan:Workflow:InMemory | Workflow.InMemory | 各存储容量、轮询周期与批大小 |
XiHan:Workflow:Database | Workflow.Database | 到期书签的轮询与批大小、租约时长、HolderId |
XiHan:Localization | Localization.Abstractions | DefaultLocale、Locales |
XiHan:Localization:Database | Localization.Database | RefreshIntervalSeconds、MaxTranslations |
XiHan:ObjectStorage:FileSystem | ObjectStorage.FileSystem | RootPath、MaxTotalBytes、MaxBlobBytes、MultipartExpiryHours |
XiHan:ObjectStorage:S3 | ObjectStorage.S3 | ServiceUrl、Region、AccessKey、SecretKey、ForcePathStyle 等 |
XiHan:ObjectStorage:Stores | ObjectStorage.Abstractions | 命名存储实例:<name>:Provider 加该 Provider 的设置 |
XiHan:ObjectStorage:StoreHealthProbeIntervalSeconds | ObjectStorage.Abstractions | 命名实例健康探测的间隔(单个键) |
XiHan:ObjectStorage:SignedUrls | Hosting.AspNetCore | 宿主代收发预签名地址的 BaseUrl、Secret |
XiHan:Configuration:Nacos | Configuration.Nacos | Nacos 服务地址、分组、命名空间、登录与超时 |
XiHan:Auditing | Auditing.Abstractions | Selection、IncludeSuccesses |
XiHan:Auditing:InMemory | Auditing.InMemory | Capacity、LogEvents |
XiHan:Auditing:Database | Auditing.Database | QueueCapacity、BatchSize、FlushIntervalSeconds、LogEvents |
XiHan:Observability:Host | Observability.Host | SampleIntervalSeconds |
XiHan:Observability:OpenTelemetry | Observability.OpenTelemetry | 服务名、追踪、指标、日志、采样与 OTLP 导出 |
XiHan:AI | AI.Abstractions | Provider 表、工具名、护栏、知识库与提示词 |
XiHan:Protocols:Http | Protocols.Http | RoutePrefix,Routes:<操作 ID> 覆盖推导的路由 |
XiHan:Protocols:Grpc | Protocols.Grpc | Package,Methods:<操作 ID> 覆盖推导的方法名 |
XiHan:Protocols:Mcp | Protocols.Mcp | ServerName、ServerVersion、Instructions,Tools:<操作 ID> |
XiHan:Protocols:CloudEvents | Protocols.CloudEvents | Inbound、Outbound、Topics:<事件类型>、Webhooks:<主题> |
XiHan:Plugins:OutOfProcess | Plugins.OutOfProcess | 插件目录、授予、握手与启停超时、健康与重启限制 |
XiHan:Plugins:Wasm | Plugins.Wasm | 插件目录、授予、挂载、内存与栈上限、调用超时 |
各键的类型与缺省值以对应包页为准。
相关
- 能力包与清单
- 部署与打包
- 序列化与 Native AOT
- Configuration.Abstractions
- Configuration.Nacos
- 规范:RFC-0014《远程配置与密钥》、RFC-0016《打包》
