【问题标题】:RSocket + webflux request-response resilienceRSocket + webflux 请求-响应弹性
【发布时间】:2020-09-27 07:52:31
【问题描述】:

给定以下代码(使用 Spring Webflux 和 RSocket):

@MessageMapping("hello.{name}")
public Mono<String> greet(@DestinationVariable String name) {
    return Mono.just("Hello " + name); // or assume this is making a slow http call
}

问题是:

  1. 当服务器负载过重时,客户端是否会向服务器发送请求,服务器会缓冲该请求?或者实际上是否有某种机制让客户端等到服务器向客户端发送信号?

  2. 如果客户端仍然发送请求,那么在某些时候服务器将内存不足来缓冲所有多余的请求。我们一般是怎么处理的?可以上网吗 经纪人在这种情况下有帮助吗? (假设是突发流量,我们无法及时横向扩展或纵向扩展服务器)

【问题讨论】:

    标签: spring-webflux project-reactor reactive rsocket netifi


    【解决方案1】:

    RSocket 的真正弹性

    RSocket 作为一种网络协议,具有一等公民的弹性。在 RSocket 中,Resilience 属性以两种方式公开:

    通过流量控制(也称为背压)实现弹性

    如果您进行流式传输,您的订阅者可以控制传递的元素数量,因此您的订阅者不会被服务器淹没。下面的动画展示了响应流规范是如何在 RSocket 协议级别实现的:

    可能会注意到,在 Reactive Streams 中,Subscriber(左侧)requests 数据通过其Subscription,此请求被转换为二进制帧,通过网络发送,并且一次接收者接收到该帧,对其进行解码,然后将其传递给远程站点上的相应订阅,以便远程发布者可以生成确切数量的消息。

    通过租赁恢复弹性

    另一方面,与流媒体一起,通常管理多个连接的服务器必须面对负载,并且在发生故障时,它应该能够阻止任何进一步的交互。为此,RSocket 带来了一个内置的协议特性,称为Leasing。简而言之,Leasing 是协议 Rate Limiting 的内置内容,其中请求限制是动态的,并且完全由 Responder 方控制。

    在该过程中可能会区分一些短语:

    1. 设置阶段 - 此阶段发生在客户端连接到服务器时,双方必须提供特定标志以同意双方都准备好遵守租赁。
    2. 静默阶段 - 在那个阶段,请求者不能做任何事情。存在严格的关系——请求不允许做任何事情,除非响应者允许这样做。 如果请求者尝试发送任何请求,此类请求将立即失败,不会向远程发送任何帧
    3. 租约配置阶段 - 一旦响应者同意其容量并准备好接收来自请求者的请求,它就会发送一个名为 Lease 的特定帧。该框架包含 2 个关键值:Number of RequestsTime to Live。第一个值告诉请求者它可以发送给响应者的请求数。第二个值表示这种津贴的有效期。因此,如果请求者到那时还没有使用所有这些,则该配额将被视为无效,并且请求者 sied 将拒绝任何进一步的请求。

    下面的动画描述了这种交互:

    注意

    租约策略在per connection 基础上运作,这意味着如果您发出租约,您会为单个特定的远程请求者发出它,而不是为连接到您服务器的所有请求者发出它。另一方面,可以应用数学来在所有连接的请求者之间共享整个服务器容量,这取决于一些指标等。

    在哪里可以找到两者的示例

    有几个很好的示例演示了如何将流控制和租赁与 RSocket 一起使用。所有这些都可以在RSocket-Java项目here的官方git repo中找到

    【讨论】:

    • 对于租赁(请求数量和离开时间),是否在应用层手动配置?租约是否为所有请求者共享?
    • 租用策略可以在两边分别配置(在Client和Server上,因为Protocol是Peer to Peer,所以Responder逻辑可以在这里和那里实现)。对于服务器,租用策略是按连接创建的,因此发送租约的机制是按连接。也就是说,如果您为连接 A 提供了 100 个允许发送的请求,而您总共只有 150 个,那么您可以进行数学运算,例如仅向其他人发出 50 或 25 个
    • 顺便说一句,我认为计算租赁中的请求数量非常困难。再加上生存时间,情况就更加复杂了。你认为计算每个请求的基础是一个好习惯吗(我们也可以这样做,也许是 0 TTL)?是否会因为我们需要为每个请求执行所有租赁阶段而显着减慢通信速度?
    • 这可以通过使用 Netflix 并发限制库轻松完成。我们正在进行一个 PR,它改变了一些内部结构并添加了一些示例来展示当有多个连接时如何计算租约github.com/rsocket/rsocket-java/pull/885
    • 另外,我们正在处理新的租约变更,但还没有 -> github.com/rsocket/rsocket/pull/311
    猜你喜欢
    • 2020-06-09
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 2019-05-20
    • 2017-12-27
    相关资源
    最近更新 更多