This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

全链路异步

当前Restlight版本支持FilterHandlerInterceptor, Controller, ExceptionHandler异步。

对应处理链路

restlightexecution.png

上述对应着一个请求的完成执行链路, 并且每个链路都支持异步。

1 - Restlight 异步保证

Restlight保证在框架层面对所有的CompletableFuture处理都不会主动的切换执行的线程

这个保证使得用户无需担心不知道自己的代码将会在什么线程上执行。

用户在HandlerInterceptor中写下了如下代码

private final Executor customExecutor = ...;
            
@Override
public CompletableFuture<Boolean> preHandle0(AsyncRequest request,
                                             AsyncResponse response,
                                             Object handler) {
    // 线程切换到 customExecutor并回调Restlight
    return CompletableFuture.supplyAsync(() -> {
        // ....
        return true;
    }, customExecutor);
}

其中当执行HandlerInterceptor.preHandle(xxx)时用户使用了自定义的线程池作为异步实现,并在完成操作后回调Restlight, 后续所有Controller, ExceptionHandler等操作都将在customExecutor的线程上执行(除非用户主动切换)

下面的Controller将会在customExecutor的线程上被调用, 而不是业务线程池

@GetMapping(value = "/test")
public String foo() {
    // biz logic
    return "Hello Restlight!";
}

如果需要回到业务线程池执行则需要用户自行通过CompletableFuture进行操作

@GetMapping(value = "/test")
public CompletableFuture<String> foo() {
    // 回到业务线程池执行Controller逻辑
    return CompletableFuture.supplyAsync(() -> {
        // biz logic
        return  "Hello Restlight!";
    }, bizExecutor);
}

2 - CompletableFuture使用注意

  • CompletableFuture不带xxxAsync(xxx)的方法默认会在当前线程执行(当前线程指的是调用CompletableFuture.complete(xxx)或者CompletableFuture.completeExceptionally(xxx)的线程), 因此此种方式CompletableFuture的线程执行策略为尽量不切换线程(这里的尽量并不是完全一定, 因为如果当前future已经为完成的状态那么CompletableFuture会直接执行后续逻辑)
  • CompletableFuturexxxAsync(xxx)的方法要求传入一个Executor, 后续回掉逻辑将在这个Executor中执行。 默认不传的情况下会使用ForkJoinPool中的公共线程池。 因此应当对所有的xxxAsync(xxx)方法调用格外注意, 一旦使用了错误的线程池可能导致隔离性的缺失, 性能不符合预期等问题。