简体   繁体   English

Spring Reactive Webclient 的请求级背压?

[英]Request-level backpressure for Spring Reactive Webclient?

This is similar to How to do akka-http request-level backpressure?这类似于如何做 akka-http 请求级背压? but for the Spring echo system.但对于 Spring 回声系统。

I'm thinking about how to implement back-pressure for HTTP clients when using Spring WebClient in a reactive fashion.我正在考虑如何在以反应方式使用 Spring WebClient 时为 HTTP 客户端实现背压。 To me it sounds like the way to go would be for the WebClient to be aware of the HTTP semantics and apply back pressure on eg status "429 - Too Many Requests".对我来说,这听起来像是让 WebClient 意识到 HTTP 语义并对例如状态“429 - 请求过多”施加反压。 I've not found any documentation on this which makes me somewhat doubtful if this is the way to go.我没有找到任何关于此的文档,这让我有点怀疑这是否是要走的路。

Questions:问题:

  1. Does back pressure based on the HTTP response headers make sense (eg based on the 429 or 503 status code and Retry-After header)?基于 HTTP 响应标头的背压是否有意义(例如,基于 429 或 503 状态代码和Retry-After标头)? Or is there a better way of doing back-pressure over HTTP for non-streaming (request-response) use cases ?或者是否有更好的方法通过 HTTP为非流式(请求-响应)用例进行背压?
  2. Is something like this implemented in Webclient or some other library that works well with the Spring reactive echo-system?是否在 Webclient 或其他与 Spring 反应式回声系统配合良好的库中实现了类似的功能?
  3. If nothing like this currently exists and given that it makes sense, would it make sense to simply retry with the timeout set in the Retry-After header?如果当前不存在这样的情况并且考虑到它有意义,那么简单地使用Retry-After标头中设置的超时重试是否有意义?

TL;DR: Spring Framework and Reactor Netty don't provide that kind of support and I'm not aware of any library that does this. TL;DR:Spring Framework 和 Reactor Netty 不提供这种支持,我不知道有任何库可以做到这一点。

You could implement the behavior you're describing with a WebFilter that intercepts incoming requests before they're dispatched to handlers and reply with any HTTP status/header of your choice.您可以使用WebFilter实现您所描述的行为,该过滤器在传入请求被分派到处理程序之前拦截传入请求,并使用您选择的任何 HTTP 状态/标头进行回复。

The only tricky part is to decide whether the request should be rejected or not.唯一棘手的部分是决定是否应该拒绝请求。 You could configure a fixed throughtput not to exceed, or rely on some other JVM metric?您可以将固定吞吐量配置为不超过或依赖其他一些 JVM 指标吗?

Now I wouldn't call that "backpressure", at least not in the context of Spring.现在我不会称之为“背压”,至少不是在 Spring 的上下文中。 In reactive streams, backpressure roughly means that the consumer gives the producer information about the number of messages it can send.在响应式流中,背压大致意味着消费者向生产者提供有关它可以发送的消息数量的信息。 Per specification, the client cannot send more messages than the allowed number.根据规范,客户端不能发送超过允许数量的消息。

In the context of HTTP in Spring, we don't enforce backpressure when accepting new connections, but this information is being used when reading/writing to TCP buffers.在 Spring 的 HTTP 上下文中,我们在接受新连接时不强制执行背压,但在读取/写入 TCP 缓冲区时会使用此信息。 This information does not cross the network, so we're merely relying on TCP flow control here.此信息不跨网络,因此我们在这里仅依赖 TCP 流量控制。

If you want real backpressure support in the protocol, you need this to be supported in the protocol itself.如果您想在协议中提供真正的背压支持,您需要在协议本身中支持这一点。 This is what the future RSocket support in Spring is all about.这就是 Spring 中未来的 RSocket 支持的全部内容。

I faced the same challenge while implementing the Spotify API client.我在实现 Spotify API 客户端时遇到了同样的挑战。 I needed to have a dynamic backoff based on the error response.我需要根据错误响应进行动态退避。

This is how I did that:我就是这样做的:

webClient
    ... // you request
    .onStatus(status -> status.equals(HttpStatus.TOO_MANY_REQUESTS), this::exctractBackOffException) // e.g. build your exception with backoff response value
    .retryWhen(Retry.withThrowable(throwableFlux ->
                    throwableFlux.map(throwable ->
                    {
                        int backoff = // exctract from throwable
                        return Retry.backoff(2, Duration.ofSeconds(backoff));
                    })))
    ...

Instead of Retry.backoff() inside, you can build any Retry.您可以构建任何 Retry,而不是内部的Retry.backoff() The point is that you can build that dynamically knowing the value proposed by the server.关键是您可以在知道服务器建议的值的情况下动态构建它。

Hope this sample could be useful.希望这个样本有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM