限制 Spring WebFlux 上的 HTTP 响应大小
Limit HTTP response size on 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 header Content-Length 不可靠。我想我需要降低一级并直接使用字节缓冲区和 Netty 事件,但是最好使用 Flux/Mono 包装它以继续使用这些原语
如果您正在使用 Spring 启动,您应该使用自动配置的 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(尚未发布),您可以随时查看过滤器功能的实现,并将 copy/paste 代码添加到您的项目中,这非常棒短的。
我正在使用 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 header Content-Length 不可靠。我想我需要降低一级并直接使用字节缓冲区和 Netty 事件,但是最好使用 Flux/Mono 包装它以继续使用这些原语
如果您正在使用 Spring 启动,您应该使用自动配置的 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(尚未发布),您可以随时查看过滤器功能的实现,并将 copy/paste 代码添加到您的项目中,这非常棒短的。