Aspire通过集成Docker Compose和Microsoft.Extensions.ServiceDiscovery自动完成服务发现,声明服务名(如builder.AddProject("myapi"))后,其他服务直接调用https://myapi即可,由ServiceDiscoveryHttpHandler解析为实际地址。

Aspire里服务发现靠什么自动完成
Aspire本身不实现服务发现协议,而是通过集成 Docker Compose 和 ServiceDiscovery 组件(如 Microsoft.Extensions.ServiceDiscovery)让服务名解析自动生效。启动时,Aspire 会把每个 ProjectResource 或 ContainerResource 注册为可解析的服务名,其他服务直接用这个名称发起 HTTP/gRPC 调用即可。
关键点是:不需要写 Consul/Eureka 客户端代码,也不用配 DNS SRV 记录 —— 只要服务在 Aspire 应用拓扑中声明了,就默认能被发现。
-
builder.AddProject声明后,其他服务调用("myapi") https://myapi即可 - 底层由 Aspire 的
ServiceDiscoveryHttpHandler拦截请求,将服务名解析为实际地址(如http://localhost:5042或容器内http://myapi:8080) - 仅限 Aspire 托管的资源之间有效;外部服务需手动配置地址或通过
AddConnectionString显式传入
HttpClient怎么自动用上服务发现
不是所有 HttpClient 都能自动解析服务名。必须通过 Aspire 提供的扩展方法注册,否则仍走默认 DNS 解析,报 UnknownHostException 或连接拒绝。
- 正确方式:
builder.Services.AddHttpClient().AddServiceDiscovery() - 如果用了命名客户端(如
AddHttpClient("myapi")),也要配套调用.AddServiceDiscovery() - 不加
AddServiceDiscovery()时,new HttpClient()或未注册的客户端无法识别https://myapi这类地址 - gRPC 客户端同理,需用
AddGrpcClient().AddServiceDiscovery()
本地开发和容器部署的服务发现行为差异
Aspire 在不同托管模式下解析逻辑不同,容易导致本地跑通、部署后 500 或超时。
- 本地开发(
dotnet run):服务名解析为localhost:port,端口由 Aspire 动态分配并注入环境变量 - Docker Compose 模式(
dotnet publish && docker compose up):服务名直接解析为 Docker 内网 DNS 名(如myapi),端口固定为容器暴露端口(如8080) - 若在代码里硬编码
http://localhost:5000,容器里必然失败;必须统一用服务名(如myapi) - 环境变量
ASPNETCORE_URLS或Kestrel__Endpoints__Http__Url不影响服务发现解析目标,只控制本服务监听地址
自定义服务发现逻辑或 fallback 怎么做
Aspire 默认不提供 fallback 机制(比如主服务不可用时切到备用地址),也不支持多实例负载策略切换。需要自己补一层容错。
- 可用
IHttpClientFactory+Polly实现重试/降级,但注意:重试不能盲目换服务名,因为 Aspire 解析结果是确定的 - 若需轮询多个实例,得自己实现
IServiceEndPointResolver并替换默认实现(通过Replace(ServiceDescriptor.Singleton)()) - 健康检查需额外接入(如
AddHealthChecks),Aspire 不自动剔除不健康实例 - 调试时看解析结果,可注入
IDnsEndPointResolver并调用ResolveAsync("myapi")查日志










