【问题标题】:Limit HTTP response size on Spring WebFlux限制 Spring WebFlux 上的 HTTP 响应大小
【发布时间】:2018-08-24 07:25:22
【问题描述】:

我正在使用 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 来包装它以继续使用这些原语会很好

【问题讨论】:

    标签: spring-boot spring-webflux


    【解决方案1】:

    如果您使用的是 Spring Boot,您应该使用自动配置的 WebClient.Builder 创建您的 WebClient;这将反映 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(它还没有发布),您可以随时查看过滤器功能实现并将该代码复制/粘贴到您的项目中,它非常简短。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-11
      • 1970-01-01
      • 2022-11-14
      相关资源
      最近更新 更多