实战SpringCloud响应式微服务系列教程(第二章)
接上一篇:实战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>
、Subscription
、Subscriber<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>
、Subscription
、Subscriber<T>
三者的交互如下:
4、Processor<T,R>
处理器(Processor)充当订阅者和发布者之间的处理媒介,Processor
接口继承了Publisher
和Subscribe
接口,它用于转换发布者/订阅者管道中的元素。
Processor<T,R>
订阅类型T的数据元素,接收并转换为R的数据,然后发布该数据。处理器在发布者/订阅者管道中充当转换器的角色。接口定义如下:
public interface Processor<T,R> extends Subscriber<T>,Publisher<R>{ }
Processor
集Subscriber
和Publisher
于一身,三者之间的关系如下所示:
这四个接口是实现各个响应式开发库之间互相兼容的桥梁,响应式流规范也仅仅聚焦于此,而对于转换、合并、分组等操作并未做要求。也是一个非常抽象且精简的接口规范。
实战SpringCloud响应式微服务系列教程(第二章)的更多相关文章
- 实战SpringCloud响应式微服务系列教程(第九章)使用Spring WebFlux构建响应式RESTful服务
本文为实战SpringCloud响应式微服务系列教程第九章,讲解使用Spring WebFlux构建响应式RESTful服务.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 从本节开始我们 ...
- 实战SpringCloud响应式微服务系列教程(第三章)
接着之前的: 实战SpringCloud响应式微服务系列教程(第一章) 实战SpringCloud响应式微服务系列教程(第二章) 1.1.3Reactor框架 响应式编程是一种编程模型,本节将介绍这种 ...
- 实战SpringCloud响应式微服务系列教程(第四章)
接上一篇: 实战SpringCloud响应式微服务系列教程(第一章) 实战SpringCloud响应式微服务系列教程(第二章) 实战SpringCloud响应式微服务系列教程(第三章) 1.1.4 引 ...
- 实战SpringCloud响应式微服务系列教程(第六章)
本章节介绍:Flux和Mono操作符 和其他主流的响应式编程一样,Reactor框架的设计目标也是为了简化相应式流的使用方法.为此Reactor框架提供了大量操作符用于操作Flux和Mono对象. 本 ...
- 实战SpringCloud响应式微服务系列教程(第七章)
本章节继续介绍:Flux和Mono操作符(二) 1.条件操作符 Reactor中常用的条件操作符有defaultIfRmpty.skipUntil.skipWhile.takeUntil和takeWh ...
- 实战SpringCloud响应式微服务系列教程(第八章)构建响应式RESTful服务
本文为实战SpringCloud响应式微服务系列教程第八章,讲解构建响应式RESTful服务.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 1.使用springboot2.1.4构建RE ...
- 实战SpringCloud响应式微服务系列教程(第十章)响应式RESTful服务完整代码示例
本文为实战SpringCloud响应式微服务系列教程第十章,本章给出响应式RESTful服务完整代码示例.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 1.搭建响应式RESTful服务. ...
- 实战SpringCloud响应式微服务系列教程(第一章)
前言 在当今互联网飞速发展的时代,业务需求不断的更新和产品的迭代给系统开发过程和编程模式也带来巨大挑战,Spring Cloud微服务也随之应用而生,从springboot1.x到springboot ...
- Cobalt Strike系列教程第二章:Beacon详解
上周更新了Cobalt Strike系列教程第一章:简介与安装,文章发布后,深受大家的喜爱,遂将该系列教程的其他章节与大家分享,提升更多实用技能! 第二章:Beacon详解 一.Beacon命令 大家 ...
随机推荐
- Laravel --- 部署Laravel项目到vps主要步骤以及遇到的问题记录
买了一个国外的vps,然后搭建环境并且跑了下laravel,折腾了一天半左右,遇到的问题和操作在此记录下: 1.我把本地的代码用git方式上传到github,然后在vps用git下载代码,步骤如下 - ...
- uint16,uint32是什么?
记得之前在刷笔试题的时候就看见过这个问题,发现当时上网百度后又忘了. 最近在看CryEngine3引擎代码的时候又晕了,趁现在赶紧记下来~ 在查看CE3的代码时我发现了这个变量,TFlowNodeId ...
- sentinel 集群流控原理
为什么需要集群流控呢?假设需要将某个API的总qps限制在100,机器数可能为50,这时很自然的想到使用一个专门的server来统计总的调用量,其他实例与该server通信来判断是否可以调用,这就是基 ...
- Linux下docker的安装
前言: 因为之前在自己的mac上直接使用HomeBrew的包管理安装的,使用brew install docker即可,这种方法简单,但最近想尝试在Linux下安装,费了一些时间,主要是启动docke ...
- 【转载】一起来学Spring Cloud | Eureka Client注册到Eureka Server的秘密
LZ看到这篇文章感觉写得比较详细,理解以后,便转载到自己博客中,留作以后回顾学习用,喝水不忘挖井人,内容来自于李刚的博客:http://www.spring4all.com/article/180 一 ...
- <h2>js数组操作大全(pop,push,unshift,splice,shift方法)</h2>
---恢复内容开始--- shift:删除原数组第一项,并返回删除元素的值:如果数组为空则返回undefined var a = [1,2,3,4,5]; var b = a.shift(); //a ...
- 设计模式-观察者模式(Observer)
观察者模式是行为模式的一种,它的作用是当一个对象的状态发生变化时,能够自动通知关联对象,自动刷新对象状态. 观察者模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步. ...
- spring boot freemarker 导出word 带echarts图形报表
创建word文件内容如下 将word导出为xml格式 将文件后缀名改为 .ftl 在springboot项目中添加freemarker依赖 <!-- 导出word文档--> <dep ...
- ASP.NET、.NET和C#的关系是怎样的?
1..NET是什么?.Net全称.NET Framework是一个开发和运行环境,该战略是微软的一项全新创意,它将使得“互联网行业进入一个更先进的阶段”,.NET不是一种编程语言. 简单说就是一组类库 ...
- WeUI Picker组件 源代码分析
前言 由于最近做的一个移动端项目需要使用到类似 WeUI Picker组件 的选择效果, 所以在这里来分析下 WeUI Picker 的实现逻辑.(weui.js项目地址) 之前也做过类似的组件, ...