Socket發送請求“超時”——接收數據方式引起的bug
一、場景描述
前段時間對接某家銀行的資管外圍系統,測試環境測試通過,聯調報告經銀行風控部門審批通過,上線時出現嚴重問題(不能正常發送/接收請求):發送請求成功、接收數據失敗並拋出SocketTimeoutException。
對接使用的技術:Socket(接觸的兩家銀行(一家股份制商業銀行、一家國有銀行(四大行之一))的外圍系統都是使用Socket,是不是銀行對外接口大多使用Socket?)
二、分析過程
出現問題後,馬上向銀行方技術團隊反饋,希望他們能夠給出一些有效的解決方案;首先要確定的就是他們是否接收到請求,因爲他們沒有權限登錄到服務器查看信息,所以只能第二天去看(正好第二天要去投產),所以約定好投產之後查看日誌確定是否接受到請求(第二天告訴我沒收到我們這邊的請求,表示很無奈);我這邊也跟蹤一下路由,看看網絡通信這些是否正常,使用traceroute命令看時並沒有發現問題,發送/接收都很正常。這時候猜想可能是銀行方給的請求的jar有點小瑕疵。在對接羣裏找其他接入方問問吧,看看他們有沒有出現過類似的問題,我勒個去,除了我 沒人有這問題。
個人感覺代碼的問題應該也不大,但就是不知道問題在哪(後來問銀行的技術團隊,他們的告訴我那個jar(其實就是幾個java文件)後來改過,但是他們手上沒有最新的,要第二天才能給我,找其他對接方要吧,人在出差得回去才能給我)。
沒辦法,只能根據他們說的問題自己改了(原來的接收數據方式比較慢);首先試了下把超時時間加大,從原來的60秒增加到120秒(我的天,一個請求完成大概用了70秒左右),接收數據正常,確定能夠正常發送/接收後,改了下接收數據的方式(先獲取數據長度,再根據長度獲取報文數據)。
三、部分代碼
原來的接收數據處理方式:
// 接收消息 BufferedReader socketIn = new BufferedReader( new InputStreamReader(sslSocket.getInputStream()));// 接受到的信息 String rtnStr = ""; String valueString = ""; while ((valueString = socketIn.readLine()) != null) { rtnStr += valueString; } if (StringUtils.isEmpty(rtnStr) || rtnStr.length() <= 8) { throw new FcsAppException("SDER01", "銀行無應答數據"); }
更改後的接收數據處理方式:// 接收消息 BufferedReader socketIn = new BufferedReader( new InputStreamReader(sslSocket.getInputStream()));// 接受到的信息 char[] messageLenChars = new char[XML_MESSAGE_LENGTH]; socketIn.read(messageLenChars); int dataLen = Integer.valueOf(new String(messageLenChars));// 先獲取報文長度 String rtnStr = ""; if (dataLen > 0) { char[] dataChars = new char[dataLen]; socketIn.read(dataChars); rtnStr = new String(dataChars); } if (StringUtils.isEmpty(rtnStr) || rtnStr.length() <= 8) { throw new FcsAppException("SDER01", "銀行無應答數據"); }
三、總結
測試環境使用的是Socket
正式環境使用的是SSLSocket
使用readLine時,連接正式環境出現SocketTimeoutException,可能是外圍資管系統響應數據後沒有主動結束,導致已知等待;已知數據長度,直接使用read(char[])讀取數據,避免等待。