Service Fabric中如何从一个节点调用其他所有节点的端点
问题:Service Fabric无状态服务跨实例调用ASP.NET端点失败
我在使用Service Fabric无状态服务时,需要从某个服务实例调用其他所有实例的ASP.NET端点。尝试通过获取所有节点的node.IpAddressOrFQDN,直接向服务端口发起HTTP请求或通过DNS调用,但均失败,求解决方法。
尝试1:直接调用指定端口和端点的代码
FabricClient fabricClient = new FabricClient(); NodeList nodes = await fabricClient.QueryManager.GetNodeListAsync(); foreach (Node node in nodes) { var nodeIpAddr = node.IpAddressOrFQDN; string httpAddress = $"http://{nodeIpAddr}:<port>/api/endpoint"; string httpsAddress = $"https://{nodeIpAddr}:<port>/api/endpoint"; HttpClient client = new HttpClient(); var responseA = await client.GetAsync(httpsAddress); var responseB = await client.GetAsync(httpAddress); } return Ok();
尝试2:通过DNS调用的代码
FabricClient fabricClient = new FabricClient(); NodeList nodes = await fabricClient.QueryManager.GetNodeListAsync(); foreach (Node node in nodes) { var nodeIpAddr = node.IpAddressOrFQDN; string httpAddress = $"http://{nodeIpAddr}:19081/Service/Application/api/endpoint"; string httpsAddress = $"https://{nodeIpAddr}:19081/Service/Application/api/endpoint"; HttpClient client = new HttpClient(); var responseA = await client.GetAsync(httpsAddress); var responseB = await client.GetAsync(httpAddress); } return Ok();
遇到的错误
HTTPS调用异常
Error: The SSL connection could not be established, see inner exception. The SSL connection could not be established, see inner exception. at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
HTTP调用响应
StatusCode: 404, ReasonPhrase: 'FABRIC_E_ENDPOINT_NOT_FOUND', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: { Server: Microsoft-HTTPAPI/2.0 Date: Wed, 08 Jan 2025 13:45:29 GMT Content-Length: 0 }
解决方案
1. 通过Service Fabric服务发现获取实例端点
不要遍历所有节点,直接查询服务的所有实例及其端点,这是最可靠的方式:
FabricClient fabricClient = new FabricClient(); // 替换为你的服务名称,格式为 fabric:/<应用名>/<服务名> var serviceName = new Uri("fabric:/MyApplication/MyStatelessService"); var serviceInstances = await fabricClient.QueryManager.GetServiceInstanceListAsync(serviceName); foreach (var instance in serviceInstances) { // 筛选出HTTP/HTTPS类型的端点 var targetEndpoint = instance.Endpoints.FirstOrDefault(e => e.Protocol == EndpointProtocol.Http || e.Protocol == EndpointProtocol.Https); if (targetEndpoint != null) { string requestUrl = $"{targetEndpoint.Protocol.ToString().ToLower()}://{targetEndpoint.Address}/api/endpoint"; using (HttpClient client = new HttpClient()) { // 处理HTTPS证书验证(测试环境临时方案,生产环境禁用) if (targetEndpoint.Protocol == EndpointProtocol.Https) { var handler = new HttpClientHandler(); handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; client = new HttpClient(handler); } var response = await client.GetAsync(requestUrl); // 根据业务需求处理响应结果 } } }
说明:这种方式直接获取每个服务实例的实际运行端点,避免了节点上无服务实例的无效请求,也不需要手动拼接端口或路径。
2. 修复DNS调用的格式问题
Service Fabric的DNS访问格式并非节点IP+19081,正确的无状态服务实例DNS格式为:http://<服务名>_<实例ID>.<应用名>.cluster.local:<端口>/api/endpoint
其中<服务名>、<实例ID>、<应用名>需要替换为你的实际信息,端口为服务端点配置的端口。
3. HTTPS问题处理
- 生产环境:确保服务使用的SSL证书已被调用方信任,证书的Subject或SAN字段包含服务实例的访问地址。
- 测试环境:可临时使用代码中的证书验证跳过逻辑,但生产环境必须使用合法的信任证书。
关键注意事项
- 避免遍历所有节点:节点上可能未部署目标服务实例,会导致大量无效请求。
- 复用HttpClient:频繁创建销毁HttpClient会导致资源浪费,建议使用单例或复用实例。
- 动态刷新端点:服务实例可能会扩容、迁移,需定期刷新端点列表以保证有效性。
内容的提问来源于stack exchange,提问作者AAYUSH SHANDILYA
相关产品推荐
相关产品推荐

