2017-02-15 47 views
2

在1月17日09:32,我们的一个服务突然开始抛出500个错误。它是一个适用于第三方服务的适配器服务,我们使用HttpClient对其进行POST(因此,我们使用查询字符串参数对我们的服务进行GET,然后使用POST和参数传递给第三方应用程序身体)。当我用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可以修复它,但我一直负责调查它。服务突然抛出SocketException,没有明显的变化

这里是底层错误:

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) 

,这是代码,它引发在_client.PostAsync与上述作为的InnerException。 _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 。但这并不能解释为什么突然停止。

更新 - 输出从trace.log中为SSL/TLS跟踪按@Trumpi建议

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 - 删除了不必要的日志^^

+0

_“当我发布到第三方服务使用邮递员或卷曲手动,它精细的反应。因此,它与我们的服务有问题[...]第三方没有做任何更改” _ - 不同的是执行请求的时间。也许第三方服务目前超载,升级过程中或其他任何情况。如果运行.NET 4.5.2会一直出现此错误,而.NET 4.6则不会,那么请检查两者之间HTTP标头的差异。 – CodeCaster

+0

“由远程主机强制关闭”正在从错误的端口调试问题。不要猜测为什么另一端决定放弃。按照电线。 –

+0

@HansPassant套接字的另一端是我无法访问的第三方应用程序。我确实联系了他们的支持团队,他们说他们看不到任何要求。 – Rodders

回答

1

有趣的是,上周我遇到了一个非常类似的问题(虽然它不是.NET Core)。我通过每天的工作一直在调用一个API端点几个月,突然之间我得到了同样的错误。我花了几天的时间才找到一个修复程序,但是对于我来说,添加下面这行代码可以解决问题。您可能只需将其添加到方法的第一行即可。

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 
+0

非常好!即使我的httpRuntime仍然设置为4.5.2,这确实解决了问题。这真的很有帮助,谢谢。这并没有解释为什么突然停止,但这是真正的进展。也许我们正在使用Tls1.2,并且有些东西使它回复到1.0 – Rodders

+0

或者考虑到它,我认为我们总是使用1.0,第三方做出了一些改变,从而失去了支持。 – Rodders

+0

我也有同感。我花了很多时间试图弄清楚为什么会发生这种情况,但过了一段时间,我开始为找到解决方案而感到高兴。如果你确实知道是什么导致了这个问题,请告诉我。 – MDiesel

1

我的第一直觉是这是TLS握手的问题,并且第三方服务正在断开连接,因为它无法执行成功的握手。正如你所指出的,TLS版本可能是一个问题。无法找到兼容的密码可能是另一个问题。

我偶然发现了this blog post,它描述了如何将握手信息写入跟踪文件。下面是他增加了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连接,该服务器不再支持。我已在下面的评论中提供了详细信息。

+1

不错的发现,我会用输出更新我的帖子。谢谢 – Rodders

+0

在来自Socket#52088480 :: PostCompletion的数据之后的字节块中,第一个字节是内容类型('0x16'),即握手。接下来的两个字节是版本('0x03'和'0x01'),它是TLS 1.0。 TLS 1.2发送'0x03'和'0x03'。源[RFC 5246 - TLS 1.2](https://tools.ietf.org/html/rfc5246)和[RFC 2246 - TLS 1.0](https://www.ietf.org/rfc/rfc2246.txt) – Trumpi

+0

I看到。所以我们使用TLS1.0。另外,如果我通过将targetFramework升级到4.6来解决此问题,则该请求将起作用,但我没有在该跟踪文件中获取任何日志。是否有可能我们使用TLS1.2,并且使其恢复到1.0? – Rodders

相关问题