自從SEOTcs系統11月份24日更新了一下SEO得分演算法以來,一直困擾我的一個問題出現了,java的資料job任務,在執行過程中會經常報以下的錯誤:
“2011-12-03 18:00:32 DefaultHttpClient [INFO] I/O exception (java.net.SocketException) caught when processing request: Connection reset by peer: socket write error
2011-12-03 18:00:32 DefaultHttpClient [INFO] Retrying request”…
為此,我找遍了中英文的一些網站,搜遍了能找的每個角落,發現了出現這種狀況的原理,該java異常在用戶端和伺服器端都有可能發生,引起該異常的原因有兩個:
1,如果一端的Socket被關閉(或主動關閉,或因為異常退出而 引起的關閉),另一端仍發送資料,發送的第一個資料包引發該異常(Connect reset by peer)。
2,一端退出,但退出時並未關閉該串連,另一端如果在從串連中讀資料則拋出該異常(Connection reset)。簡單的說就是在串連斷開後的讀和寫操作引起的。
於是我簡單的認為通過設定一些socket的timeout時間,就能解決:
但是設定以後情況依然是那樣。
這個問題困擾了好幾天,每天都在思考和對比測試中,以求發現造成這個原因代碼的地方,我不禁思考,同樣數量的關鍵詞數量前提下,為什麼之前批量查詢排名資料沒有出錯,而最近會頻繁報錯,這到底是為什嗎?是被請求的介面網站屏蔽掉了我們的伺服器ip?這個理由也不是很充分,肯定是程式中某個地方沒有合理釋放掉connection的串連導致!
在這個思路的指引下,通過幾天連續的奮戰和實踐,今天終於發現了問題的本質,那就是那個timer的方法導致的!情況是這樣的,這幾天,我在手動觸發一些批量任務,發現在過濾排名值為100的情況下,java的java.net.SocketException: Connection reset 這個錯會一直拋出,而且刷屏特別厲害,在仔細對照了timer的這段代碼
後,終於猛然醒悟,對!就是這裡出問題了,我自己來分析一下:
一個函數值,它返回的值,是一個臨界值,但是我這個timer的方法中,判斷了返回的值如果是臨界值的話,會迫使它在10秒內繼續執行那個方法,而這個方法是要去擷取一個頁面中原始碼的一個特定資料,每次這個方法執行會消耗掉幾十毫秒的時間,即相當於在這個時間內,是建立了一個socket串連,但是由於它一直返回的是那個臨界值,所以這個方法會在10秒內不停的建立socket串連以擷取資料,如果這個方法每次執行時間大概是80ms(經過測試,每個這樣的方法執行時間為80毫秒左右),在10秒時間內,會建立10*1000/80 = 125次socket串連,即每秒會建立起12.5個socket串連,再加上由於這個是過濾的程式,多個臨界值的情況會連續出現在一起,所以,在短暫的幾秒鐘內,對同一個網站頁面的socket串連數會飆升的很高,達到幾百甚至上千,導致等待處理的請求串連數太高:
當初為什麼會用這個定時器方法來讓一個方法多執行幾遍,原因就是為了擷取一個資料的穩定值,但是現在想來,帶來的負面影響代價是多麼的大,產生的效果是不可小覷的,不過經過幾天的綜合分析和測試,終於還是發現了這個罪魁禍首,問題解決後,心,一下子豁然了,可以安心睡覺了。。。