其具体实现在:org.springframework.aop.interceptor.AsyncExecutionInterceptor,是一个方法拦截器,其invoke方法的部分代码如下:
Java代码
Future<?>result = determineAsyncExecutor(specificMethod).submit(
new Callable<Object>() {
public Object call() throws Exception {
try {
Object result = invocation.proceed()
if (result instanceof Future) {
return ((Future<?>) result).get()
}
}
catch (Throwable ex) {
ReflectionUtils.rethrowException(ex)
}
return null
}
})
即把当前任务的调用提交给线程池,很简单。
1、测试无事务的异步任务
这个相对来说比较简单:
1.1、设置任务的返回值为Future:
Java代码
public Future sendSystemMessage(Long[] receiverIds, Message message)
1.2、调用future.get()等待任务结束。
Java代码
Future future = messageApi.sendSystemMessage(userIds, message)
future.get()
这个很简单。
2、测试带事务的异步任务
因为是带事务的,所以异步任务肯定要启动一个线程来执行任务,所以无法在主线程回滚,造成数据会commit到数据库,这在集成测试时肯定是不行的;解决方案是移除异步任务:
2.1、使用spring profile,在测试环境下不执行<task:annotation-driven>即可。
2.2、使用我提供的工具类,在测试时移除异步支持即可:
Java代码
//移除异步支持
if(AopProxyUtils.isAsync(messageApi)) {
AopProxyUtils.removeAsync(messageApi)
}
测试类可以参考MessageApiServiceIT.java
工具类下载 AopProxyUtils.java
3、包级别测试
Java代码
@Async
public void sendSystemMessage() {
sendSystemMessageInner()
}
void sendSystemMessageInner() {
//测试时测试这个方法即可
}
这样测试时测试这个包级别的sendSystemMessageInner方法即可
其实更好的做法是spring内部提供支持,支持这样异步调用的测试。
实现方案使用TransactionSynchronizationManager在事务提交之后 *** 作
public void insert(TechBook techBook){
bookMapper.insert(techBook)
// send after tx commit but is async
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter()
{
用tornado毕竟是可以做异步request的, 如果你的数据库真的很慢, 不如再开其他的tornado做block数据库 *** 作(你可以用tornado wsgi多线程/多进程形式部署, 也可以用django, flask等), 然后通过API的形式将数据库返回过来. 相当于用tornado给你的数据库 *** 作web化(写内部数据API)这个是我刚才刚刚想到的, 原理就是用一些独立的进程去做费时的数据库 *** 作, 这样你的主web tornado进程就可以异步畅通, 增加吞吐量. 这样就不需要为各个数据库写驱动了.
如果数据库在不同的机器上, 那么可以考虑将这些独立的数据 *** 作tornado进程在数据库机器上部署. 使用wsgi多线程/多进程的好处是查询可以同时进行, 当然也可能卡死数据库. 使用tornado自己的单进程异步部署的时候, tornado还可以充当一个数据库 *** 作队列的作用.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)