Aspire里服务发现靠什么自动完成
Aspire本身不实现服务发现协议,而是通过集成
Docker Compose和
ServiceDiscovery组件(如
Microsoft.Extensions.ServiceDiscovery)让服务名解析自动生效。启动时,Aspire 会把每个
ProjectResource或
ContainerResource注册为可解析的服务名,其他服务直接用这个名称发起 HTTP/gRPC 调用即可。
关键点是:不需要写 Consul/Eureka 客户端代码,也不用配 DNS SRV 记录 —— 只要服务在 Aspire 应用拓扑中声明了,就默认能被发现。
builder.AddProject<myapi>("myapi")</myapi> 声明后,其他服务调用 https://myapi即可 底层由 Aspire 的
ServiceDiscoveryHttpHandler拦截请求,将服务名解析为实际地址(如
http://localhost:5042或容器内
http://myapi:8080) 仅限 Aspire 托管的资源之间有效;外部服务需手动配置地址或通过
AddConnectionString显式传入
HttpClient怎么自动用上服务发现
不是所有
HttpClient都能自动解析服务名。必须通过 Aspire 提供的扩展方法注册,否则仍走默认 DNS 解析,报
UnknownHostException或连接拒绝。 正确方式:
builder.Services.AddHttpClient<myclient>().AddServiceDiscovery()</myclient>如果用了命名客户端(如
AddHttpClient("myapi")),也要配套调用 .AddServiceDiscovery()不加
AddServiceDiscovery()时,
new HttpClient()或未注册的客户端无法识别
https://myapi这类地址 gRPC 客户端同理,需用
AddGrpcClient<myservice.myserviceclient>().AddServiceDiscovery()</myservice.myserviceclient>
本地开发和容器部署的服务发现行为差异
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<iserviceendpointresolver myresolver>())</iserviceendpointresolver>) 健康检查需额外接入(如
AddHealthChecks),Aspire 不自动剔除不健康实例 调试时看解析结果,可注入
IDnsEndPointResolver并调用
ResolveAsync("myapi") 查日志
服务发现看似“开箱即用”,但实际依赖 Aspire 的资源声明完整性、HttpClient 注册方式、以及调用地址是否严格使用服务名 —— 任一环节断掉,就会退化成普通 HTTP 调用并失败。 