限制Spring WebFlux上的HTTP响应大小

时间:2018-08-24 07:25:22

标签: spring-boot spring-webflux

我正在使用Spring WebFlux编写http搜寻器,它很容易并行执行并具有HTTP超时:

val sitesToCrawl: Flux<String> = streamOfUrl()
val concurrencyLimit = 100
sitesToCrawl.flatMap(
    { WebClient.create().get().uri(it).exchange().timeout(Duration.ofSeconds(10)) },
    concurrencyLimit
)

但是如何限制页面响应的大小,例如我不想为每个URL下载超过500KB的数据。读取HTTP标头Content-Length不可靠。我想我需要下一层,直接使用字节缓冲区和Netty事件,但是使用Flux / Mono来包装这些原语会很好

1 个答案:

答案 0 :(得分:1)

如果您使用的是Spring Boot,则应使用自动配置的WebClient创建WebClient.Builder;这将反映Spring Boot的意见,例如,将根据您选择的配置选项来配置Jackson解码。

您还应该构建一个实例并将其用于许多请求,而不是为每个请求创建一个新的客户端实例-这样效率不高。

现在,从Spring Framework 5.1(Spring Boot 2.1)开始,Spring WebFlux附带了一个过滤器功能,该功能可以做到这一点:它将读取N个字节,然后取消响应(停止读取并关闭连接)。请注意,如果响应相当大,则此行为很有趣,但是这样做也会使连接不适合重用,并且不会返回到连接池。如果要在同一主机上爬网很多页面,则连接池与创建新连接是一个有趣的折衷。

现在看起来应该像这样:

@Component
public class CrawlingService {

  private WebClient webClient;

  public CrawlingService(WebClient.Builder builder) {
      this.webClient = builder.filter(ExchangeFilterFunctions.limitResponseSize(maxSize))
                    .build();
  }

  public Mono<Void> crawlPage(URI page) {
      return // use webClient here
  }  

}

如果您还没有准备好使用Spring Boot 2.1(尚未发布),则可以随时查看filter函数的实现并将该代码复制/粘贴到您的项目中,这很短。