使用HttpClient调用PKI认证API时SSL/TLS通道建立失败问题排查
问题:HttpClient通过PKI证书访问REST API超200次后无法创建SSL/TLS安全通道
背景与API限制
- 已建立的TLS连接最多处理200次请求
- 同一连接再次发送请求需等待5秒超时
现有代码实现
HttpClient初始化代码
private HttpClientHandler _httpClientHandler; private static HttpClient _httpClient; public MyTestClass() { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; _httpClientHandler = new HttpClientHandler(); _httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic; _httpClient = new HttpClient(_httpClientHandler); }
请求执行方法
private HttpResponseMessage PerformRequest(string apiCommand, Entity.EntityTypes entityType, List<KeyValuePair<Entity.Attributes, string>> attributes) { try { string relativeUri = string.Format("{0}/{1}?{2}&{3}", apiCommand, (apiCommand == Entity.API_SELECT) ? Entity.GetEntityCommand(entityType) : string.Empty, SYSTEM_AUTHENTICATION_PRODUCTION, PKI_USER_AUTHENTICATION); foreach (KeyValuePair<Entity.Attributes, string> attribute in attributes) relativeUri += "&" + Entity.GetAttributeCommand(entityType, attribute.Key) + attribute.Value; return _httpClient.GetAsync(relativeUri).Result; } catch (Exception ex) { throw new ClientException(ex.Message, ex.InnerException); } finally { LogReturn(CALL2); } }
批量调用逻辑
public string GetInfos(string partNo) { HttpResponseMessage response = new HttpResponseMessage(); string result = null; try { List<KeyValuePair<Entity.Attributes, string>> attributes = new List<KeyValuePair<Entity.Attributes, string>>(); attributes.Add(new KeyValuePair<Entity.Attributes, string>(Entity.Attributes.PartKey, PartNo)); response = PerformRequest(Entity.API_SELECT, Entity.EntityTypes.Part, attributes); if (response.Content.Headers.ContentType.MediaType == MIME_TYPE_TEXT) { result = (response.Content.ReadAsStringAsync()).Result; } } finally { response.Dispose(); } return result; }
问题表现
- 执行
PerformRequest方法超过200次后(如218次、220次),抛出WebException:请求已中止: 无法创建SSL/TLS安全通道 - 此后所有新调用均失败,仅重启应用后可恢复正常
意外现象
将应用使用的REST API URL复制到浏览器执行,加载数据后,应用可再次正常执行循环
已尝试的无效方案
- 使用/不使用
using块管理HttpClient/HttpClientHandler及响应消息 - 改用
WebRequestHandler手动选择证书 - 设置
ServicePoint.ConnectionLeaseTimeout、HttpClientHandler.PreAuthenticate、HttpClient.DefaultRequestHeaders.ConnectionClose、ServicePointManager.Expect100Continue等属性
疑问与需求
- 问题的可能原因是什么?
- 为何浏览器调用后应用可恢复?
- 求可行的解决方案
内容的提问来源于stack exchange,提问作者Lordas Smile
相关产品推荐
相关产品推荐

