繁体   English   中英

正确关闭Apache httpcomponents阻止HTTP服务器的方法

[英]Proper way to shutdown Apache httpcomponents blocking HTTP server

我有Apache HttpComponents 4.4.1 同步服务器的应用程序,它运行几个HTTP“服务”,每个我在不同的端口启动HTTP服务器。 当用户决定停止服务时,我使用以下代码关闭在此端口上运行的HTTP服务器:

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

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

我在Linux上遇到以下问题:如果打开了Keep-alive连接(没有请求处理),则不会关闭这些套接字。 仅关闭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

尝试在同一端口上再次启动HTTP服务器时抛出BindingException:

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,服务器启动进程请求没有任何问题。

结果证明是一个错误: https: //issues.apache.org/jira/browse/HTTPCORE-420 oleg已经提出修复。 我将在正式发布时更新此信息。

您的问题是连接未关闭。 HTTP规范没有规定持久连接应该保持多长时间。

来自文档

某些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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM