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