在多线程环境中重用 JAX RS 客户端(带 resteasy)
根据文档,
客户端是管理客户端的重量级对象通信基础设施.初始化和处置客户端实例可能是一个相当昂贵的操作.因此是建议在应用."
"Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application. "
好的,我正在尝试将 Client 本身和 WebTarget 实例缓存在静态变量中,在多线程环境中调用 someMethod():
Ok, I'm trying to cache Client itself and WebTarget instances in a static variable, the someMethod() is invoked in multi-threaded environment:
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;
}
但有时(并非总是)我会遇到异常:
But sometimes (not always) I'm get an exception:
BasicClientConnManager 使用无效:连接仍然分配.确保在分配另一个连接之前释放连接.
Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one.
如何正确重用/缓存 Client/WebTarget?可以使用 JAX RS 客户端 API 吗?或者我必须使用一些特定于框架的功能(resteasy/jersey)你能提供一些示例或文档吗?
How can Client/WebTarget be reused/cached correctly? Is it possible with JAX RS Client API? Or I have to use some framework-specific features (resteasy/jersey) Could you provide some example or documentation?
推荐答案
你的实现不是线程安全的.当两个线程同时访问 someMethod
时,它们共享相同的 Client
并且一个线程将尝试在第一个请求未完成时发出第二个请求.
Your implementation is not thread-safe. When two threads access someMethod
at the same time they are sharing the same Client
and one will try to make a second request while the first one is not finished.
你有两个选择:
- 手动同步对
Client
和WebTarget
的访问. - 让容器通过使用
@javax.ejb.Singleton
注释封闭类型来管理并发,这保证了线程安全.(参见 EJB 规范)
- Synchronize the access to the
Client
andWebTarget
manually. - Let the container manage concurrency by annotating the enclosing type with
@javax.ejb.Singleton
which guarantees thread safety. (see chapter 4.8.5 of the EJB specification)
如果 someMethod
在容器管理的环境中,我会使用第二种方法.
If someMethod
in a container managed environment I would use the second approach.
相关文章