docker-compose部署下Dapr服务间调用报连接拒绝错误如何解决?
问题根因
报错Connection refused (127.0.0.1:3500)是Dapr SDK尝试连接当前服务绑定的Dapr sidecar(即player-service-dapr)的默认HTTP端口失败导致,还未到调用Quest-Service的步骤。结合给出的配置,核心原因如下:
- 容器启动顺序问题:配置了player-service-dapr依赖player-service,也就是业务服务先启动、sidecar后启动。ASP.NET Core服务初始化完成后调用Dapr接口时,sidecar还未完成初始化、没有开始监听3500端口,就会触发连接拒绝错误。你提到消息通信功能正常也符合这个特征:pubsub是sidecar就绪后主动推送消息,而服务调用是业务服务主动请求sidecar,启动阶段请求就会失败。
- 端口配置未显式声明:Dapr默认端口可能被容器内其他进程占用,没有显式绑定端口会增加排查难度。
解决方案
1. 修复启动时序问题
因为你用了network_mode: "service:player-service"共享网络栈,sidecar必须依赖业务容器先启动才能拿到网络栈,因此不能调整依赖顺序,改为让业务服务启动时等待sidecar端口就绪再启动服务:
修改player-service的docker-compose配置,新增启动命令:
player-service: image: ${DOCKER_REGISTRY-gamification}/player-service:${TAG:-latest} environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - SeqServerUrl=http://seq # 新增启动命令,等待3500端口就绪后再启动业务服务 command: ["sh", "-c", "until nc -z 127.0.0.1 3500; do sleep 1; done; dotnet LW.Gamificaiton.PlayerService.dll"] build: context: . dockerfile: Services/LW.Gamificaiton.PlayerService/Dockerfile ports: - "5109:80" - "50009:50001"
如果你的基础镜像没有预装netcat(nc),可以替换为其他端口检测工具,或者在代码中给Dapr调用增加重试策略,首次调用失败后自动重试2-3次即可。
2. 显式绑定Dapr端口
在两个服务的配置中都显式声明Dapr端口,避免默认值异常:
player-service侧修改
player-service: environment: # 新增两个环境变量,给Dapr SDK指定sidecar端口 - DAPR_HTTP_PORT=3500 - DAPR_GRPC_PORT=50001 # 其余原有配置不变 player-service-dapr: command: ["./daprd", "-app-id", "Player-Service", "-app-port", "80", # 新增端口声明 "-dapr-http-port", "3500", "-dapr-grpc-port", "50001", "-components-path", "/Components", "-config", "/Configuration/config.yaml" ] # 其余原有配置不变
quest-service侧修改
quest-service: environment: - DAPR_HTTP_PORT=3500 - DAPR_GRPC_PORT=50001 # 其余原有配置不变 quest-service-dapr: command: ["./daprd", "-app-id", "Quest-Service", "-app-port", "80", "-dapr-http-port", "3500", "-dapr-grpc-port", "50001", "-components-path", "/Components", "-config", "/Configuration/config.yaml" ] # 其余原有配置不变
3. 可选优化
调用的请求路径改为绝对路径,避免相对路径拼接错误:
// demo service to service call var httpClient = DaprClient.CreateInvokeHttpClient("Quest-Service"); // 路径前加斜杠 var requestUri = $"/api/v1/Quest"; var result = await httpClient.GetFromJsonAsync<IEnumerable<string>>(requestUri);
排查验证
如果修改后还是报错,可进入player-service容器执行curl http://127.0.0.1:3500/v1.0/healthz,如果返回200说明sidecar正常,问题出在业务代码逻辑;如果返回连接拒绝,查看player-service-dapr的容器日志排查sidecar启动失败原因即可。
内容的提问来源于stack exchange,提问作者Choco
相关产品推荐
相关产品推荐

