本文为《Spring 响应式编程》的读书笔记,响应式技术栈可以创建极其高效、易于获取且具有回弹性的端点,同时响应式可以容忍网络延迟,并以影响较小的方式处理故障。响应式微服务还可以隔离慢速事务并加速速度最快的事务。通过本书可以学到以下内容:

Spring 响应式编程-读书笔记_响应式编程

响应式编程基本原则和响应式流(Reactive Stream)规范;

使用 Spring 5 集成的 Project Reactor 响应式开发框架;

使用 Spring Webflux 构建响应式 RESTful 服务;

使用 Spring Data Reactive 构建响应式数据访问组件;

使用 Spring Cloud Stream Reactive 构建响应式消息通讯组件。

第一章 响应式Spring

首先了解一下响应式编程相关的名词:


弹性:可以横向扩展;

回弹:故障隔离,做到独立性;

消息驱动:不应该是阻塞的,即时响应。

响应式中,较为关键的是背压:主要用来支持回弹性,实现处理阶段之间工作负载管理的复杂机制,可以确保一个处理阶段不会压垮另一个。


在JVM领域,构建响应式系统最知名的两个框架:Akka 、Vert.x。而在在传统 Java 中,实现响应式的方式:


回调函数,但会带来回调地狱问题;

JDK 8 CompletionStage.

Spring 4为了兼容旧 JDK 没有支持CompletionStage,在Spring 5中才支持该方法。同时,Servlet 3.0 引入了异步客户端-服务器通讯,3.1 支持I/O 非阻塞写入。但是Spring MVC 没有提供一个开箱即用的异步非阻塞客户端。为了陈旧包袱,彻底丧失响应式支持。也导致了 Spring为响应式单独开了一份技术栈。


第二章 Spring响应式编程基本概念

发布订阅模式,它可以被视为观察者模式的变体。在基于RxJava的实现中,但没有人监听时,温度传感器不会探测温度数据。这种行为是响应式编程具有主动订阅概念这一事实的自然结果。基于发布-主题的实现没有这样的属性,因此存在更多限制。



RxJava库是 Reactive Extensions(响应式扩展,也称为 ReactiveX)的Java虚拟机实现。Reactive Extensions 是一组工具,能用命令式语言处理数据流,无论该流是同步的还是异步的。ReactiveX通常被定义为观察者模式、迭代器模式和函数式编程的组合。


RXJava通过订阅者订阅可观察流,该流又反过来触发事件生成的异步过程。采用这种方法对可变对象有害,唯一合理的策略是采用不变性。不变性即函数式编程(functional programming)的核心原则之一。对象一旦被创建,就不会被更改。这样一条简单的规则可以防止在并行系统中可能出现的问题。


如果没有函数式编程,人们就必须创建许多匿名类或者内部类,这些类会污染应用程序。并且他们创建的样板代码多于有效代码。正由于它的不可变性,非常适合应用于并发编程。


历史

异步编程的历史最早追溯05年微软做的:大规模异步数据密集型互联网服务架构的编程模型。09年开源了Rx.NET,后来Netflix正面临大量互联网流量这一复杂难题,就开源了RxJava。并基于它开发了诸如:Hystrix、Ribbon、Zuul、RxNetty知名的库。但其实在响应式编程方向完全落实并成功做出巨大贡献的是:Node.js。


RxJava也并不是Java中唯一的解决方案,Vert.x也可以实现类似功能。Vert.x是一个事件驱动的开发框架,在设计上类似Node.js。它为异步编程提供了一个简单的并发模型和原始语义。


随着RxJava的成功,许多公司和开源项目都开始了激烈的竞争。由于各个库的行为总体上非常相似,但在实现中又略有不同。所以如果共用一些响应式库,可能会出现隐藏的bug。为了解决这些兼容性问题,出现了一个标准:响应式流(Reactive Streams)。


第三章 响应式流-新的标准

使用多个响应式库需要自己去编写适配器进行兼容,Spring 4的ListenableFuture和CompletionStage之间并没有直接的集成,而在Spring 5中才扩展了ListenableFuture的API名为Comple-table的方法来解决不兼容问题。核心问题在于没有一种方法能够使库提供商提供对齐的API,Vert.x、Ratpack和Retrofit都比较重视RxJava,并提供了支持。


在整个响应式环境演变的早期阶段,所有库的设计思想都是把数据从源头推送到订阅者。采用推模型的主要原因是它可以通过将请求量减少到最小值来优化整体处理时间。




这也就是为什么RxJava1.x及类似的开发库以推送数据为目的进行设计,这也是为什么流技术能称为分布式系统中组件之间重要的通讯技术。但如果生产者不关注消费者的吞吐能力,则会存在一下可能:


慢生产者和快消费者

快生产者和慢消费者

针对这种情况的解决方案是将未处理的元素收集到队列中。


无界队列:无限大小的队列;

有界丢弃队列:为避免内存溢出;

有界阻塞队列:支付订单阻塞;

通常,纯推模型中不受控制的语义可能导致许多我们不希望出现的情况。响应式宣言中提到使系统巧妙地响应负载的机制的重要性,及背压的重要性。


响应式流规范定义了4个主要的接口:Publisher、Subscriber、Subscription和Processor。


其中,Publisher和Observable、Subscriber和Observer基本相同;


在Subscriber中的onSubscribe方法中,引用了Subscription,这为控制元素的生产提供了基础。响应式流规范引入了request方法以扩展Publisher和Subscriber之间的交互能力。为了通知Publisher应该推送多少数据,Subscriber应该通过request方法发出关于所需数量的信号,并确保传入元素的数量不超过限制。