Spring Webflux中的阻塞读取超时时间为5000毫秒。

42

我为 Handler(Spring Webflux)撰写了一个测试。

@Test
public void checkServicesHandlerTest() {
    Request request = new Request();
    request.setMsisdn("ffdfdfd");
    this.testClient.post().uri("/check")
                   .body(Mono.just(request), Request.class)
                   .exchange().expectStatus().isOk();
}

但是结果出现了错误。

Timeout on blocking read for 5000 MILLISECONDS

这个处理程序很简单:

 public Mono<ServerResponse> check(ServerRequest request) {
       
     Request request = request.bodyToMono(Request.class).block();

问题出在哪里?如果我直接向服务器发送请求,一切都正常。


1
这是你完整的处理程序实现吗?在处理程序内部使用 block() 是强烈不建议的,这可能是潜在问题的根本原因。 - Brian Clozel
谢谢。我写了一段没有块的代码,它运行得很好。你能否建议一个关于 Reactor3 或 Weblux 的好课程? - Mikhail
http://projectreactor.io/learn 和 https://bclozel.github.io/webflux-workshop/ 可能会很有用。 - Brian Clozel
你能回答自己的问题吗?这可能会帮助其他 Stack Overflow 用户。 - Brian Clozel
@BrianClozel 我遇到了同样的问题。我有一个集成测试(使用 Junit5 和 Spring Boot 2.0.0.RC1),通过调用一个 Web 服务获取所有用户,该服务从表中获取数据,该表最多可以有 50-60 个用户。当用户只有 15-20 个时,我看到测试过去曾经通过。现在它失败了,请给予建议。 - ROCKY
只是补充一下:如果你在测试运行期间进行调试,由于这可能需要更多时间,因此也可能会出现“阻塞读取超时”错误。 - Asriel
5个回答

66

我在运行集成测试时遇到了类似的问题和异常,其中一些测试聚合了来自多个其他服务的响应,这些服务具有数据库访问等功能。因此,当运行集成测试时,我们会间歇性地遇到此问题。我们使用的是Spring Boot 2.0.0.RC1和带Gradle的Junit 5。我做了以下操作来解决这个问题。关键是将WebClient突变为30秒的响应超时,以防万一。

@Autowired
private WebTestClient webTestClient;

@BeforeEach
public void setUp() {
    webTestClient = webTestClient.mutate()
                                 .responseTimeout(Duration.ofMillis(30000))
                                 .build();
}

7
无论我设置了多长的超时时间,我总是遇到超时问题。但如果我启动应用程序并直接测试端点,则我的rest api(与上面的相似)可以正常工作。 - DBS
2
嗨,我也遇到了同样的问题。即使我设置了超时时间,它仍然会抛出错误。还有其他想法如何解决它吗? - Sam
我必须说:#我也是 - du-it

60
@AutoConfigureWebTestClient(timeout = "36000")注解可以覆盖默认的超时时间。例如:
@AutoConfigureWebTestClient(timeout = "36000")
@SpringBootTest
class MyTestClass {
}

这对我的Spring Boot WebTestClient的超时时间没有任何影响... - zb226
3
我建议使用 ISO-8601 的持续时间格式。例如,对于 36 秒:@AutoConfigureWebTestClient(timeout = "PT36S") - RoBeaToZ
这很有帮助!我增加了超时时间,现在我可以看到实际的异常信息,而不是超时消息! - user1354825
1
有没有专门用于实现与使用注释@AutoConfigureWebTestClient相同行为的环境变量?如果有的话,调试将变得更容易,只需修改代码并传递运行/调试配置即可。 - Ankit Gaurav

1
使用WebTestClient时,您可以使用@AutoConfigureWebTestClient(timeout = "36000")来设置超时时间,其中timeout值是您选择的值。特别要考虑第三方服务的响应时间。

0

如果是Kotlin测试,可以使用以下示例:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class RouterTests {
    lateinit var client: WebTestClient

    private val dealService: DealService = QshDealService()
    private val dealStream: StreamHandler<MarketData> = DealStream(dealService)
    private lateinit var fileService: FileService

    @BeforeAll
    fun init() {
        val streamHandlers: Map<String, StreamHandler<MarketData>> = mapOf("dealStream" to dealStream)
        fileService = CommonFilesService(streamHandlers)
        val filesHandler = QshFilesHandler(fileService)
        this.client = WebTestClient
            .bindToRouterFunction(QshRouter(filesHandler).route())
            .configureClient()
            .responseTimeout(Duration.ofMillis(30000))
            .build()
    }

    @Test
    fun whenRequestToRoute_thenStatusShouldBeOk() {
        ...
    }

}

0

请检查您的pom文件,如果存在BlockHound依赖项,请将其删除。

<dependency>
  <groupId>io.projectreactor.tools</groupId>
  <artifactId>blockhound</artifactId>
  <version>$LATEST_RELEASE</version>
</dependency>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接