想让系统更具有弹性?了解背压机制和响应式流的秘密!

简介: 想让系统更具有弹性?了解背压机制和响应式流的秘密!

分析传统开发模式和响应式编程实现方法之间的差别引出了数据流的概念

1 引言

从“流”的概念出发,并引入响应式流程规范,从而分析响应式编程中所包含的各个核心组件。

2 流的概念

由生产者生产,并由一或多个消费者消费的元素序列。这种生产者/消费者模型也称发布/订阅模型。


Reactive Streams 是 2013 年底由 Netflix、Lightbend 和 Pivotal 的工程师发起的一项计划,旨在为无阻塞异步流处理提供一个标准。解决处理元素流的问题——如何将元素流从发布者传递到订阅者,而不需要发布者阻塞,或订阅者有无限制的缓冲区或丢弃。

3 流的处理模型

拉模式

消费者主动从生产者拉取元素。

推模式

生产者将元素推送给消费者

4 流量控制

4.1 v(生产者生产数据) < v(消费者消费数据)

消费者消费数据没有任何压力,也就不需要进行流量的控制。

4.2 v(生产者生产数据) > v(消费者消费数据)

消费者可能因为无法处理过多的数据而发生崩溃。

一般就是在生产者与消费者之间加一个队列做缓冲。我们知道队列具有存储与转发的功能,所以可以用它来进行一定的流量控制。

5 队列选型

无界队列

  • 优势:确保消费者消费到所有的数据
  • 劣势:系统的回弹性降低,任何一个系统不可能拥有无限的资源,一旦内存等资源耗尽,系统就可能会有崩溃的风险。

有界丢弃队列

有界丢弃队列考虑了资源的限制,适用于允许丢消息的业务场景。但消息重要性很高的场景显然不可能采取这种队列。

有界阻塞队列

6 背压(Backpressure)机制

纯“推”模式下的数据流量会有很多不可控制的因素,需要在“推”模式和“拉”模式之间考虑一定的平衡性,从而优雅地实现流量控制

下游能够向上游反馈流量请求的机制。

如果消费者消费数据的速度赶不上生产者生产数据的速度,它就会持续消耗系统的资源。使得消费者可以根据自身当前的处理能力通知生产者来调整生产数据的速度,这就是背压。

7 响应式流规范

针对流量控制的解决方案以及背压机制都包含在响应式流规范中,其中包含了响应式编程的各个核心组件。

8 响应式流的核心接口

8.1 Publisher

一种可以生产无限数据的发布者。

public interface Publisher<T> {
    /**
     * 请求 Publisher 开始流式传输数据。
     * 这是一个“工厂方法”,可以多次调用,每次开始一个新的 Subscription.
     * 每个 Subscription 只能为一个 Subscriber.
     * A Subscriber 只能订阅一次 Publisher
     * 如果 拒绝 Publisher 订阅尝试或失败,它将通过 发出 Subscriber.onError(Throwable)错误信号
     */
    public void subscribe(Subscriber<? super T> s);
}

Publisher 里的 subscribe 方法传入 Subscriber 接口,这里用的是回调,Publisher 根据收到的请求向当前订阅者 Subscriber 发送元素。


,发出信号的元素类型。

8.2 Subscriber

可以从发布者那里订阅并接收元素的订阅者。

public interface Subscriber<T> {
    public void onSubscribe(Subscription s);
    public void onNext(T t);
    public void onError(Throwable t);
    public void onComplete();
}

Subscriber 接口定义的这组方法构成了数据流请求和处理的基本流程,其中,onSubscribe() 从命名上看就是一个回调方法,当发布者的 subscribe() 方法被调用时就会触发这个回调。而在该方法中有一个参数 Subscription,可以把这个 Subscription 看作是一种用于订阅的上下文对象。Subscription 对象中包含了这次回调中订阅者想要向发布者请求的数据个数。


当订阅关系已经建立,那么发布者就可以调用订阅者的 onNext() 方法向订阅者发送一个数据。这个过程是持续不断的,直到所发送的数据已经达到 Subscription 对象中所请求的数据个数。这时候 onComplete() 方法就会被触发,代表这个数据流已经全部发送结束。而一旦在这个过程中出现了异常,那么就会触发 onError() 方法,我们可以通过这个方法捕获到具体的异常信息进行处理,而数据流也就自动终止了。

8.3 Subscription

