服务突然抛出了SocketException,没有明显的变化



在1月17日09:32,我们的一项服务突然开始扔500个错误。这是对第三方服务的适配器服务,我们使用httpclient来发表帖子(因此,我们使用查询字符串参数来获取我们的服务,并使用使用中的帖子和参数将其传输到第三方应用程序中身体)。当我使用Postman或Curl手动向第三方服务发布时,它做出了良好的反应。因此,这是我们服务的问题。它是使用OWIN中间件的.NET服务,类似于我认为的.NET核心工作方式。问题在于一段时间以前,.NET框架从4.5.2升级到4.6,并且在VS中进行此操作时,它会在Web.config中添加<httpRuntime targetFramework="4.5.2"/>元素。这是为了保留应用程序现有行为的最佳努力,以防框架版本之间发生任何破坏的变化。升级的人没有意识到并留在web.config中的元素中。它效果很好,然后在所有环境中突然(包括本地)被破坏了。我认为在.NET框架中必须有一些时间,但是将我的系统时钟滚动回去无法解决!我能寻找什么,对这个谜团有什么想法?只需将web.config提高到4.6修复它,但我的任务是调查它。

这是基本错误:

System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host
    at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
    at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)

这是代码,它以上述为Innerexception抛出_client.PostAsync。_Client是System.Net.Http.HttpClient

public async Task<CalculateResponse> Calculate(CalculateRequest request)
{
    var env = new RequestEnvelope { Body = { RblsCalculate = request } };
    request.LoginId = _username;
    request.Password = _password;
    var body = XmlConvert.SerializeObject(env);
    var content = new StringContent(body, Encoding.UTF8, "application/soap+xml");
    var httpResponse = await _client.PostAsync(_endpointPath, content);
    var response = XmlConvert.ToObject<ResponseEnvelope>(await httpResponse.Content.ReadAsStreamAsync());
    return response?.Body?.RblsCalculateResponse;
}

第三方没有进行任何更改,Windows更新没有运行(这同时实现了5个不同的环境)。我们没有进行任何更改。当我们部署时,我们每次都部署到新实例时,web.config并未在服务器上更改,而先前的部署是几周前。

我已经审查了4.6的一些更改,如果不使用TLSV1.0 作为协议,则在HttpClient周围有一些破坏的变化,我在其中一台服务器上使用Wireshark进行了检查,我们正在使用TLSV1.2。但这并不能解释为什么它突然停止。

update-根据@trumpi建议

,从trace.log输出trace.log for ssl/tls跟踪
System.Net.Sockets Verbose: 0 : [16292] Data from Socket#52088480::PostCompletion
System.Net.Sockets Verbose: 0 : [16292] 00000000 : 16 03 01 00 88 01 00 00-84 03 01 58 A4 49 35 01 : ...........X.I5.

更新2-删除了不必要的日志^^

有趣的是,我上周遇到了一个非常相似的问题(尽管它没有.NET Core)。我已经通过日常工作打电话给API端点了几个月,突然之间我遇到了同样的错误。我花了几天时间才找到修复程序,但是对我而言,添加以下代码解决了问题。您可能只能将其添加到方法的第一行。

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

我的第一个本能是,这是TLS握手的问题,第三方服务正在删除连接,因为它无法执行成功的握手。正如您指出的那样,TLS版本可能是一个问题。找不到兼容密码可能是另一个问题。

我偶然发现了这篇博客文章,该文章描述了如何将握手信息写入跟踪文件。这是他添加到web.config文件的部分:

<system.diagnostics> <trace autoflush="true"/> <sources> <source name="System.Net" maxdatasize="1024"> <listeners> <add name="TraceFile"/> </listeners> </source> <source name="System.Net.Sockets" maxdatasize="1024"> <listeners> <add name="TraceFile"/> </listeners> </source> </sources> <sharedListeners> <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log"/> </sharedListeners> <switches> <add name="System.Net" value="Verbose" /> <add name="System.Net.Sockets" value="Verbose" /> </switches> </system.diagnostics>

这是我可以在问题中的信息中做到的最好的,我希望这会有所帮助。

编辑:发布结果后,调用似乎正在尝试协商服务器不再支持的TLS 1.0连接。我在下面的评论中将详细信息放在。

最新更新