接上一篇:实战SpringCloud响应式微服务系列教程(第一章)

1.1.2背压

背压是响应式编程的核心概念,这一节也是我们了解响应式编程的重点。

1.背压的机制

在生产者/消费者模型中,我们意识到消费者在消费由生产者生产的数据的同时,也需要有一种能够向上游反馈流量需求的机制,这种能够向上游反馈请求的机制称之为背压。

如下图所示

现在我们从一个具体的角度来说背压的概念。在1.1.1中我们了解了同步消费和异步消费,其中异步消费者会向生产者订阅消费数据,当有新的数据可用时,消费者会通过之前订阅时提供的回调函数激活调用过程。

如果生产者发出的数据比消费者能够处理的数据量大而且快时,消费者可能会被迫一直再获取或处理数据,消耗越来越多的资源,从而埋下潜在的风险。为了防止这一点,需要有一种机制,消费者可以通知生产者降低生产数据的速度。生产者可以通过多种方式来实现这一要求,这时候我们就会用到背压机制。

采用背压机制后,消费者告诉生产者降低生产数据速度并保存元素,知道消费者能够处理更多的元素。使用背压可以有效地避免过快的生产者压制消费者。如果生产者要一直生产和保存元素,使用背压也可能会要求其拥有无限制的缓冲区。生产者也可以实现有界缓冲区来保存有限数量的元素,如果缓冲区已满可以选择放弃。

2.背压的实现方式

背压的实现方式有两种,一种是阻塞式背压另一种是非阻塞式背压。

1、阻塞式背压

阻塞式背压是比较容易实现的,例如:当生产者和消费者在同一个线程中运行时,其中任何一方都将阻塞其他线程的执行。这就意味着,当消费者被执行时,生产者就不能发出任何新的数据元素。因而也需要一中自然地方式来平衡生产数据和消费数据的过程。

在有些情况下,阻塞式背压会出现不良的问题,比如:当生产者有多个消费者时,不是所有消费者都能以同样的速度消费消息。当消费者和生产者在不同环境中运行时,这就达不到降压的目的了。

2、非阻塞式背压

