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即可修复它,但我的任务是调查它。
这是潜在的错误:
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工作。但它并没有解释为什么它突然停止了。
更新 - 根据@Trumpi建议从trace.log输出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 - 删除了不必要的日志^^
答案 0 :(得分: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 :(得分:1)
有趣的是,上周我遇到了一个非常类似的问题(虽然它不是.NET Core)。我通过日常工作几个月来一直在调用API端点,突然间我得到了同样的错误。我花了好几天才找到修复程序,但对我来说,添加以下代码行修复了这个问题。您可以将它添加到方法的第一行。
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;