AppHost 应用主机
更新: 2026-10-16 15:20:09 字数: 0 字 时长: 0 分钟
AppHost 是 Aspire 应用的编排入口。它用代码描述「这个系统由哪些部分组成、它们之间是什么关系」,但不承载业务逻辑。Aspire 读取这份描述后,负责分配端口、注入配置、决定启动顺序,并把运行状态汇入仪表板。
三种 AppHost 形态
| 形态 | 入口文件 | 适用场景 |
|---|---|---|
| 项目型 C# AppHost | AppHost.cs + AppHost.csproj | 模板默认生成的形式,适合团队协作与大型解决方案。 |
| 文件型 C# AppHost | apphost.cs | 单文件编排器,使用 #:sdk 与 #:package 指令,适合快速试用。 |
| TypeScript AppHost | apphost.mts | 以 Node.js / 前端为主的团队,无需 .NET SDK。 |
语言不影响可编排的内容
无论 AppHost 使用哪种语言,都可以在同一个应用模型中编排 C#、JavaScript、Python、Go、Java、Rust、PowerShell 以及各类容器。AppHost 语言决定的是「用什么写编排代码」,而不是「能编排什么」。
文件型 C# AppHost
文件型 AppHost 使用 .NET 10 的单文件指令语法,把 SDK 与包引用写在文件顶部:
csharp
#:sdk Aspire.AppHost.Sdk
#:package Aspire.Hosting.JavaScript
#:package Aspire.Hosting.PostgreSQL
var builder = DistributedApplication.CreateBuilder(args);
var db = builder.AddPostgres("db");
var api = builder.AddProject<Projects.Api>("api")
.WithReference(db);
builder.AddNpmApp("frontend", "../frontend")
.WithReference(api);
builder.Build().Run();TypeScript AppHost
TypeScript AppHost 采用客户端/主机架构:apphost.mts 通过生成的 .aspire/modules/ 模块与宿主进程通信,但底层使用的是同一套编排引擎、集成、服务发现与诊断能力。
typescript
import { createBuilder } from './.aspire/modules/aspire.mjs'
const builder = await createBuilder()
const cache = await builder.addRedis('cache')
const api = await builder.addNodeApp('api', '../api', 'server.js').withReference(cache)
await builder.build().run()创建 AppHost
bash
aspire new aspire-starter -n AspireApp -o AspireAppbash
aspire initaspire init 会为已有仓库生成一个最小的 AppHost 骨架与 aspire.config.json,并可选安装 aspireify 代理技能,让 AI 编码代理协助完成后续接线。
AppHost 在做什么
一个 AppHost 程序通常由四个部分组成:
csharp
// 1. 创建构建器
var builder = DistributedApplication.CreateBuilder(args);
// 2. 声明资源
var cache = builder.AddRedis("cache");
var db = builder.AddPostgres("pg").AddDatabase("appdata");
// 3. 表达关系
var api = builder.AddProject<Projects.Api>("api")
.WithReference(cache)
.WithReference(db)
.WithHttpHealthCheck("/health");
builder.AddProject<Projects.Web>("web")
.WithExternalHttpEndpoints()
.WithReference(api)
.WaitFor(api);
// 4. 构建并运行
builder.Build().Run();Build().Run() 之后,Aspire 会接管以下事情:
- 端口分配:为每个资源分配实际端口,并通过代理统一入口。
- 环境变量注入:把连接字符串、服务地址等注入到依赖方,见环境变量与配置注入。
- 启动顺序:根据依赖关系(DAG)决定启动次序,并结合健康检查判断就绪。
- 生命周期管理:监控资源状态,在退出时按依赖顺序优雅停止。
常用 API 速查
添加资源(Add 系列)
| API | 说明 |
|---|---|
AddProject<T>("name") | 添加 .NET 项目资源。 |
AddContainer("name", "image") | 添加基于镜像的容器资源。 |
AddDockerfile("name", "path") | 添加由 Dockerfile 构建的容器资源。 |
AddExecutable("name", "cmd", "args") | 添加本机可执行文件资源。 |
AddNpmApp("name", "path") | 添加 npm 应用资源。 |
AddNodeApp("name", "path", "script") | 添加 Node.js 应用资源。 |
AddPythonApp("name", "path", "script") | 添加 Python 应用资源。 |
AddPostgres("name") | 添加 PostgreSQL 资源(需集成包)。 |
AddRedis("name") | 添加 Redis 资源(需集成包)。 |
AddParameter("name") | 添加外部参数,见外部参数与机密。 |
表达关系(With 系列)
| API | 说明 |
|---|---|
WithReference(resource) | 引用资源,注入连接信息并启用服务发现。 |
WaitFor(resource) | 等待依赖资源就绪后再启动当前资源。 |
WithEnvironment(name, value) | 显式设置环境变量。 |
WithHttpEndpoint(...) | 为资源添加 HTTP 端点。 |
WithExternalHttpEndpoints() | 标记端点需要暴露给外部访问。 |
WithHttpHealthCheck("/health") | 添加 HTTP 健康检查。 |
WithDataVolume() / WithBindMount() | 数据持久化,见数据持久化。 |
WithImageTag("tag") | 固定容器镜像版本。 |
WithAnnotation(...) | 附加自定义注解元数据,见应用模型与架构。 |
Run 模式与 Publish 模式
AppHost 代码在两种「执行上下文」中运行,可以通过 builder.ExecutionContext 判断:
csharp
IResourceBuilder<IResourceWithConnectionString> db = builder.ExecutionContext.IsRunMode
? builder.AddSqlServer("sql").AddDatabase("db")
: builder.AddConnectionString("db");- Run 模式:本地开发,Aspire 创建容器、分配端口、启动进程。
- Publish 模式:生成部署产物,本地的容器资源通常被替换为云端服务引用。
这是让同一份架构描述在本地与生产环境都成立的关键机制。
配置
AppHost 自身也是一个 .NET 应用,可以读取标准配置源:
json
{
"Parameters": {
"insertionRows": "1"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Aspire.Hosting.Dcp": "Warning"
}
}
}敏感值不建议写在 appsettings.json,请使用用户机密:
bash
aspire secret set Parameters:sql-password "your-password"最佳实践
- 让 AppHost 保持「纯声明」:不要在 AppHost 里写业务逻辑或复杂的分支计算。
- 优先使用
WithReference而不是手工拼接连接字符串,这样服务发现与连接注入才能生效。 - 给资源取稳定的名字:资源名会参与环境变量名生成,改名等于改配置,见环境变量命名约定。
- 用
WaitFor表达启动依赖,不要靠Thread.Sleep。 - 把 AppHost 提交到版本库:它是应用架构的唯一信息来源。





