2016-03-24 15 views
3

Ich habe eine Anwendung mit Apache HttpComponents 4.4.1 synchronen Server, die mehrere HTTP "Dienste" läuft, für jeden von ihnen starte ich HTTP-Server auf anderen Port. Wenn der Benutzer den Dienst zu beenden entscheidet, schloß ich HTTP-Server auf diesem Port mit diesem Code läuft nach unten:Proper Weg zum Herunterfahren Apache httpcomponents blockieren HTTP-Server

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

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

Ich habe folgendes Problem auf Linux: Wenn es Keep-alive geöffneten Verbindungen (keine Anforderung Verarbeitung), diese Steckdosen sind nicht geschlossen. Es wird nur ServerSocket- geschlossen:

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 

Im Versuch erneut zu starten HTTP-Server auf dem gleichen Port ein BindingException geworfen wird:

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) 

Unter Windows ist das Verhalten ist das gleiche, aber es gibt keine BindingException ist und die Der Server startet Prozessanforderungen ohne Probleme.

+0

Könnten Sie bitte einen Testfall zusammenstellen, der das Problem reproduziert und eine JIRA unter https://issues.apache.org/jira/ erstellt? – oleg

Antwort

0

Ihr Problem ist, dass die Verbindung nicht geschlossen ist. Die HTTP-Spezifikation gibt nicht an, wie lange eine dauerhafte Verbindung am Leben erhalten werden soll.

Von documentation:

Einig HTTP-Server verwenden, um einen Nicht-Standard-Keep-Alive Header des Kunden kommuniziert die Zeit in Sekunden sie beabsichtigen, hält die Verbindung am Leben auf der Serverseite. HttpClient verwendet dieser Informationen, falls verfügbar. Wenn der Keep-Alive Header nicht in der Antwort vorhanden ist, nimmt HttpClient an, dass die Verbindung unbegrenzt am Leben gehalten werden kann.

So raten sie Ihre KeepAliveStrategy zu schaffen, um diese Verbindungen nach einer bestimmten Zeit zu beenden:

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

Ich verwende HTTP-Komponenten ** Server **. Mein Code läuft serverseitig. Ich weiß nicht, welche Clients sich mit meinem Server verbinden werden. –