使用Spring 6新HTTP Interface时遭遇blocking read超时问题
解决Spring 6 HTTP Interface中blockingGet超时问题
问题核心
你遇到的IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS异常,是Reactor中Mono.block()方法的默认超时(5秒)导致的,和你设置的5秒连接超时、10秒ReadTimeoutHandler是完全独立的两个超时控制:
ReadTimeoutHandler是TCP层面的读取超时,控制已建立连接后等待数据的时间- blockingGet的超时是控制阻塞调用等待响应Mono完成的最大时间
解决方案
根据你的Spring版本,有两种简单处理方式:
方式1:Spring 6.1及以上版本(推荐)
Spring 6.1给HttpServiceProxyFactory.Builder新增了blockTimeout方法,可直接设置阻塞调用的超时时间:
HttpClient client = HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(10000L, TimeUnit.MILLISECONDS))); WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(client)) .baseUrl(locationUrl.toExternalForm()) .build(); // 设置block超时为10秒 HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient)) .blockTimeout(Duration.ofSeconds(10)) .build();
方式2:Spring 6.1以下版本
通过给WebClient添加ExchangeFilterFunction,为每个请求的响应Mono添加超时控制,会在block超时前先触发响应超时:
HttpClient client = HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(10000L, TimeUnit.MILLISECONDS))); WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(client)) .baseUrl(locationUrl.toExternalForm()) // 给每个请求添加10秒超时 .filter((request, next) -> next.exchange(request) .timeout(Duration.ofSeconds(10))) .build(); HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient)) .build();
说明
两种方式都能让阻塞调用的超时和你设置的ReadTimeoutHandler保持一致(10秒),避免出现默认的5秒阻塞超时异常。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

