2016-03-24 17 views
3

私はApache HttpComponents 4.4.1 でアプリケーションを持っています。複数のHTTP "services"を実行するは、それぞれ別のポートでHTTPサーバーを起動します。ユーザがサービスを停止することを決定したとき、私はこのコードで、このポート上で実行されているHTTPサーバのシャットダウン:Apache HTTPコンポーネントをシャットダウンする適切な方法HTTPサーバーをブロックする

org.apache.http.impl.bootstrap.HttpServer server; 
.... 

public void stopServer(){ 
    server.shutdown(42, TimeUnit.MICROSECONDS); 
} 

I Linux上で次のような問題があります開いたキープアライブ接続がある場合(要求がありません処理)、これらのソケットは閉じられません。のみのServerSocketを閉じている:

netstat -aon | grep 58276 
TCP 127.0.0.1:50658  127.0.0.1:58276  ESTABLISHED  18012 
TCP 127.0.0.1:58276  127.0.0.1:50658  ESTABLISHED  18012 

BindingExceptionがスローされているのと同じポート上で再びHTTPサーバを起動しようとする試みには:

Caused by: java.net.BindException: Address already in use 
at java.net.PlainSocketImpl.socketBind(Native Method) 
at java.net.PlainSocketImpl.socketBind(PlainSocketImpl.java:521) 
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:414) 
at java.net.ServerSocket.bind(ServerSocket.java:326) 
at java.net.ServerSocket.<init>(ServerSocket.java:192) 
at javax.net.DefaultServerSocketFactory.createServerSocket(ServerSocketFactory.java:170) 
at org.apache.http.impl.bootstrap.HttpServer.start(HttpServer.java:116) 

Windows上で動作は同じである、しかしBindingExceptionと何がありませんサーバーはプロセス要求を問題なく開始します。

+0

問題を再現したテストケースをまとめて、JIRAをhttps://issues.apache.org/jira/で作成してください。 – oleg

答えて

0

問題は接続が閉じていないことです。 HTTP仕様では、永続的な接続をどれくらい長く維持するかを指定していません。 documentationから

いくつかのHTTPサーバは秒単位の時間の期間は、彼らが に予定のクライアントと通信 に非標準Keep-Aliveヘッダーを使用し、サーバー側で生きて接続を維持。 HttpClientは、利用可能であれば、この情報の を使用します。 Keep-Aliveヘッダが でない場合、HttpClientは接続が無期限に生きていると仮定します。

そこで、彼らは一定時間後にそれらの接続を終了するために、あなたのKeepAliveStrategyを作成することをお勧め:

ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() { 

    public long getKeepAliveDuration(HttpResponse response, HttpContext context) { 
     // Honor 'keep-alive' header 
     HeaderElementIterator it = new BasicHeaderElementIterator(
       response.headerIterator(HTTP.CONN_KEEP_ALIVE)); 
     while (it.hasNext()) { 
      HeaderElement he = it.nextElement(); 
      String param = he.getName(); 
      String value = he.getValue(); 
      if (value != null && param.equalsIgnoreCase("timeout")) { 
       try { 
        return Long.parseLong(value) * 1000; 
       } catch(NumberFormatException ignore) { 
       } 
      } 
     } 
     HttpHost target = (HttpHost) context.getAttribute(
       HttpClientContext.HTTP_TARGET_HOST); 
     if ("www.naughty-server.com".equalsIgnoreCase(target.getHostName())) { 
      // Keep alive for 5 seconds only 
      return 5 * 1000; 
     } else { 
      // otherwise keep alive for 30 seconds 
      return 30 * 1000; 
     } 
    } 

}; 
CloseableHttpClient client = HttpClients.custom() 
     .setKeepAliveStrategy(myStrategy) 
     .build(); 
+0

私はhttp-components ** server **を使用しています。私のコードはサーバー側で動作します。私はどのクライアントが私のサーバに接続するのか分からない。 –

関連する問題