确保生产者、消费者针对数据处理速度达成一种动态平衡的基础,流量控制中实现背压的关键。

public interface Subscription {
    public void request(long n);
    public void cancel();
}

响应式流规范非常灵活,还可提供独立的“推”模型和“拉”模型。

响应式流是一种规范,而该规范的核心价值,就在于为业界提供了一种非阻塞式背压的异步流处理标准。

业界主流响应式开发库包括:

  • RxJava
  • Akka
  • Vert.X
  • Project Reactor

总结

本文分析了数据流的概念的分类以及“推”流模式下的流量控制问题,从而引出了响应式系统中的背压机制。

响应式流规范是对响应式编程思想精髓的呈现

对于开发人员而言,理解这一规范有助于更好的掌握开发库的使用方法和基本原理。

FAQ

简要描述响应式流规范中数据的生产者和消费者之间的交互关系。


响应式流规范中,数据的生产者和消费者之间的交互关系是基于观察者模式实现的。生产者通过创建一个可观察的数据流并向消费者提供订阅方法,消费者可以通过订阅这个数据流来获取数据。一旦生产者有新的数据产生,它会将数据发送给所有已订阅该数据流的消费者。消费者可以通过取消订阅方法来停止接收数据。这种交互关系使得生产者和消费者之间解耦,同时也允许消费者按需获取数据,从而实现了高效的异步编程。


目录
相关文章
|
4月前
|
前端开发 JavaScript API
解锁高效应用构建:Vuex与后端交互的前端状态同步策略,让数据流动如行云流水,紧跟前端开发的热点趋势
【8月更文挑战第27天】本文深入探讨了Vue框架下的前端状态管理库Vuex与后端服务交互时的状态同步策略。通过剖析Vuex的核心机制——状态(State)、变异(Mutation)、动作(Action)及模块(Module),文章展示了如何优雅地将后端数据加载并更新至前端状态中。特别地,借助示例代码解释了Action处理API调用、Mutation更新状态的过程,并介绍了如何通过模块化和命名空间提高状态管理的准确性和时效性。此外,还讨论了组件如何利用`mapState`和`mapActions`简化状态访问与操作的方法。遵循这些策略,开发者可以在构建复杂应用时显著提升性能与用户体验。
47 0
|
5月前
|
编译器 调度 C++
协程问题之机制保障中提到的早值班机制和稳定性周会机制分别是什么
协程问题之机制保障中提到的早值班机制和稳定性周会机制分别是什么
|
4月前
|
消息中间件 存储 负载均衡
现代消息队列与云存储问题之进一步减少流处理中的读写操作的问题如何解决
现代消息队列与云存储问题之进一步减少流处理中的读写操作的问题如何解决
|
3月前
|
边缘计算 缓存 自动驾驶
5G如何实现更高的数据速率?涉及哪些技术?
5G如何实现更高的数据速率?涉及哪些技术?
104 0
|
4月前
|
算法 数据处理 流计算
流计算引擎数据问题之传播模块工作如何解决
流计算引擎数据问题之传播模块工作如何解决
42 1
|
7月前
|
网络协议 算法 开发者
如何实现网络同步?
【5月更文挑战第3天】如何实现网络同步?
133 9
|
7月前
|
监控 安全 持续交付
【专栏】Webhook是服务器主动发送事件通知的机制,打破传统客户端轮询模式,实现数据实时高效传递。
【4月更文挑战第29天】Webhook是服务器主动发送事件通知的机制,打破传统客户端轮询模式,实现数据实时高效传递。常用于持续集成部署、第三方服务集成、实时数据同步和监控告警。具有实时性、高效性和灵活性优势,但也面临安全风险和调试挑战。理解并善用Webhook能提升系统性能,广泛应用于现代软件开发和集成。
436 0
|
7月前
|
消息中间件 存储 监控
【ZeroMQ的SUB视角】深入探讨订阅者模式、C++编程实践与底层机制
【ZeroMQ的SUB视角】深入探讨订阅者模式、C++编程实践与底层机制
808 1
|
7月前
|
网络协议 程序员 网络安全
掌握 SOME/IP :事件通知 构建高效通信系统的关键技术
掌握 SOME/IP :事件通知 构建高效通信系统的关键技术
377 0
|
存储 Java 数据处理
响应式流的核心机制——背压机制
响应式流的核心机制——背压机制
191 0