# 生命周期与排空
DynamicApp 使用生命周期和健康状态共同决定 Gateway 是否可以把新流量转发到某个 Mod 目标。
# 生命周期状态
Pending -> Starting -> Active -> Draining -> Stopped
\-> Failed
| 状态 | 含义 |
|---|---|
Pending | 已声明但尚未启动 |
Starting | 已发布或正在启动,等待健康检查 |
Active | 当前接收 Gateway 新流量 |
Draining | 不接收新流量,只等待旧请求和后台任务结束 |
Stopped | 已停止,可释放资源 |
Failed | 启动、健康检查、退出或编排失败 |
IDynamicAppStateStore.Activate(...) 会将目标版本设置为 Active/Healthy,并将同一 dynamicAppId/modId 下其他版本设置为 Draining/Draining,同时记录 DrainingSinceUtc。
# 状态存储
运行目标包含以下时间线字段:
CreatedAtUtcUpdatedAtUtcDrainingSinceUtcLastStatusMessage
InMemoryDynamicAppStateStore 和 FileDynamicAppStateStore 在激活、更新、删除目标时维护这些字段。IDynamicAppStateStore.RemoveTarget(...) 用于排空完成后的目标清理。
# 排空清理
DynamicAppDrainCleanupHostedService 定时扫描 Draining 目标。目标超过 DynamicAppDrainOptions.DrainTimeout 后,服务会调用 IDynamicAppModRunner.StopAsync(...) 并从状态表移除目标。
配置示例:
builder.Services.AddDynamicAppHost(
configureDrain: options =>
{
options.Enabled = true;
options.ScanInterval = TimeSpan.FromSeconds(15);
options.DrainTimeout = TimeSpan.FromSeconds(60);
options.RemoveTargetWhenStopFails = true;
});
# Process 日志与退出监控
ProcessDynamicAppModRunner 管理 Process 模式 Mod:
- 启动时订阅 stdout、stderr 和
Exited事件。 - 标准输出和标准错误写入
IDynamicAppProcessLogSink。 - 主动
StopAsync(...)会登记为预期退出,并写入Stopped/Stopped。 - 非预期退出会写入
Failed/Unhealthy,同时记录退出日志。 - 默认日志 Sink 为
InMemoryDynamicAppProcessLogSink,单目标默认保留最近 1000 条。
# Process 自愈
DynamicAppProcessSelfHealingHostedService 会定时扫描非 Stopped、非 Draining 的 Process 目标。目标子进程异常退出、状态进入 Failed/Unhealthy,或持久化状态中显示可运行但当前 Host 不再持有活进程时,自愈服务会按 Manifest 历史重新启动该 Mod。
自愈成功路径:
Failed/Unhealthy
-> Process Runner Start
-> Health Probe
-> Activate
-> Active/Healthy
自愈不会重启人工停止的目标:
Stopped/Stopped表示人工停止或控制面停止,不会自动拉起。Draining/Draining表示版本排空,不会自动拉起。- Manifest 丢失、启动失败或健康探测失败时保持
Failed/Unhealthy。 - 同一目标受退避和最大重试次数限制,避免坏包无限重启。
配置示例:
builder.Services.AddDynamicAppHost(
configureSelfHealing: options =>
{
options.Enabled = true;
options.ScanInterval = TimeSpan.FromSeconds(5);
options.RestartBackoff = TimeSpan.FromSeconds(5);
options.MaxRestartAttempts = 5;
options.AttemptWindow = TimeSpan.FromMinutes(5);
options.ResetAttemptsAfterHealthy = true;
});
配置文件示例:
{
"DynamicApp": {
"SelfHealing": {
"Enabled": true,
"ScanIntervalSeconds": 5,
"RestartBackoffSeconds": 5,
"MaxRestartAttempts": 5,
"AttemptWindowSeconds": 300,
"ResetAttemptsAfterHealthy": true
}
}
}
日志查询接口:
POST /dynamicapp-manager/logs
请求体:
{
"dynamicAppId": "security-platform",
"modId": "auth",
"version": "1.0.0"
}
# 回滚
IDynamicAppManager.RollbackAsync(dynamicAppId, modId, ...) 的回滚策略:
- 找到同一
dynamicAppId/modId下最近更新的健康旧版本。 - 排除当前
Active/Healthy版本。 - 候选版本必须是
Active或Draining,且健康状态为Healthy。 - 找到后调用状态存储的
Activate(...),让旧版本重新成为活动版本。
接口:
POST /dynamicapp-manager/rollback
请求体:
{
"dynamicAppId": "security-platform",
"modId": "auth"
}
# Self-Healing Observability And Package Governance
Process self-healing now persists retry-window state through IDynamicAppSelfHealingStateStore. The demo entry uses FileDynamicAppSelfHealingStateStore, and the recommended file paths are:
{
"DynamicApp": {
"SelfHealingStateStore": {
"FilePath": "data/dynamicapp-self-healing.json",
"SaveOnChange": true
},
"TargetArchiveStore": {
"FilePath": "data/dynamicapp-archives.json",
"SaveOnChange": true
}
}
}
The persisted self-healing state contains retry attempts, retry limits, backoff timing, counting-window reset time, pause state, latest failure stage, and latest failure message.
Operations:
GET /dynamicapp-manager/self-healing
POST /dynamicapp-manager/self-healing/reset
GET /dynamicapp-manager/archived
POST /dynamicapp-manager/archive
POST /dynamicapp-manager/unarchive
archive is the governance path for bad packages or invalid manifests. It stops and removes the runtime target when present, clears self-healing retry state, writes a durable archive record, and filters that version from /dynamicapp-manager/applications. Manifest audit history is still available from /dynamicapp-manager/manifests.
← 架构边界 Manager API →