背压机制应该以非阻塞式的方式工作,实现非阻塞式背压的方法是放弃推策略,采用拉策略。生产者发送消息给消费者等操作都可以保存在拉策略当中,消费者会要求生产者生成多少消息量,而且最多只能发送这些量,然后等到更多消息的请求。(关于推策略和拉策略请回顾1.1.1中的流的概念

1.1.3 响应式流

响应式编程的另外一个核心概念就是响应式流。响应式流是一种规范,这种规范表现在技术上就是一批被预先定义好的接口。

1.响应式流规范

响应式流规范是提供非阻塞背压的异步流处理标准倡议的。响应式流的目标是定义将数据流从生产者传递到消费者而不需要生产者阻塞。在响应式流模型中,消费者向生产者发送多个元素的异步请求,然后生产者向消费者发送合适数量的数据。

各个响应式开发库都要遵循响应式流规范,采用规范的好处是显而易见的。由于各个响应式都遵循一套规范,因而互相兼容,不同的开发库之间也是可以进行交流的。甚至可以在同一个项目中使用多个开发库。而Spring WebFlux响应式web是采用Reactor框架来实现的。(其他开发库可百度了解这里我们只探讨reactor)。

虽然响应式流规范用来约束响应式开发库的实现方式的,但是作为使用者而言,能够了解这一规范,对我们了解使用开发库的方法和基本原理很有帮助,因为规范内容都是对响应式编程思想的精髓呈现。

2.响应式流接口

Java API响应式流有4个接口,即Publisher<T>SubscriptionSubscriber<T>Processor<T,R>

1、Publisher<T>

发布者(Publisher)是潜在的包含无限数量的有序元素的生产者,他根据收到的请求向当前订阅者发送元素。接口定义如下:

public interface Publisher<T>{
public void subscribe (Subscriber<? super T> s);
}

2、Subscriber<T>

订阅者从发布这那里订阅并且接收元素。发布者想订阅者发送订阅令牌。使用订阅令牌,订阅者向发布者请求多个元素。当元素准备就绪时,发布者就会向订阅者发送合适数量的元素。然后订阅者可以请求更多的元素,发布者也可能有多个来自订阅者的待处理请求。接口定义如下:

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

当执行发布者的subscribe()方法时,发布者会回调订阅者的onSubscribe()方法。在这个方法中订阅者通常会借助传入的Subscription 对象向发布者请求n个数据。然后发布者通过不断调用onNext()方法想订阅者发出最多n个数据。如果数据全部发送完毕,就会调用onComplete()方法告知订阅者所需要的n个数据已经发送完毕。如果有错误发生就会通过调用onError()方法发出错误数据,这同样也会终止数据流。

3、Subscription

订阅(Subscription )表示订阅者订阅的一个发布者的令牌,当订阅请求成功时,发布者将其传递给订阅者,订阅者使用订阅令牌与发布者进行交互,比如:请求更多的元素或取消订阅。接口定义如下:

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

当发布者调用subscribe()方法注册订阅者时,会通过订阅者的回调方法onSubscribe()传入Subscription对象,之后订阅者就可以使用Subscription对象的request()方法向发布者请求数据了。

Publisher<T>SubscriptionSubscriber<T>三者的交互如下:

4、Processor<T,R>

处理器(Processor)充当订阅者和发布者之间的处理媒介,Processor接口继承了PublisherSubscribe接口,它用于转换发布者/订阅者管道中的元素。

Processor<T,R>订阅类型T的数据元素,接收并转换为R的数据,然后发布该数据。处理器在发布者/订阅者管道中充当转换器的角色。接口定义如下:

public interface Processor<T,R> extends Subscriber<T>,Publisher<R>{

}

ProcessorSubscriberPublisher于一身,三者之间的关系如下所示:

这四个接口是实现各个响应式开发库之间互相兼容的桥梁,响应式流规范也仅仅聚焦于此,而对于转换、合并、分组等操作并未做要求。也是一个非常抽象且精简的接口规范。

实战SpringCloud响应式微服务系列教程(第二章)的更多相关文章

  1. 实战SpringCloud响应式微服务系列教程(第九章)使用Spring WebFlux构建响应式RESTful服务

    本文为实战SpringCloud响应式微服务系列教程第九章,讲解使用Spring WebFlux构建响应式RESTful服务.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 从本节开始我们 ...

  2. 实战SpringCloud响应式微服务系列教程(第三章)

    接着之前的: 实战SpringCloud响应式微服务系列教程(第一章) 实战SpringCloud响应式微服务系列教程(第二章) 1.1.3Reactor框架 响应式编程是一种编程模型,本节将介绍这种 ...

  3. 实战SpringCloud响应式微服务系列教程(第四章)

    接上一篇: 实战SpringCloud响应式微服务系列教程(第一章) 实战SpringCloud响应式微服务系列教程(第二章) 实战SpringCloud响应式微服务系列教程(第三章) 1.1.4 引 ...

  4. 实战SpringCloud响应式微服务系列教程(第六章)

    本章节介绍:Flux和Mono操作符 和其他主流的响应式编程一样,Reactor框架的设计目标也是为了简化相应式流的使用方法.为此Reactor框架提供了大量操作符用于操作Flux和Mono对象. 本 ...

  5. 实战SpringCloud响应式微服务系列教程(第七章)

    本章节继续介绍:Flux和Mono操作符(二) 1.条件操作符 Reactor中常用的条件操作符有defaultIfRmpty.skipUntil.skipWhile.takeUntil和takeWh ...

  6. 实战SpringCloud响应式微服务系列教程(第八章)构建响应式RESTful服务

    本文为实战SpringCloud响应式微服务系列教程第八章,讲解构建响应式RESTful服务.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 1.使用springboot2.1.4构建RE ...

  7. 实战SpringCloud响应式微服务系列教程(第十章)响应式RESTful服务完整代码示例

    本文为实战SpringCloud响应式微服务系列教程第十章,本章给出响应式RESTful服务完整代码示例.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 1.搭建响应式RESTful服务. ...

  8. 实战SpringCloud响应式微服务系列教程(第一章)

    前言 在当今互联网飞速发展的时代,业务需求不断的更新和产品的迭代给系统开发过程和编程模式也带来巨大挑战,Spring Cloud微服务也随之应用而生,从springboot1.x到springboot ...

  9. Cobalt Strike系列教程第二章:Beacon详解

    上周更新了Cobalt Strike系列教程第一章:简介与安装,文章发布后,深受大家的喜爱,遂将该系列教程的其他章节与大家分享,提升更多实用技能! 第二章:Beacon详解 一.Beacon命令 大家 ...

随机推荐

  1. spring 5.x 系列第8篇 —— 整合Redis客户端 Jedis和Redisson (代码配置方式)

    文章目录 一.说明 1.1 Redis 客户端说明 1.2 Redis可视化软件 1.3 项目结构说明 1.3 依赖说明 二.spring 整合 jedis 2.1 新建基本配置文件和其映射类 2.2 ...

  2. idea创建类报错

    创建类报错: 在idea.exe.vmoptions 或 idea64.exe.vmoptions中加入配置 -Djdk.util.zip.ensureTrailingSlash=false jar包 ...

  3. 每天学点node系列-stream

    在编写代码时,我们应该有一些方法将程序像连接水管一样连接起来 -- 当我们需要获取一些数据时,可以去通过"拧"其他的部分来达到目的.这也应该是IO应有的方式. -- Doug Mc ...

  4. 抽丝剥茧分析asyncio事件调度的核心原理

    先来看一下一个简单的例子 例1: async def foo(): print('enter foo ...') await bar() print('exit foo ...') async def ...

  5. BFS(三):双向广度优先搜索

    所谓双向广度搜索指的是搜索沿两个方向同时进行:(1)正向搜索:从初始结点向目标结点方向搜索:(2)逆向搜索:从目标结点向初始结点方向搜索:当两个方向的搜索生成同一子结点时终止此搜索过程. 广度双向搜索 ...

  6. BZOJ 2957:楼房重建(分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2957 题意:…… 思路:对于每一个块,维护一个单调递增的斜率(因为小于前面的斜率的话是肯定看不见的) ...

  7. POI 设置Excel单元格背景色(setFillForegroundColor)

    背景介绍:使用Java开发信息系统项目,项目中往往会涉及到报表管理部分,而Excel表格首当其冲称为最合适的选择,但是对单元格操作时对于设置单元格的背景颜色却很少提及,本文旨在方便单元格背景颜色设计. ...

  8. svn unable to connect to a repository url 计算机积极拒绝

    网上应该说启动server服务,首先找不到这个服务,后来下载个软件有了,启动还是不行.clear了所有saved data之后也是不行. 解决方法:Network中 Enable proxy Serv ...

  9. Innovus Lab和Lab Guide下载地址 | Innovus教程 - Flow系列 - 数据准备

    本文转自:自己的微信公众号<集成电路设计及EDA教程> <Innovus Lab和Lab Guide下载地址 |    Innovus教程 - Flow系列 - 数据准备>   ...

  10. js random获取随机数,获取任意范围内随机整数

     壹 ❀ 引 想着好久没做笔试题了,去GitHub找了面试相关的项目,结果被第一道题难住了.....说难其实也不难,而是我忘记了取范围随机整数怎么写了,不可否认如果当时是我在笔试,肯定也凉了,那么就由 ...