Hai*_*man 10 java rest multithreading jersey servlet-3.0
我正在研究一个有两种口味的项目,有多种租赁方式.
该项目公开了一个我希望异步的REST服务.所以我的基本服务看起来像
@Component
@Path("/resouce")
@Consumes(MediaType.APPLICATION_JSON)
public class ResouceEndpoint {
@POST
@ManagedAsync
public void add(final Event event, @Suspended final AsyncResponse asyncResponse) {
resouce.insert (event);
asyncResponse.resume( Response.status(Response.Status.NO_CONTENT).build());
}
}
Run Code Online (Sandbox Code Playgroud)
没有多租户就可以正常工作,我可以免费获得内部Jersey执行器服务的好处.请参阅@ManagedAsync
当我切换到多租户时,我在请求上添加了一个过滤器,用于解析租户ID并将其放在本地线程上(在我们的例子中是HTTP线程).
当处理链命中上面的"add()"方法时,当前线程是Jersey执行器服务提供的线程,因此它不包括我的租户ID.我只能考虑以下选项来解决这个问题.
将ResouceEndpoint扩展为MutliTenantResouceEndpoint并使用我自己的线程执行器删除@ManagedAsync
public class MutliTenantResouceEndpoint extends ResouceEndpoint {
@POST
public void add(final Event event, @Suspended final AsyncResponse asyncResponse) {
final String tenantId = getTeantIdFromThreadLocal();
taskExecutor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
setTeantIdToThreadLocal(tenantId);
browserEventsAnalyzer.insertEvent(event);
Response response = Response.status(Response.Status.NO_CONTENT).build();
asyncResponse.resume(response);
return null;
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
但是这样我需要管理自己的线程执行器,感觉就像我在这里遗漏了一些东西.有关不同方法的任何建议吗?
Ald*_*den 16
以下是一些建议.
对于背景,我已经使用泽西岛2年了,18个月前就遇到了这个问题.
@ManagedAsync
如果您可以控制运行Jersey的http服务器,我建议您停止使用@ManagedAsync
.
而不是设置Jersey立即返回它的http处理线程并将实际请求工作卸载到托管执行程序服务线程,为您的http服务器使用Grizzly之类的东西,并将其配置为具有更大的工作线程池.这实现了同样的目的,但是将同步责任推到泽西岛下面的一层.
如果您使用@ManagedAsync
任何中型到大型项目,您将在一年内遇到许多痛点.以下是他们中的一些:
return
陈述@Context
和ContainerRequest
属性这将涉及调用requestContext.setProperty("tenant_id", tenantId)
您的过滤器,然后requestContext.getProperty("tenant_id")
使用@Context
注入的请求调用您的资源中的调用.
这将涉及设置HK2绑定,InterceptionService
该绑定具有MethodInterceptor
检查托管异步资源方法并手动执行所有RequestScoped
绑定ContainerRequestFilter
的方法.而不是你的过滤器在Jersey注册,你用HK2注册它们,由方法拦截器运行.
如果您愿意,我可以向选项2/3添加更多详细信息和代码示例,或者提供其他建议,但首先查看更多过滤器代码会有所帮助,如果可能,我再次建议选项1.