Spring WebFlux 适配达梦新方案|dm‑r2dbc:Netty 异步传输的实验性 R2DBC 驱动

Spring WebFlux 适配达梦新方案|dm‑r2dbc:Netty 异步传输的实验性 R2DBC 驱动

仓库地址:https://github.com/jinyuttt/dm‑r2dbc.git ⚠️重要提示:本项目属于实验性技术研究项目,禁止直接用于生产环境,存在反射、许可协议相关风险,请务必仔细阅读免责声明。

一、背景痛点:达梦 R2DBC 现状

达梦数据库 DM8 作为主流国产数据库,在 Spring WebFlux 响应式项目中适配一直比较尴尬。

达梦官方提供了 R2DBC 驱动,但底层是JDBC 桥接模式 :仅仅封装一层 R2DBC SPI 接口,网络 IO 仍然使用传统阻塞java.net.Socket。本质上属于 "伪响应式",所有数据库 IO 依旧是阻塞调用,靠boundedElastic线程池隔离阻塞逻辑。高并发场景很容易出现线程池饥饿、吞吐量瓶颈,大字段 CLOB/BLOB 处理也容易踩坑。

想要做真正全链路非阻塞 R2DBC,正常有两条路:

  1. 完全逆向达梦私有 TCP 二进制协议,从零实现 R2DBC 驱动。工作量巨大,协议版本一变就要大规模改代码,还有逆向带来的法律风险。
  2. 复用官方 JDBC 成熟的协议编解码,只替换底层网络传输层。也就是开源项目dm‑r2dbc选择的混合架构方案。

二、dm‑r2dbc 项目简介

dm‑r2dbc 是面向达梦 DM8 的实验性 R2DBC 驱动,混合架构:Netty 异步网络传输层 + JDBC 驱动协议编解码复用

核心思路:不去逆向达梦私有协议二进制报文,直接复用达梦 JDBC 驱动内部已经成熟的编解码逻辑,通过反射替换 JDBC 内部默认阻塞 Socket 传输实现,替换为 Netty NIO 异步通道,实现真正异步非阻塞网络 IO。

版本信息

  • 项目名称:dm‑r2dbc
  • 当前版本:1.0‑SNAPSHOT
  • 许可证:Apache‑2.0
  • 目标 JDBC 驱动版本:DmJdbcDriver8 8.1.3.62
  • JDK 要求:JDK17+
  • 数据库:DM8(8.1.3.x)
  • 测试状态:12 项单元测试全部通过(连接、查询、DML、CLOB/BLOB、事务、自增主键、关键字、存储过程)

三、整体架构设计

整体分层:应用层 → R2DBC SPI → dm‑r2dbc 驱动适配层 → JDBC 协议编解码复用层 → Netty 异步传输层 → DM8 数据库服务端 (5236 端口)。

  1. R2DBC API 适配层 :实现ConnectionFactoryProviderDmConnectionDmStatementDmCallableStatement,对外暴露标准 R2DBC 接口;
  2. 协议编解码复用层 :直接调用达梦 JDBC 驱动DmDriverDmdbConnection、PreparedStatement 完成 SQL 解析、报文编解码,不自己解析二进制协议;
  3. 反射注入传输层 :通过反射找到 JDBC 驱动内部通信管理器的传输对象字段,替换为自研DmNettyTransport
  4. Netty 网络层 :实现 JDBC 驱动定义的传输接口,使用 Netty NIO 完成 TCP 收发;DmNettyResponsePipeline处理服务端响应报文缓存。

线程模型关键点:

  • Netty EventLoop 线程:只做 TCP 读写,绝不执行任何阻塞业务逻辑
  • JDBC 所有阻塞调用(连接创建、SQL 执行、编解码)全部调度到Schedulers.boundedElastic()弹性线程池,隔离阻塞;
  • 上层应用 WebFlux 线程消费 Mono/Flux 结果。
    ⚠️当前 1.0‑SNAPSHOT 版本限制:DmNettyResponsePipeline内部使用wait/notifyAll等待响应,虽然阻塞被放到 boundedElastic 线程,但高并发场景会占用弹性线程资源。v1.1 规划迭代串行请求‑应答匹配模型,消除该阻塞点。

四、快速上手示例

注意:达梦官方 JDBC 驱动无法从公共 Maven 仓库下载,需要手动将DmJdbcDriver8.jar安装到本地 Maven 仓库或者放入项目 lib 目录。

1.Maven 依赖

复制代码
<dependency>
    <groupId>org.dameng</groupId>
    <artifactId>dm‑r2dbc</artifactId>
    <version>1.0‑SNAPSHOT</version>
</dependency>

同时需要准备达梦 JDBC 驱动 8.1.3.62。

2. 连接字符串格式

复制代码
r2dbc:dm://SYSDBA:SYSDBA@127.0.0.1:5236

3.Spring Boot WebFlux 配置(application.yml)

复制代码
spring:
  r2dbc:
    url: r2dbc:dm://127.0.0.1:5236
    username: SYSDBA
    password: SYSDBA

4. 编程式使用示例

复制代码
import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.ConnectionFactoryOptions;
import reactor.core.publisher.Mono;
import static io.r2dbc.spi.ConnectionFactoryOptions.*;

public class Demo {
    public static void main(String[] args) {
        ConnectionFactoryOptions options = ConnectionFactoryOptions.builder()
                .option(DRIVER, "dm")
                .option(HOST, "127.0.0.1")
                .option(PORT, 5236)
                .option(USER, "SYSDBA")
                .option(PASSWORD, "SYSDBA")
                .build();

        ConnectionFactory factory = ConnectionFactories.get(options);

        Mono.from(factory.create())
                .flatMap(conn ->
                        Mono.from(conn.createStatement("SELECT ID,NAME FROM USERS WHERE ID = ?")
                                        .bind(0,1L)
                                        .execute())
                                .flatMapMany(result -> result.map((row,meta)->{
                                    Long id = row.get("ID",Long.class);
                                    String name = row.get("NAME",String.class);
                                    return id + " | " + name;
                                }))
                                .then(Mono.from(conn.close()))
                )
                .subscribe(System.out::println);
    }
}

再次强调:实验性项目,不要直接上生产。如果业务需要生产级 R2DBC 能力,优先使用达梦官方驱动,或者等待官方推出原生异步 R2DBC 实现。

GitHub 仓库:https://github.com/jinyuttt/dm‑r2dbc.git 完整技术设计文档仓库内可查看。

相关推荐
泡海椒1 小时前
内置SPI函数库详解:JQuick-Java Builtin工具类实战用法
java·开发语言·python
辰烨chenye1 小时前
LeetCode Hot 100 题解 · 二分篇
java·算法·leetcode
小羊没烦恼!2 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰2 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
小荷才露尖尖角,早有蜻蜓立上头3 小时前
过滤器的4种创建方式
java
大圣编蚕3 小时前
Java ByteArrayInputStream 详解:从入门到实战
java·开发语言·算法
程序员阿明3 小时前
idea把插件啥的不默认放在C盘
java·ide·intellij-idea
linweidong4 小时前
中科闻歌Java面试题及参考答案
java·python·大模型·提示词·ai agent·mcp·rag原理
OpenAnolis小助手4 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom