响应式编程Spring Reactor探索

一,介绍

响应式编程(Reactive Programming),简单来说是一种生产者只负责生成并发出数据/事件,消费者来监听并负责定义如何处理数据/事件的变化传递方式的编程思想。

响应式编程借鉴了Reactor设计模式,我们通常会在高性能NIO网络通信框架中见到Reactor设计模式的身影,用来实现I/O多路复用。

基本思想是将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程阻塞在多路复用器上,通过轮询或者边缘触发的方式来处理网络I/O事件。当有新的I/O事件到来或准备就绪时,多路复用器返回并将事件分发到对应的处理器中。Reactor设计模式和响应式编程类似,它们都不主动调用某个请求的API,而是通过注册对应接口,实现事件触发执行。

Reactor 诞生在响应式流规范制定之后,从一开始就是严格按照响应式流规范设计并实现了它的 API,因此Spring 选择它作为默认响应式编程框架。

背压处理

背压是所有响应式编程框架所必须要考虑的核心机制,Reactor 框架支持所有常见的背压传播模式,包括以下几种。

纯推模式:订阅者通过 subscription.request(Long.MAX_VALUE) 请求有效无限数量的元素。

纯拉模式:订阅者通过 subscription.request(1) 方法在收到前一个元素后只请求下一个元素。

推-拉混合模式:当订阅者有实时控制需求时,发布者可以适应所提出的数据消费速度。

二,动手实现

1,引入pom

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2,Controller层创建Mono来接收请求

创建Mono,设置超时时间为60秒,将任务交给service层去处理,请求会在这儿挂着,然后可以继续接收新的请求。service层处理后续业务,处理完成之后,调用monoSink.success方法返回。

如果60秒没有处理完成,就直接完成这个请求,发送超时的返回值。

如果中途执行中出现校验异常之类的,也会直接返回,结束这个请求。

复制代码
/**
 * 接收请求
 *
 * @param cmd 请求指令
 * @return 结果
 */
@PostMapping(value = "order")
public Mono<OrderResponse> order(@RequestBody OrderCmd cmd, ServerHttpRequest request) {
    return createMono(cmd, request);
}
复制代码
/**
 * 创建 Mono
 *
 * @param cmd     请求指令
 * @param request 请求
 * @return Mono
 */
public Mono<OrderResponse> createMono(OrderCmd cmd, ServerHttpRequest request) {
    // 生成关联 ID
    String correlationId = genCorrelationId(request.getId());
    // 创建MonoSink, 执行业务逻辑
    return Mono.create((Consumer<MonoSink<OrderResponse>>) monoSink -> orderService.dealRequest(correlationId, cmd, monoSink))
            // 超时时间
            .timeout(Duration.ofSeconds(60))
            //只处理 OrderException,给正常响应包
            .onErrorResume(OrderException.class, e -> Mono.just(orderService.dealException(correlationId, cmd, e)))
            .doOnSuccess(obj -> {
                if (Objects.equals(obj.get("超时返回"), "超时返回")) {
                    exceptionNoticesService.notice(new OrderException("超时返回"));
                }
            });
}

3,service层执行逻辑,并注册dispose事件

可以将MonoSink缓存,后面业务逻辑执行完成之后从缓存中获取MonoSink对象。

复制代码
// 将对象存储
cacheStore.put(correlationId, monoSink);

// 当完成其操作并关闭时,onDispose方法会被调用,以便释放资源或执行其他必要的清理工作。
monoSink.onDispose(() -> cacheStore.remove(correlationId));

//完成业务逻辑之后,调success方法,返回请求结果

复制代码
MonoSink<OrderResponse> monoSink = cacheStore.get(correlationId);
复制代码
monoSink.success(transResponse);

三,小结

Spring Reactor框架是响应式编程的一个很好的实践,能帮助开发者快速完成相关的需求,能很好的实现支持背压处理。

相关推荐
Ajiang282473530424 分钟前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空29 分钟前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10223 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸4 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象5 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了5 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
----云烟----5 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024065 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
小二·6 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端