“反应流”,每当我们遇到这些话,有两件事来到我们的脑海。第一个是异步流处理,第二个是非阻塞背压。在这个博客中,我们将了解后一部分。
了解背压
根据英文词典,背压意味着”阻力或力反对所需的流体流通过管道“。为了在我们的软件上下文中定义它,代替流体流,我们可以说数据流”阻力或力反对通过软件所需的数据流“
让我们看看背压在Akka流中扮演什么角色。
假设您构建了一个应用,并且它的工作方式正是你想要的,但当用户数量增加时,应用就会崩溃,因为它不是用来处理这些压力。我们不希望任何系统或应用程序如此。这是处理背压的需要。
此问题有许多解决方案,其中各种实现之一是 Akka 流。
流式处理应用程序方面的问题
将这两个人视为数据流的两个端点。一个是数据源,称为将发送数据的被动流中的发布服务器,另一个是负责接收和缓冲的数据源,称为被动流中的订阅服务器,他们将接收来自发布者的数据。这些术语用于定义反应流规范。在 Akka 流中,这些概念作为源(发布者)、流(称为反应流中的处理器)和接收器(订阅服务器)实现。
反应流背压工作模式可称为”动态推/拉模式”,因为它将在推和拉基背压模型之间切换,具体取决于下游能否应对上游生产速率。
要了解此问题的情况并查看背压如何处理它们,让我们看看这两种情况。
1. 快速发布者和慢速订阅者
在这里,我们可以看到发布者速度很快,每秒可以发送 100 个请求,而订阅者速度很慢,每秒可以处理 1 个请求。所有订阅者都有某种缓冲区,可以存储等待的请求。现在的问题是,当缓冲区溢出时会发生什么?
解决方案:基于拉的背压
因此,在基于拉的背压中,我们有一个速度较慢的订户,它有一个已知的缓冲区空间,也就是说我们有一个边界缓冲区。在这里,我们与发布者通信,通知他们订阅服务器在其缓冲区中有多少可用空间来容纳传入数据,而发布者可以发送我们允许发送的元素数量。
如上图所示,我们可以看到慢速订阅者如何要求仅发送 3 个元素,因为剩余空间量仅针对 3 个元素,然后 Publisher 仅向订阅服务器发送其中 3 个元素因此,想象一下,当这3个元素将飞过到订户,在此期间,存在于订阅者缓冲区的元素将得到处理。因此,现在订阅者可以异步请求更多元素。
我们可以看到,此方案有效地意味着订阅服务器将从发布服务器中提取元素,因此此操作模式称为基于拉的背压。
2. 慢速发布者和快速订阅者
此方案不是大问题,因为您不需要减慢发布服务器的速度。发布服务器和订阅服务器的信号速率很少是恒定的,并且可能随时更改为快速发布服务器和慢速订阅服务器。因此,为了防止这种情况,必须在此类情况下启用背压协议。
该协议的工作方式与基于拉的背压中讨论的方式相同。发布服务器永远不会发送比订阅服务器所需的请求更多的元素。但是,由于在这种情况下,订阅服务器更快,它将以更高的速率请求元素。这意味着发布者不必等待发布传入请求。
我们可以看到,在这种情况下,我们有效地在所谓的推送模式下运行。由于 Publisher 可以继续以尽可能快的速度生成元素,因此在发出元素时,挂起的需求将及时恢复。使用基于推送的流,生产者处于控制之下,并在数据可用时将数据推送给使用者。在处理用户输入时,我们大多更喜欢推送流,因为它们对生产者进行精确建模,因为您无法控制用户。
结论
Akka 流库的用户不必编写任何显式背压处理代码。该协议是内置的,由所有提供的 Akka Streams 运算符自动处理。但是,可以添加具有溢出策略的显式缓冲区运算符,以影响流的行为。