Spring5的WebFlux介绍

WebFlux 是 Spring 5 引入的响应式编程框架,作为传统 Spring MVC 的替代方案,特别适合高并发、低延迟的异步非阻塞场景

WebFlux特别适合微服务架构中的网关、代理服务和高并发API场景,但对于传统CRUD应用,Spring MVC仍然是更简单的选择。

使用过程中的注意点:

  1. 避免阻塞操作‌:不要在响应式链中调用阻塞方法
  2. 合理使用调度器‌:控制线程模型(Schedulers)
  3. 背压处理‌:正确处理订阅者的需求速率
  4. 错误处理‌:使用onErrorResume等操作符

核心概念

  1. 响应式编程模型‌:基于 Reactive Streams 规范,使用 Publisher-Subscriber 模式
  2. 非阻塞 I/O‌:使用 Netty 或 Servlet 3.1+ 容器作为底层服务器
  3. 函数式编程‌:支持 Router Functions 和 Handler Functions 的声明式 API

主要组件

1. Reactive 核心类型

  • Mono: 表示 0 或 1 个元素的异步序列
  • Flux: 表示 0 到 N 个元素的异步序列

2. WebFlux 架构

  • 基于 Reactor 库实现响应式流
  • 支持两种编程模型:
    • 注解驱动(类似 Spring MVC)
    • 函数式端点(Router Functions

关键特性

  1. 响应式数据访问‌:支持 Reactive Repositories (MongoDB, Cassandra, Redis等)
  2. WebClient‌:非阻塞的HTTP客户端
  3. 服务器推送事件(SSE)‌:支持实时数据流
  4. WebSocket支持‌:全双工通信
  5. 函数式路由‌:RouterFunction API

使用案例


@SpringBootApplication
public class WebFluxDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebFluxDemoApplication.class, args);
    }
}

@RestController
@RequestMapping("/api")
class DemoController {
    
    @GetMapping("/hello")
    public Mono<String> hello() {
        return Mono.just("Hello, WebFlux!");
    }
    
    @GetMapping("/numbers")
    public Flux<Integer> numbers() {
        return Flux.range(1, 10)
                   .delayElements(Duration.ofMillis(200));
    }
}

<project>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
    </dependencies>
</project>

WebFlux 通知前端的机制

WebFlux 主要通过以下几种方式将数据推送到前端:

1. HTTP 响应式流 (Server-Sent Events/SSE)


javaCopy Code

@GetMapping("/stream") public Flux<String> streamEvents() { return Flux.interval(Duration.ofSeconds(1)) .map(sequence -> "Event #" + sequence); }

  • 特点:单向服务器推送,基于HTTP长连接
  • 前端通过EventSource API接收

2. WebSocket 双向通信


javaCopy Code

@GetMapping("/ws") public Mono<Void> handleWebSocket(WebSocketSession session) { return session.send( Flux.interval(Duration.ofSeconds(1)) .map(i -> session.textMessage("Tick #" + i)) ); }

  • 特点:全双工通信,低延迟
  • 前端通过WebSocket API连接

3. 响应式HTTP请求


javaCopy Code

@GetMapping("/data") public Mono<Data> getData() { return dataService.fetchData(); }

  • 特点:传统请求-响应模式但非阻塞
  • 前端通过fetch/axios等接收

4. Server Push (HTTP/2)


javaCopy Code

@GetMapping("/push") public Mono<ResponseEntity<String>> pushResource() { return ServerResponse.ok() .header("Link", "</style.css>; rel=preload; as=style") .body(Mono.just("Pushing resources")); }

  • 特点:服务器主动推送资源
  • 浏览器自动处理

核心原理

  1. 响应式背压‌:前端可以控制数据流速
  2. 非阻塞IO‌:服务器线程不被阻塞
  3. 事件驱动‌:数据就绪时自动触发推送
  4. 协议支持‌:兼容HTTP/1.1, HTTP/2, WebSocket等

需要根据具体场景和前端技术栈进行统一选择。以下是选择建议:

  1. 技术匹配原则‌:

    • SSE需要前端使用EventSource API
    • WebSocket需要前端使用WebSocket API
    • HTTP Streaming需要前端支持分块传输解析
    • 普通响应式请求需要前端适配异步处理
  2. 场景适配指南‌:

模式前端技术需求适用场景不适用场景
SSEEventSource/Fetch API单向实时通知(如股票行情)需要双向交互的场景
WebSocketWebSocket API聊天室/实时协作/游戏简单数据查询
HTTP StreamingFetch+ReadableStream大文件下载/实时日志需要精确控制消息边界
普通响应式请求常规AJAX库(axios等)CRUD操作/普通API调用高频率实时更新
  1. 统一性要求‌:

    • 同一功能模块应保持通信机制一致
    • 混合使用会导致前端代码复杂度剧增
    • 需要前后端团队明确协议规范(如WS消息格式)
  2. 典型组合方案‌:

    
    

    textCopy Code

    方案1:仪表盘系统 - 主要:SSE推送实时指标 - 辅助:普通HTTP请求获取配置 方案2:在线协作应用 - 核心:WebSocket双向通信 - 附件:HTTP文件分块上传 方案3:日志监控系统 - 主通道:HTTP Streaming传输日志 - 控制面:RESTful API操作

最佳实践是:在项目设计阶段就确定通信矩阵,为每类数据交互明确指定通知机制,并建立对应的前端处理规范。

Mono和Flux函数详解

Mono和Flux是Project Reactor(也是Spring WebFlux的基础)中的两个核心响应式类型,用于表示异步数据流。

Mono 详解

Mono表示0或1个元素的异步序列,类似于Java中的OptionalFuture

