1. 程式人生 > >java.net.SocketException: No buffer space available (maximum connections reached?): connect 問題分析

java.net.SocketException: No buffer space available (maximum connections reached?): connect 問題分析

  • 異常日誌
 Caused by: java.net.SocketException: No buffer space available (maximum connections reached?): connect
    at java.net.TwoStacksPlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206
) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:121
) at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180) at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:326) at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:610
) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:445) at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
  • 問題分析
    網上說No buffer space available (maximum connections reached?)是因為機器埠號用盡導致tcp無法申請新的埠去建立連線。首先想到去檢視機器埠號使用情況。
    這裡寫圖片描述
    大量的埠處於TIME_WAIT狀態,初步估計可能是客戶端每次去請求服務端都建立了一次tcp連線,使用完就關閉連線,但是tcp協議中如果客戶端主動關閉,為了確保傳送的報文不影響下一次連線,主動關閉的一方需要停留在TIME_WAIT狀態2*MSL(Max Segment Lifetime)。當併發高的時候,就會產生大量TIME_WAIT,而處於TIME_WAIT狀態的埠是不能馬上去建立新的連線的,這就導致No buffer space available (maximum connections reached?)這個異常。

  • 問題修復
    排查程式碼發現有一處rest請求每次都會建立一個httpclient。相當於每次都要重新建立tcp連線,完成3次握手和4次揮手。
    這裡寫圖片描述
    修復後的程式碼是使用http連線池,服用重複的http連線。這樣不必每次都去建立新的tcp連線。不僅可以避免埠被佔滿,也可以提升io的效能(tcp連線建立和關閉是需要開銷的)。httpclient提供PoolingHttpClientConnectionManager類支援http連線池的管理。