DeferredResult的使用
功能
当一个请求到达API接口,在没有超时或者DeferredResult对象设置setResult时,接口不会返回,但是Servlet容器线程会结束,DeferredResult另起线程来进行结果处理(即这种操作提升了\服务短时间的吞吐能力**),并setResult,如此以来这个请求不会占用服务连接池太久,如果超时或设置setResult,接口会立即返回。
使用DeferredResult的流程:
- 浏览器发起异步请求
- 请求到达服务端被挂起
- 向浏览器进行响应,分为两种情况:
- 调用
DeferredResult.setResult()
,请求被唤醒,返回结果 - 超时,返回一个你设定的结果
- 调用
- 浏览器得到响应
示例代码
@RestController
@Validated
@Slf4j
public class AsyncController {
static final Map<String,DeferredResult<String>> MAP = new HashMap<>(16);
@GetMapping("/call")
public DeferredResult<String> process(String name,Long t){
DeferredResult<String> deferredResult = new DeferredResult<String>(t,"time out");
MAP.put(name,deferredResult);
deferredResult.onCompletion(()->{
log.info("onCompletion t: "+ t);
});
deferredResult.onTimeout(()->{
log.info("onTimeout t: "+ t);
});
log.info("process t: "+ t);
return deferredResult;
}
@GetMapping("/call/over")
public String logs(String name){
DeferredResult<String> deferredResult = MAP.remove(name);
deferredResult.setResult("call/over -> success");
return "success";
}
}
测试
http://127.0.0.1:8080/call?t=20000&name=zs , 超时时间20s" class="reference-link">请求 http://127.0.0.1:8080/call?t=20000&name=zs , 超时时间20s
结果为 : time out
控制台输出:
process t: 20000
onTimeout t: 20000
onCompletion t: 20000
再次请求 http://127.0.0.1:8080/call?t=20000&name=zs , 超时时间20s ,
在20s内执行请求 http://127.0.0.1:8080/call/over?name=zs
结果为: call/over -> success
控制台输出:
process t: 20000
onCompletion t: 20000