如何检测HTTP请求因目标微服务不存在而失败?
解决方案
要可靠区分「服务不存在」与DNS错误、SSL证书问题等场景,核心是绕过本地化的异常消息,直接检查底层异常的错误码或枚举值——因为连接类异常的底层错误标识是固定的,不会随系统语言变化。
关键思路
区分HTTP层错误与连接层错误:
- 如果服务器能正常响应(包括404这类错误),
EnsureSuccessStatusCode()抛出的HttpRequestException会带有StatusCode属性,可直接判断。 - 如果连接根本无法建立(服务未启动、端口未监听、DNS失败等),
HttpRequestException的StatusCode为null,此时需要检查它的InnerException(通常是SocketException或Win32Exception)。
- 如果服务器能正常响应(包括404这类错误),
用固定错误标识判断场景:
- 服务不存在/端口未监听:对应
SocketError.ConnectionRefused枚举(跨平台兼容,Windows下映射为10061,Linux下为11)。 - DNS解析失败:对应
SocketError.HostNotFound或SocketError.NoData。 - SSL证书问题:通常会抛出嵌套
AuthenticationException的HttpRequestException,或对应特定Win32错误码(如0x80090326)。
- 服务不存在/端口未监听:对应
代码实现
修改你的请求逻辑,加入异常处理逻辑:
// htmlAddress is actually a method parameter. // It contains a uri that the user enters. // At this uri, an Apache server handles HTTP or HTTPS requests. // I may assume this Apache server is available. // An example uri would be: var htmlAddress = new Uri("http://my.server.domain/path"); // Alongside there may or may not be a microservice running. // If it runs, it requires https and listens on port 19500, // e.g. https://my.server.domain:19500/path/route/to/endpoint var builder = new UriBuilder(htmlAddress) { Scheme = "https", Port = 19500 }; using var restClient = new HttpClient { BaseAddress = builder.Uri, Timeout = TimeSpan.FromSeconds(5) }; try { var response = await restClient.GetAsync("route/to/endpoint").ConfigureAwait(false); // 触发HTTP错误(如404)的异常,此时StatusCode有值 response.EnsureSuccessStatusCode(); // 处理正常响应逻辑 } catch (HttpRequestException ex) { // 1. 处理HTTP层错误(服务存在但接口/资源不存在) if (ex.StatusCode.HasValue) { if (ex.StatusCode == HttpStatusCode.NotFound) { // 服务存在但请求的端点不存在,执行对应逻辑 } // 其他HTTP状态码处理 return; } // 2. 处理连接层错误,检查内部异常 var socketEx = ex.InnerException as SocketException; if (socketEx != null) { switch (socketEx.SocketErrorCode) { case SocketError.ConnectionRefused: // 目标机器拒绝连接,判定为服务未启动/不存在,执行降级逻辑 break; case SocketError.HostNotFound: case SocketError.NoData: // DNS解析失败,执行对应错误处理 break; // 其他Socket错误处理 default: break; } return; } // 3. 处理SSL证书相关错误 var authEx = ex.InnerException as AuthenticationException; if (authEx != null) { // SSL证书验证失败,执行对应逻辑 return; } // 其他未知错误处理 }
注意事项
- 跨平台兼容性:使用
SocketError枚举而非硬编码错误码,能自动适配Windows/Linux/macOS的底层错误标识。 - 超时处理:你的代码已经设置了5秒超时,超时会抛出带有
TaskCanceledException的HttpRequestException,可单独捕获处理(检查ex.InnerException is TaskCanceledException)。
内容的提问来源于stack exchange,提问作者LWChris
相关产品推荐
相关产品推荐

