首页 > 解决方案 > webclient阻塞主线程netty,为什么?

问题描述

我不明白为什么 webclient 会阻塞我使用 gradle 的主 netty 线程,这里是它的依赖项:

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR11"
    }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    ...
}

此 gradle 脚本用于两个应用程序。在第一个应用程序中,我执行:

    @GetMapping
    open fun otherApp(): Mono<String> {
        return WebClient.create("http://localhost:8081")
                .get()
                .uri("/test")
                .retrieve()
                .bodyToMono(String::class.java)
//              I tried to use an additional scheduler but the main stream is blocked with it too
//              .publishOn(Schedulers.boundedElastic())
    }

第二个应用程序模拟一个长响应处理:

@GetMapping("/test")
    open fun test(): Mono<String> {
        Thread.sleep(15000L)
        return Mono.just("Hello");
    }

而且我希望调用服务不会阻塞主线程,而是会继续处理传入的连接,但是直到我从第一个调用中得到响应(睡眠会起作用),我的下一个连接都处于等待状态。

结果:第一个应用程序像 tomcat 一样工作,只有一个线程

我的问题:我做错了什么?

标签: springkotlinnettywebclientblocking

解决方案


客户端应用程序不会阻塞,它能够处理新请求。您可以通过添加日志来确认:

@GetMapping("/test")
public Mono<String> test() {
    return Mono.just("incoming request")
        .doOnNext(e -> logger.info("Process: {}", e))
        .flatMap(e -> webclient.test());
}

服务器应用程序被阻塞,因为Thread.sleep(15000L)阻塞了主线程(考虑.delayElement(Duration.ofSeconds(15))改用)

如果由 Web 浏览器发起的请求出现问题

这是由于浏览器缓存。您应该禁用缓存或强制硬刷新 (CTRL + F5)。

我测试了硬刷新,它似乎工作正常。


推荐阅读