Netty + Modbus RTU 工业级通信方案文档

11 阅读2分钟

适用场景:工业物联网(IIoT)、PLC采集、2000+设备高并发轮询


一、方案概述

本方案基于 Netty NIOmodbus4j 库,构建高性能、低延迟的 Modbus RTU over TCP 通信系统。

核心设计思想

层级职责
NettyIO 多路复用、拆包、连接管理、调度
modbus4j协议解析、CRC校验、功能码语义
业务层数据持久化、告警、计算

单一职责
无阻塞 IO
毫秒级轮询
线性扩展


二、系统架构

┌──────────────────────────────┐
│        Business Layer        │  ← 数据库 / MQ / 告警
└─────────────▲────────────────┘
              │ ChannelHandler
┌─────────────┴────────────────┐
│      StateMachineHandler      │  ← 请求-响应对齐
├──────────────────────────────┤
│       ModbusParseHandler      │  ← modbus4j 解析
├──────────────────────────────┤
│       ModbusRtuDecoder        │  ← 拆包 + CRC
├──────────────────────────────┤
│      IdleStateHandler         │  ← 心跳/断连
└─────────────▲────────────────┘
              │ Socket
┌─────────────┴────────────────┐
│         TCP Device            │
│      (串口服务器/网关)        │
└──────────────────────────────┘

三、核心技术选型

组件选型原因
IO框架Netty 4.1.x高性能、成熟
协议解析modbus4j工业验证
定时器HashedWheelTimerO(1) 轮询
线程模型EventLoopGroup非阻塞
序列化ByteBuf零拷贝

四、核心模块设计

4.1 服务启动(ServerBootstrap)

EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup();

ServerBootstrap b = new ServerBootstrap();
b.group(boss, worker)
 .channel(NioServerSocketChannel.class)
 .childOption(ChannelOption.TCP_NODELAY, true)
 .childOption(ChannelOption.SO_KEEPALIVE, true)
 .childHandler(new ChannelInitializer<>() {
     @Override
     protected void initChannel(SocketChannel ch) {
         ch.pipeline()
           .addLast(new IdleStateHandler(5, 0, 0))
           .addLast(new ModbusRtuDecoder())
           .addLast(new ModbusParseHandler())
           .addLast(new StateMachineHandler())
           .addLast(new BusinessHandler());
     }
 });

b.bind(9090).sync();

4.2 拆包层(ModbusRtuDecoder)

只负责拿到完整 RTU 帧

  • 最小 4 字节
  • CRC 校验
  • 功能码长度预判

📌 不解析寄存器


4.3 协议解析层(ModbusParseHandler)

public class ModbusParseHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        byte[] frame = (byte[]) msg;
        ModbusResponse resp = ModbusRtuUtils.parseResponse(frame);
        ctx.fireChannelRead(resp);
    }
}

modbus4j 自动完成:

  • CRC
  • 异常码
  • 字节序

4.4 状态机层(StateMachineHandler)

状态行为
IDLE允许发送
WAIT_RESPONSE拒绝新请求
TIMEOUT关闭连接

防止 RTU 乱序


4.5 轮询调度(HashedWheelTimer)

HashedWheelTimer timer =
    new HashedWheelTimer(100, MILLISECONDS, 512);

void schedule(Channel ch, int slaveId) {
    timer.newTimeout(t -> {
        if (!ch.isActive()) return;

        ModbusRequest req =
            new ReadHoldingRegistersRequest(slaveId, 0, 10);
        ch.writeAndFlush(req);

        schedule(ch, slaveId);
    }, 1, SECONDS);
}

天然背压控制


五、业务处理示例

protected void channelRead0(ChannelHandlerContext ctx,
                           ModbusResult result) {

    ReadResponse resp = result.response();

    int status = resp.getShort(0);
    float temp = resp.getFloat(2);
    long ts = System.currentTimeMillis();

    businessExecutor.execute(() ->
        repository.save(status, temp, ts)
    );
}

⚠️ 严禁阻塞 EventLoop


六、性能与稳定性设计

6.1 线程模型

线程职责
BossAccept
WorkerIO
BusinessDB / MQ

6.2 高并发优化

✅ 单连接串行轮询
✅ 无锁状态机
✅ ByteBuf 零拷贝
✅ 定时器 O(1)


6.3 容错机制

场景策略
CRC 错误丢弃 + 断连
超时关闭连接
乱序丢弃
OOM池化 ByteBuf

七、部署建议

规模配置
≤500 设备单节点
500~2000多端口
≥2000多实例 + 网关分组

八、与手写 NIO 对比

指标手写 NIONetty
开发周期
Bug 率极低
维护成本
吞吐量极高

九、总结

Netty 负责“快”,modbus4j 负责“准”。

该方案已在工业现场验证,适用于:

  • 电力监控
  • 智能制造
  • 能源采集
  • 智慧水务

十、下一步可选交付

✅ 封装 Modbus RTU ↔ Netty Adapter
✅ 多 Slave 轮询模板
✅ 断线重连与黑名单机制
✅ Prometheus 监控指标