Springboot + WebFlux + Disruptor 实现数据转发

avatar
@海尔优家智能科技(北京)有限公司

 1. 背景

利用Springboot 、WebFlux 、 Disruptor开发一套高性能、低延迟、高安全的通用数据转发平台,实现数据接收、基于配置的第三方服务转发,并通过控制台实现第三方服务的统一管控与转发规则配置。

技术框架及组件说明

WebFluxDisruptor
描述是 Spring Framework 5 引入的 响应式(Reactive)Web 框架,用于构建非阻塞、异步、高并发的 Web 应用程序。它是 Spring MVC 的响应式替代方案,适用于需要高吞吐量和低资源消耗的场景(如微服务、实时数据流、IoT 后端等)通常指 LMAX Disruptor,这是一个由英国金融技术公司 LMAX 开发的高性能并发框架,用于在 Java 中实现低延迟、高吞吐量的消息传递和事件处理。
核心优势- 在 I/O 密集型场景下,吞吐量显著高于 Spring MVC(尤其在连接数 > 1000 时)。
  • 内存占用更低(无需为每个请求分配线程栈)。
  • 更适合现代云原生、容器化部署(资源受限环境)。 | - 无锁设计:利用 CAS操作和内存屏障实现线程安全,避免锁竞争和线程上下文切换;
  • 极致低延迟:延迟可低至 纳秒级;
  • 接近零 GC:预分配内存,避免运行时创建对象;
  • 灵活的消费模式:支持单 / 多生产者、单 / 多消费者,以及消费者依赖编排。 | | 核心原理 | WebFlux 基于 Reactor 框架(实现 Reactive Streams 规范),底层依赖非阻塞 IO 容器(默认 Netty,也支持 Tomcat/Jetty 9.0+)实现。 | Disruptor 的核心是环形缓冲区(Ring Buffer) + 序列号(Sequence) ,替代传统队列的 “入队 / 出队” 操作 |

2.系统架构

2.1 整体架构

whiteboard_exported_image.png

2.2 核心流程设计

2.2.1 第三方服务配置流程

