CXF JAXRS客户端不重用TCP连接

时间:2011-07-11 15:44:48

标签: rest tcp cxf jax-rs keep-alive

我正在使用CXF 2.2.5中的JAX-RS支持来调用REST Web服务。我正在为需要与之通信的每个端点创建单个org.apache.cxf.jaxrs.client.WebClient实例(通常是任何给定部署的一个或两个端点),并为每个Web服务调用重新使用此客户端。

我遇到的问题是客户端正在为每个请求创建到服务器的新TCP连接,尽管使用了keep-alive设置。在高流量水平下,这会导致问题。我的客户代码摘录如下。

我正在尝试挖掘CXF来源以确定问题,但目前正在失去绝望。任何想法都非常感激。

谢谢, FB

ConcurrentMap<String, WebClient> webclients = new ConcurrentHashMap<String, WebClient>();

public void dispatchRequest(MyRequestClass request, String hostAddress) {

    // Fetch or create the web client if we don't already have one for this hostAddress
    // NOTE: WebClient is only thread-safe if not changing the URI or headers between calls!
    //   http://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-ThreadSafety
    WebClient client = webclients.get(hostAddress);
    if (client == null) {
        String serviceUrl = APP_HTTP_PROTOCOL + "://" + hostAddress + ":" + APP_PORT + "/" + APP_REQUEST_PATH;
        WebClient newClient = WebClient.create(serviceUrl).accept(MediaType.TEXT_PLAIN);
        client = webclients.putIfAbsent(hostAddress, newClient);
        if (client == null) {
            client = newClient;
        } // Else, another thread must have added the client in the meantime - that's fine if so.
    }

    XStream marshaller = MyCollection.getMarshaller();
    String requestXML = marshaller.toXML(request);

    Response response = null;
    try {
        // Send it!
        response = client.post(requestXML);
    }
    catch (Exception e) {
    }

    ...
}

2 个答案:

答案 0 :(得分:4)

在示例代码中,您将获得JAX-RS响应,默认情况下 getEntity()方法将返回 InputStream 。因此,由于CXF不负责使用流,这显然是敞开的。

如果您没有明确关闭它,它将在垃圾收集阶段关闭。 但即使这样,在高流量速率下,这种小延迟也会阻止底层HTTP连接重新插入由HttpURLConnection利用的内部持久连接池(CXF在引擎盖下使用)。所以它不能按时重复使用。

如果您负责关闭InputStream,则不应再看到大量的TIME_WAIT套接字。

答案 1 :(得分:1)

我肯定会尝试更新到更新且受支持的CXF版本。在较新版本的CXF中,JAX-RS的内容已经有很多更新,这个问题可能已经修复。