RSocket + webflux 请求-响应弹性
RSocket + webflux request-response resilience
给定以下代码(使用 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
}
问题是:
当服务器负载很重时,客户端是否会直接将请求发送给服务器,服务器会缓冲该请求?还是实际上有某种机制让客户端等待,直到服务器向客户端发送信号?
如果客户端无论如何都要发送请求,那么在某些时候服务器将用完内存来缓冲所有多余的请求。我们通常是怎么处理的?可以netifi
经纪人在这种情况下有帮助吗? (假设是突发流量,我们无法及时横向扩展或纵向扩展服务器)
RSocket 的真正弹性
RSocket 作为一种网络协议,具有作为 first-class 公民的弹性。在 RSocket 中,Resilience 属性 以两种方式公开:
弹性通过 flow-control(a.k.a 背压)
如果您进行流式传输,您的订阅者可以控制传送的元素数量,因此您的订阅者不会被服务器淹没。下面的动画显示了 reactive-streams 规范如何在 RSocket 协议级别上实现:
可能会注意到,在 Reactive Streams 中,Subscriber
(左侧)request
s 数据通过其 Subscription
,此请求被转换为二进制帧,通过网络发送,一旦接收方收到该帧,它就会对其进行解码,然后传送到远程站点上的相应订阅,以便远程发布者可以生成准确数量的消息。
通过租赁获得弹性
另一方面,随着流式传输,通常管理多个连接的服务器必须承受负载,并且在出现故障的情况下,它应该能够阻止任何进一步的交互。为此,RSocket 带来了一个 built-in 协议特性,称为 Leasing
。简而言之,Leasing
是协议速率限制中的 built-in,其中请求限制是动态的并且完全由响应方控制。
在这个过程中有几个短语可以区分:
- 设置阶段 - 这个阶段发生在客户端连接到服务器时,双方都必须提供特定的标志同意双方准备尊重Leasing。
- 静默阶段 - 在那个阶段,请求者不能做任何事情。有一个严格的关系——请求不允许做任何事情,除非响应者允许这样做。 如果请求者尝试发送任何请求,此类请求将立即失败,不会向远程发送任何帧.
- 租赁供应阶段 - 一旦响应者同意其容量并准备好接收来自请求者的请求,它就会发送一个特定的帧称为
Lease
。该帧包含 2 个关键值:Number of Requests
和 Time to Live
。第一个值告诉请求者它可以发送给响应者的请求数。第二个值表示此类津贴的有效期。因此,如果请求者到那时还没有使用所有这些,则此类津贴将被视为无效,并且任何进一步的请求都将被拒绝。
此交互在以下动画中进行了描述:
备注
租约策略在 per connection
基础上运作,这意味着如果您签发租约,您是为单个特定的远程请求者签发租约,而不是为连接到您的服务器的所有请求者签发。另一方面,数学可以应用于在所有连接的请求者之间共享整个服务器容量取决于一些指标等。
在哪里可以找到两者的例子
有几个很好的示例演示了如何将 flow-control 和租赁与 RSocket 一起使用。所有这些都可以在 RSocket-Java 项目 here
的官方 git 仓库中找到
给定以下代码(使用 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
}
问题是:
当服务器负载很重时,客户端是否会直接将请求发送给服务器,服务器会缓冲该请求?还是实际上有某种机制让客户端等待,直到服务器向客户端发送信号?
如果客户端无论如何都要发送请求,那么在某些时候服务器将用完内存来缓冲所有多余的请求。我们通常是怎么处理的?可以netifi 经纪人在这种情况下有帮助吗? (假设是突发流量,我们无法及时横向扩展或纵向扩展服务器)
RSocket 的真正弹性
RSocket 作为一种网络协议,具有作为 first-class 公民的弹性。在 RSocket 中,Resilience 属性 以两种方式公开:
弹性通过 flow-control(a.k.a 背压)
如果您进行流式传输,您的订阅者可以控制传送的元素数量,因此您的订阅者不会被服务器淹没。下面的动画显示了 reactive-streams 规范如何在 RSocket 协议级别上实现:
可能会注意到,在 Reactive Streams 中,Subscriber
(左侧)request
s 数据通过其 Subscription
,此请求被转换为二进制帧,通过网络发送,一旦接收方收到该帧,它就会对其进行解码,然后传送到远程站点上的相应订阅,以便远程发布者可以生成准确数量的消息。
通过租赁获得弹性
另一方面,随着流式传输,通常管理多个连接的服务器必须承受负载,并且在出现故障的情况下,它应该能够阻止任何进一步的交互。为此,RSocket 带来了一个 built-in 协议特性,称为 Leasing
。简而言之,Leasing
是协议速率限制中的 built-in,其中请求限制是动态的并且完全由响应方控制。
在这个过程中有几个短语可以区分:
- 设置阶段 - 这个阶段发生在客户端连接到服务器时,双方都必须提供特定的标志同意双方准备尊重Leasing。
- 静默阶段 - 在那个阶段,请求者不能做任何事情。有一个严格的关系——请求不允许做任何事情,除非响应者允许这样做。 如果请求者尝试发送任何请求,此类请求将立即失败,不会向远程发送任何帧.
- 租赁供应阶段 - 一旦响应者同意其容量并准备好接收来自请求者的请求,它就会发送一个特定的帧称为
Lease
。该帧包含 2 个关键值:Number of Requests
和Time to Live
。第一个值告诉请求者它可以发送给响应者的请求数。第二个值表示此类津贴的有效期。因此,如果请求者到那时还没有使用所有这些,则此类津贴将被视为无效,并且任何进一步的请求都将被拒绝。
此交互在以下动画中进行了描述:
备注
租约策略在 per connection
基础上运作,这意味着如果您签发租约,您是为单个特定的远程请求者签发租约,而不是为连接到您的服务器的所有请求者签发。另一方面,数学可以应用于在所有连接的请求者之间共享整个服务器容量取决于一些指标等。
在哪里可以找到两者的例子
有几个很好的示例演示了如何将 flow-control 和租赁与 RSocket 一起使用。所有这些都可以在 RSocket-Java 项目 here
的官方 git 仓库中找到