1

OS之後的BindException:於Linux(Debian)
的Java:Java(商標)SE運行時環境(建立1.7.0_05-B06)
的Java:Java的熱點(TM )64位服務器VM(建設23.1 - B03,混合模式)
Apache的HTTP客戶端:v4.2.3(最新)的Apache HTTP客戶端 - >本地地址綁定 - >一段時間

我想創建一個PoolingConnectionManager有幾個客戶,各有其獨特的本地地址(ConnRoutePNames。 LOCAL_ADDRESS)。
這些客戶端將被幾個工作者使用(每個工作者選擇隨機客戶端並執行請求)。

的問題是:當我設置本地地址的客戶,一段時間後(例如1分鐘),我總是與消息「地址已在使用」得到java.net.BindException。

問題:它有問題嗎?

java.net.BindException: Address already in use 
at java.net.PlainSocketImpl.socketBind(Native Method) ~[na:1.7.0_05] 
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376) ~[na:1.7.0_05] 
at java.net.Socket.bind(Socket.java:627) ~[na:1.7.0_05] 
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:120) ~[httpclient-4.2.3.jar:4.2.3] 
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180) ~[httpclient-4.2.3.jar:4.2.3] 
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294) ~[httpclient-4.2.3.jar:4.2.3] 
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:645) ~[httpclient-4.2.3.jar:4.2.3] 
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480) ~[httpclient-4.2.3.jar:4.2.3] 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) ~[httpclient-4.2.3.jar:4.2.3] 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) ~[httpclient-4.2.3.jar:4.2.3] 
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784) ~[httpclient-4.2.3.jar:4.2.3] 
at controllers.Test$Worker.run(Test.java:67) ~[test_2.9.1-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] 
at java.lang.Thread.run(Thread.java:722) [na:1.7.0_05] 

代碼(簡化):

public static void main(String[] args) throws UnknownHostException 
{ 
    ClientConnectionManager connManager = buildConnectionManager(30); 

    List<HttpClient> clients = new ArrayList<>(); 
    for(int i=0; i<8; ++i) 
    { 
     HttpClient client = buildClient(connManager, InetAddress.getByName("111.111.111." + (50 + i)); 
     clients.add(client); 
    } 

    for(int i=0; i<30; ++i) 
    { 
     new Thread(new Worker(clients)).start(); 
    } 
} 

public static ClientConnectionManager buildConnectionManager(Integer parallelism) 
{ 
    PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(); 
    connectionManager.setMaxTotal(parallelism); 
    connectionManager.setDefaultMaxPerRoute(parallelism); 

    return connectionManager; 
} 

public static HttpClient buildClient(ClientConnectionManager connectionManager, InetAddress localAddress) 
{ 
    DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager); 
    HttpParams params = httpClient.getParams(); 
    params.setParameter(ConnRoutePNames.LOCAL_ADDRESS, localAddress); 

    return httpClient; 
} 

private static class Worker implements Runnable 
{ 
    private List<HttpClient> clients = null; 

    public Worker(List<HttpClient> clients) 
    { 
     this.clients = clients; 
    } 

    public void run() 
    { 

     do 
     { 
      HttpGet httpGet = new HttpGet("http://google.com/robots.txt"); 
      HttpClient client = this.clients.get(new Random().nextInt(this.clients.size())); 

      try 
      { 
       HttpResponse httpResponse = client.execute(httpGet); 
       EntityUtils.consume(httpResponse.getEntity()); 

       logger.debug("Success request"); 
      } 
      catch(IOException e) 
      { 
       httpGet.abort(); 
       logger.info("IO error", e); 
      } 
     } 
     while(true); 
    } 
} 
+0

消耗響應後嘗試'httpResponse.releaseConnection()'。理想情況下,在如[所示](http://hc.apache.org/httpcomponents-client-ga/quickstart.html) – Pyranja

+0

@Pyranja所示的finally塊中,不,它不起作用。無論如何,這不會很好的解決我的問題:( –

回答

0

感謝您的回答!
是的,問題是與TCP/IP堆棧,但我無法得到爲什麼:)

所以,原因解釋如下。我創建了連接管理器(例如大小= 10),幾個客戶端(每個客戶端都有其唯一的本地地址)和幾個工作人員。
每個工作人員採用隨機客戶端並執行請求。
因此,一次可能有一個客戶可以同時執行多達10名員工。
在另一時間,另一個客戶可以並行執行多達10名工人。
這就是爲什麼經理中的所有10個連接都不能保持活躍狀態​​,他們總是關閉/創建。

對不起,打擾你了!

+0

你有你的解決方案的示例代碼? – spy

0

我能想到的唯一的理論是TCP/IP協議棧運行進出港口,並開始分配相同的端口號,而舊的連接新連接還沒有完全清理。我沒有看到這個問題是HttpClient中的一個錯誤。