响应式编程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框架是响应式编程的一个很好的实践,能帮助开发者快速完成相关的需求,能很好的实现支持背压处理。

相关推荐
Charlotte_jc5 分钟前
完美解决openpyxl保存Excel丢失图像/形状资源的技术方案
开发语言·python·excel·openpyxl
盖世英雄酱581368 分钟前
🚀不改SQL,也能让SQL的执行效率提升100倍
java·数据库·后端
Java技术小馆18 分钟前
Cursor链接远程服务器实现项目部署
java
用户05956611920924 分钟前
深入理解Spring Boot框架:从基础到实践
java·spring·编程语言
西北大程序猿25 分钟前
服务器代码知识点补充
服务器·开发语言·网络·c++·网络协议
晴空月明30 分钟前
JVM 类加载过程与字节码执行深度解析
java
掉鱼的猫1 小时前
Solon AI + MCP实战:5行代码搞定天气查询,LLM从此告别数据孤岛
java·openai·mcp
带刺的坐椅2 小时前
Solon AI + MCP实战:5行代码搞定天气查询,LLM从此告别数据孤岛
java·mcp·solon-ai
androidwork2 小时前
嵌套滚动交互处理总结
android·java·kotlin
新知图书2 小时前
R语言ICU患者死亡率预测实战
开发语言·r语言