主要特性:

  • 表示单值或空值的异步计算
  • 支持链式操作(类似于Stream API)
  • 可以表示成功、错误或空值三种状态

常用创建方法:


javaCopy Code

Mono.just("Hello") // 创建包含单个值的Mono Mono.empty() // 创建空Mono Mono.error(new RuntimeException()) // 创建错误Mono Mono.fromFuture(future) // 从Future创建 Mono.fromCallable(() -> "value") // 从Callable创建

常用操作符:

  • map(): 转换值
  • flatMap(): 异步转换值
  • filter(): 过滤值
  • doOnNext(): 副作用操作
  • onErrorResume(): 错误恢复
  • zipWith(): 合并两个Mono

Flux 详解

Flux表示0到N个元素的异步序列,类似于ObservableStream

主要特性:

  • 表示多值异步序列
  • 支持背压(backpressure)
  • 可以表示成功、错误或完成三种状态

常用创建方法:

Flux.just("A", "B", "C") // 创建包含多个值的Flux Flux.fromIterable(list) // 从集合创建 Flux.range(1, 10) // 创建数字范围 Flux.interval(Duration.ofSeconds(1)) // 定时发射 Flux.fromStream(stream) // 从Stream创建

常用操作符:

  • map(): 转换每个元素
  • flatMap(): 异步转换每个元素
  • filter(): 过滤元素
  • take(n): 取前n个元素
  • skip(n): 跳过前n个元素
  • reduce(): 聚合操作
  • collectList(): 收集为List
  • buffer(): 缓冲多个元素

核心区别

特性MonoFlux
元素数量0或1个0到N个
适用场景单个异步结果(如HTTP响应)流式数据(如SSE、WebSocket)
完成信号发射元素后立即完成发射所有元素后发送完成信号
典型操作符then, defaultIfEmptywindow, groupBy, sample

实际应用示例

// 组合多个Mono Mono<String> mono1 = Mono.just("Hello"); Mono<String> mono2 = Mono.just("World"); Mono.zip(mono1, mono2) .map(tuple -> tuple.getT1() + " " + tuple.getT2()) .subscribe(System.out::println); // 处理Flux流 Flux.interval(Duration.ofMillis(100)) .take(5) .map(i -> "Item " + i) .subscribe(System.out::println);

Mono和Flux是响应式编程的基础构建块,理解它们的特性和操作符对于有效使用WebFlux至关重要。

全双工通信 vs 半双工通信详解

核心区别

特性全双工通信 (Full-Duplex)半双工通信 (Half-Duplex)
数据流向双向同时传输双向交替传输
通道占用同一时间双向占用通道同一时间单向占用通道
延迟极低(无需等待通道释放)较高(需等待对方释放通道)
复杂度较高(需要分离收发通道)较低(共享传输通道)
典型协议WebSocket, TCP, 电话通话HTTP/1.1, 对讲机, RS-485总线

技术实现对比

全双工实现原理

graph LR A[客户端] -- 持续发送 --> B[服务器] B -- 同时响应 --> A

  • 物理层实现‌:
    • 双绞线(不同线对负责不同方向)
    • 光纤(不同波长传输不同方向)
    • 无线(MIMO多天线技术)
  • 协议层实现‌:
    • WebSocket:建立持久双向通道
    • HTTP/2:多路复用实现准全双工
    • QUIC:基于UDP的多向数据流

半双工实现原理


mermaidCopy Code

graph TD A[客户端] -- 请求数据 --> B[服务器] B -- 处理请求 --> A A -- 等待 --> B B -- 返回响应 --> A

  • 工作机制‌:
    1. 请求方获取通道控制权
    2. 发送数据后释放通道
    3. 接收方获取通道控制权
    4. 返回响应后释放通道
    5. 循环1-4步骤

响应式系统中的应用

WebFlux中的双工模式

通信方式双工类型实现机制
WebSocket全双工持久双向二进制帧传输
HTTP/2准全双工多路复用+流优先级
SSE半双工长连接服务端单向推送
HTTP/1.1半双工请求-响应轮询模式

性能影响对比

场景全双工方案半双工方案差异
实时聊天延迟<50ms延迟>200ms4倍延迟差距
高频数据采集吞吐量10万+/s吞吐量1万/s10倍吞吐量差距
大规模IoT设备连接数10万+连接数5千20倍连接数差距
资源消耗内存占用较高CPU占用较高资源消耗类型不同

选型建议

优先选择全双工的场景 ✅

  1. 强实时交互系统‌:在线游戏/远程控制
  2. 双向流式处理‌:视频会议/协同编辑
  3. 高频数据交换‌:金融交易系统/IOT监测
  4. 长连接服务‌:即时通讯/实时监控

适合半双工的场景 ⚠️

  1. 传统请求-响应‌:RESTful API
  2. 低频数据推送‌:新闻订阅/告警通知
  3. 资源受限设备‌:嵌入式设备通信
  4. 简单数据采集‌:传感器定期上报

混合架构实践

现代高并发系统常采用‌混合双工模式‌:


mermaidCopy Code

graph LR A[客户端] -- WebSocket全双工 --> B[实时服务] A -- HTTP/2 准全双工 --> C[API网关] C -- HTTP/1.1 半双工 --> D[传统服务]

最佳实践‌:

  1. 核心实时通道用WebSocket(全双工)
  2. 主要API交互用HTTP/2(准全双工)
  3. 对接遗留系统用HTTP/1.1(半双工)
  4. 推送服务用SSE(半双工替代轮询)

理解双工差异是设计高并发系统的关键基础,实际选型需综合考虑协议支持、基础设施、团队技术栈等约束条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值