在多线程环境中重用JAX RS Client(具有resteasy)

Ale*_*ndr 16 java multithreading jax-rs jersey resteasy

根据文件,

"客户端是管理客户端通信基础设施的重量级对象.初始化以及客户端实例的处理可能是一项相当昂贵的操作.因此建议在应用程序中仅构建少量客户端实例."

好吧,我正在尝试将Client本身和WebTarget实例缓存在一个静态变量中,someMethod()在多线程环境中调用:

private static Client client = ClientBuilder.newClient();
private static WebTarget webTarget = client.target("someBaseUrl");
...
public static String someMethod(String arg1, String arg2)
{
    WebTarget target = entrTarget.queryParam("arg1", arg1).queryParam("arg2", arg2);
    Response response = target.request().get();
    final String result = response.readEntity(String.class);
    response.close();
    return result;
}
Run Code Online (Sandbox Code Playgroud)

但有时(并非总是)我得到一个例外:

BasicClientConnManager的使用无效:仍然分配了连接.确保在分配另一个连接之前释放连接.

如何正确地重用/缓存Client/WebTarget?是否可以使用JAX RS Client API?或者我必须使用一些特定于框架的功能(resteasy/jersey)你能提供一些示例或文档吗?

Pat*_*ick 8

由于此问题在编写时仍处于打开状态(版本3.0.X),因此RESTEASY:不推荐使用Apache类清理

您可以更深入地使用较新的,不推荐使用的类来创建resteasy客户端.您还可以更好地控制池的使用方式等.

这是我做的:

// This will create a threadsafe JAX-RS client using pooled connections.
// Per default this implementation will create no more than than 2
// concurrent connections per given route and no more 20 connections in
// total. (see javadoc of PoolingHttpClientConnectionManager)
PoolingHttpClientConnectionManager cm =
        new PoolingHttpClientConnectionManager();

CloseableHttpClient closeableHttpClient =
        HttpClientBuilder.create().setConnectionManager(cm).build();
ApacheHttpClient4Engine engine =
        new ApacheHttpClient4Engine(closeableHttpClient);
return new ResteasyClientBuilder().httpEngine(engine).build();
Run Code Online (Sandbox Code Playgroud)

还要确保在拨打电话后释放连接.调用response.close()会为你做这个,所以可能把它放在finally块中.


lef*_*loh 7

您的实现不是线程安全的.当两个线程同时访问someMethod它们共享时Client,一个将尝试发出第二个请求,而第一个请求未完成.

你有两个选择:

  • 同步访问ClientWebTarget手动.
  • 让容器通过注释@javax.ejb.Singleton用于保证线程安全的封闭类型来管理并发性.(参见EJB规范的第4.8.5章)

如果someMethod在容器管理环境中,我会使用第二种方法.

  • 这是不正确的。客户端是要共享的。这就是客户端实现类具有易变变量的原因。WebTarget不是线程安全的。 (4认同)
  • @SaptarshiBasu:正如链接问题[Is JAX-RS Client Thread Safe](http://stackoverflow.com/questions/24700798/is-jax-rs-client-thread-safe)中所讨论的,不幸的是规范不要求`Client` 是线程安全的。在某些实现中它是(例如在 Jersey,我相信),在其他实现中它不是(例如 Apache CXF)。 (3认同)