whiteboard_exported_image (1).png

  1. 管理员通过控制台提交数据提供方信息,并生成服务唯一key;
  2. 管理员通过控制台提交第三方服务信息(接口地址、请求方式、超时时间),并关联数据提供方信息;
  3. 配置信息先持久化到 MySQL,再同步缓存到 Redis(设置过期时间,定时刷新;
  4. 管理员可通过控制台启停服务(修改 Redis/MySQL 中服务状态字段,转发模块实时读取状态过滤无效服务)。

2.2.2 数据转发流程

whiteboard_exported_image (2).png

  1. 数据发送端提交数据(https)到数据接收模块,通过网关进行身份和白名单认证;
  2. 数据接收模块采用WebFlux+Netty,对数据进行预处理(格式校验、补全数据)、数据转发(异步执行);
  3. 数据下发到转发模块(通过Disruptor队列进行处理)后,数据接收模块直接返回处理结果;
  4. 在数据转发模块中,加载配置信息(第三方服务配置、转发策略配置等);
  5. 获取配置信息,构建webClient需要的请求信息(服务url,,请求方法,body信息)、重试机制和异常处理;
  6. 记录webClient执行日志,并定时批量持久化到数据库中;

2.3 高性能设计要点

  1. 响应式编程:数据接收模块基于 Spring WebFlux+Netty,非阻塞 IO 模型,支持 10w + 并发连接,相比传统 Servlet 模型大幅提升吞吐量;
  2. 异步转发:数据转发采用 “生产者 - 消费者” 模型,接收数据后放入内存队列(Disruptor 高性能队列,避免 ArrayBlockingQueue 的锁竞争),消费者线程池异步转发,解耦接收与转发流程,降低延迟;
  3. 配置缓存:第三方服务配置、转发规则全部缓存到 Redis,避免频繁查询数据库,配置读取延迟控制在毫秒级;
  4. 连接池复用:使用 WebClient连接池复用第三方服务连接,避免频繁创建 TCP 连接,提升转发效率;

3. 核心模块详细设计(代码片段)

3.1 数据接收模块

@RequestMapping("/data/receive")
public class DataReceiveController {
    @PostMapping("/json")
    public Mono<DataReceiveResult<Boolean>> receiveData(
            @RequestHeader("Send-Service-Key") String sendServiceKey,
            @RequestBody String bodyDate){
        if (!configManager.isServiceKeyValid(sendServiceKey)) {
            return Mono.just(DataReceiveResult.error("无效的服务Key"));
        }
        dataForwardService.forwardDataAsync(sendServiceKey, bodyDate, DataFormat.JSON);
        return Mono.just(DataReceiveResult.ok(true));
    }
}

@Override
public void forwardDataAsync(String sendServiceKey, String bodyDate, DataFormat dataFormat) {
    log.info("数据转发服务-异步转发数据-开始, sendServiceKey: {}, bodyDate: {}", sendServiceKey, bodyDate);
    // 获取Disruptor发布者
    RingBuffer<ForwardEvent> ringBuffer = disruptor.getRingBuffer();
    long sequence = ringBuffer.next();
    try {
        ForwardEvent event = ringBuffer.get(sequence);
        event.setSendServiceKey(sendServiceKey);
        event.setData(bodyDate);
        event.setDataFormat(dataFormat);
        event.setStartCreateTime(System.currentTimeMillis());
    } finally {
        ringBuffer.publish(sequence);
    }
}

3.2 数据转发模块

@Component
public class ForwardEventHandler implements EventHandler<ForwardEvent> {
    @Override
    public void onEvent(ForwardEvent event, long sequence, boolean endOfBatch) throws Exception {
        String serviceKey = event.getSendServiceKey();
        String rawData = event.getData();
        long startTime = System.currentTimeMillis();
        AtomicBoolean success = new AtomicBoolean(false);
        AtomicReference<String> errorMsg = new AtomicReference<>();
        
        // 执行转发(带重试,使用WebClient进行异步调用)
        Mono<String> stringMono = executeByWebClient(serviceConfig, rawData, event.getDataFormat());
        stringMono.subscribe(
            result -> {
                success.set(true);
                logService.recordForwardLog(serviceKey, rawData, rawData, success.get(), System.currentTimeMillis() - startTime, errorMsg.get());
            },
            error -> {
                errorMsg.set("转发失败:" + error.getMessage());
                logService.recordForwardLog(serviceKey, rawData, rawData, success.get(), System.currentTimeMillis() - startTime, errorMsg.get());
            }
        );
    }
    
    private Mono<String> executeByWebClient(ServiceInfo serviceConfig, String data, DataFormat dataFormat) {
        return webClient.method(getHttpMethod(serviceConfig))
                .uri(serviceConfig.getApiUrl())
                .headers(headers -> {
                    headers.setAll(getHttpHeaders(dataFormat));
                })
                .bodyValue(data)
                .retrieve()
                .bodyToMono(Result.class)
                .flatMap(result -> {
                    if (result.getSuccess()) {
                        return Mono.just(result.getData() != null ? result.getData().toString() : "");
                    } else {
                        return Mono.error(new RuntimeException("转发失败:" + result.getMessage()));
                    }
                })
                .retryWhen(
                        Retry.backoff(serviceConfig.getRetryCount(), Duration.ofMillis(100))
                                .maxBackoff(Duration.ofMillis(500))
                                .jitter(0.2d)
                                .filter(throwable -> {
                                    return shouldRetry(throwable);
                                })
                )
    }
}

团队介绍

「智慧家技术平台-应用软件框架开发」主要负责设计工具的研发,包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力,研发并沉淀素材库,构建家居家装素材库,集成户型库、全品类产品库、设计方案库、生产工艺模型,打造基于户型和风格的AI设计能力,快速生成算量和报价;同时研发了门店设计师中心和项目中心,包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理,同时为水,空气,厨房等产业提供商机管理工具,从而实现了以场景贯穿的B端C端全流程系统。