我正在使用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) {
}
...
}
答案 0 :(得分:4)
在示例代码中,您将获得JAX-RS响应,默认情况下 getEntity()方法将返回 InputStream 。因此,由于CXF不负责使用流,这显然是敞开的。
如果您没有明确关闭它,它将在垃圾收集阶段关闭。 但即使这样,在高流量速率下,这种小延迟也会阻止底层HTTP连接重新插入由HttpURLConnection利用的内部持久连接池(CXF在引擎盖下使用)。所以它不能按时重复使用。
如果您负责关闭InputStream,则不应再看到大量的TIME_WAIT套接字。
答案 1 :(得分:1)
我肯定会尝试更新到更新且受支持的CXF版本。在较新版本的CXF中,JAX-RS的内容已经有很多更新,这个问题可能已经修复。