1. 程式人生 > >一個連接出錯問題的背後

一個連接出錯問題的背後

先說下基本背景:簡訊被封裝為服務,由於是外部呼叫,所以採用訊息佇列的方式來做非同步的簡訊傳送處理,簡訊傳送記錄會被儲存到mongodb中。

發生的異常:

簡訊服務無法傳送簡訊,具體異常如下

異常1

org.apache.axis.AxisFault: ; nested exception is: java.net.SocketException: Connection reset at org.apache.axis.AxisFault.makeFault(AxisFault.java:101) ~[mw-1.1.0.jar:na]at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:154) ~[mw-1.1.0.jar:na]at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32) ~[mw-1.1.0.jar:na]at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118) ~[mw-1.1.0.jar:na]at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83) ~[mw-1.1.0.jar:na]at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invokeEngine(Call.java:2784) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:2767) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:2443) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:2366) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:1812) ~[mw-1.1.0.jar:na]at mw.WmgwSoap_BindingStub.mongateSendSubmit(WmgwSoap_BindingStub.java:323) ~[mw-1.1.0.jar:na]

異常2:

org.apache.axis.AxisFault: (0)null at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.java:744) ~[mw-1.1.0.jar:na]at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144) ~[mw-1.1.0.jar:na]at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32) ~[mw-1.1.0.jar:na]at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118) ~[mw-1.1.0.jar:na]at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83) ~[mw-1.1.0.jar:na]at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invokeEngine(Call.java:2784) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:2767) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:2443) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:2366) ~[mw-1.1.0.jar:na]at org.apache.axis.client.Call.invoke(Call.java:1812) ~[mw-1.1.0.jar:na]at mw.WmgwSoap_BindingStub.mongateSendSubmit(WmgwSoap_BindingStub.java:323) ~[mw-1.1.0.jar:na]

由於是外部呼叫,所以開始懷疑是不是簡訊服務商不行了,後來在測試環境驗證,服務商一切正常,疑惑了很久,始終找不到原因,後來,同時發生問題的另外一個應用找出原因:一次從mongodb拉取大量資料。由於簡訊傳送記錄要儲存在mongodb中,立刻查詢程式碼,發現傳送簡訊業務和儲存mongodb的程式碼在一次同步呼叫中,簡單推理找到最終原因:

簡訊服務和另外一個出問題的應用共享mongo資料庫,由於另外一個應用從mongo中大量拉取資料,導致mongo處理速度變得奇慢無比,所以簡訊呼叫的業務會阻塞在儲存mongodb的程式碼塊中,由於簡訊服務請求很頻繁,所以大量的執行緒會啟動socket和簡訊服務商相連,又由於發生阻塞,大量保持socket的執行緒阻塞在系統中,連線得不到釋放,最終導致上面的錯誤。

總結:

不是核心步驟的業務可以走非同步過程。

設定合理的超時機制,避免無限制或長時間的等待。

connect reset可以從驗證外部服務、分析系統連線狀況來分析原因。

邏輯無關的業務資料可以分別存放,不用耦合在一起。