DeferredResult的使用

阅读:630
作者:majingjing
发布:2021-11-22 16:50:04

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

结果为 : 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