Go语言Modbus网关实战:ffutop modbus-gateway TCP转RTU多从站路由与Docker部署完整教程

freeFree Technical Resource

This content is free to read, suitable for basic learning and search traffic.

🌐 This page is not yet available in English. Showing the Chinese version. Back to Chinese page.
本文目录
  1. 1. 一、modbus-gateway概述
  2. 2. 二、架构原理
  3. 3. 三、安装与编译
  4. 4. 四、基础配置:TCP转RTU网关
  5. 5. 五、多从站路由配置
  6. 6. 六、本地虚拟从站
  7. 7. 七、RTU-over-TCP配置
  8. 8. 八、多网关实例
  9. 9. 九、RS485高级控制
  10. 10. 十、Docker部署
  11. 11. 十一、完整实战:工厂能源监控网关
  12. 12. 十二、性能优化与监控
  13. 13. 十三、常见问题与排查
  14. 14. 十四、配置参考速查表
  15. 15. 十五、学习资源

modbus-gateway是由ffutop开源的高性能Modbus网关,使用Go语言编写,支持TCP、RTU、RTU-over-TCP三种协议的任意桥接,基于Slave ID的多从站路由,内置本地虚拟从站,以及多主站并发队列。本文从架构原理、安装编译、配置详解到实战部署,完整介绍如何用modbus-gateway搭建工业级Modbus协议转换网关。

一、modbus-gateway概述

1.1 什么是modbus-gateway

modbus-gateway是一个配置驱动的高性能ModbusProtocol Gateway,核心功能是在不同Modbus传输协议之间进行桥接转换。典型场景是:上位机(SCADA/PLC)通过Modbus TCP连接网关,网关再通过RS485串口(Modbus RTU)连接现场设备,实现TCPtoRTU的协议转换。它还支持基于从站ID(Slave ID)的路由,可以将不同从站地址的请求分发到不同的下游设备。

1.2 核心特性

  • 全协议桥接:TCP、RTU、RTU-over-TCP三种协议在上游和下游可任意组合
  • Slave ID路由:按从站地址将请求分发到不同下游,支持范围(1-10)和列表(1,2,3)
  • 本地虚拟从站:内置虚拟Modbusslave,支持memory/file/mmap三种持久化
  • 多主站并发:多个上游主站同时连接,每个下游有独立序列化队列防止总线冲突
  • RS485 RTS控制:完整的RTS信号时序控制,支持工业级RS485转换器
  • 多网关实例:单个进程可运行多个独立网关实例
  • pprof性能分析:内置Go pprof端点,可实时诊断CPU/内存/协程
  • 高性能:Go原生并发,单实例可处理数千请求/秒
  • 零依赖部署:编译为单个二进制文件,无需运行时环境

1.3 典型应用场景

  • TCP转RTU:以太网上位机访问RS485串口设备(最常见)
  • RTU转TCP:串口主站访问以太网Modbus TCPdevice
  • 多从站聚合:多条RS485总线的设备聚合到一个TCP端口
  • 协议中继:RTU-over-TCP与标准TCP/RTU之间转换
  • 设备模拟:用本地虚拟从站模拟不存在的Modbusdevice
  • 远程访问:将现场RS485设备暴露为TCP服务,支持远程调试

二、架构原理

modbus-gateway的架构分为三层:上游(Upstream)、网关核心(Gateway)、下游(Downstream)。

┌─────────────────────────────────────────────────────────────┐
│                      Upstreams(上游)                        │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ TCP Master   │  │ RTU-over-TCP │  │ RTU Master   │      │
│  │ 0.0.0.0:502  │  │ 0.0.0.0:503  │  │ /dev/ttyS0   │      │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘      │
└─────────┼─────────────────┼─────────────────┼──────────────┘
          │                 │                 │
┌─────────▼─────────────────▼─────────────────▼──────────────┐
│                   Gateway Core(网关核心)                    │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │  Queue   │→│ Buffer   │→│Serializer│→│SlaveID   │   │
│  │  队列缓冲 │  │  缓冲区  │  │ 序列化   │  │Router    │   │
│  └──────────┘  └──────────┘  └──────────┘  └────┬─────┘   │
│                                          ┌───────▼───────┐  │
│                                          │ Local Slave   │  │
│                                          │ 本地虚拟从站   │  │
│                                          └───────────────┘  │
└──────────────────────────────┬──────────────────────────────┘
                               │
┌──────────────────────────────▼──────────────────────────────┐
│                     Downstreams(下游)                       │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ RTU Slave    │  │ TCP Slave    │  │ Local Slave  │      │
│  │ slave_ids:   │  │ slave_ids:   │  │ slave_ids:   │      │
│  │ 1-10         │  │ 11-20        │  │ 100          │      │
│  │ /dev/ttyUSB0 │  │ 192.168.1.50 │  │ mmap存储     │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘

2.1 关键机制说明

  • 队列缓冲(Queue Buffer):每个上游连接的请求先进入队列,避免请求丢失
  • 序列化(Serializer):同一下游的请求被串行化执行,防止RS485总线冲突
  • Slave ID路由:根据请求中的从站地址,查表决定发往哪个下游
  • 本地虚拟从站:路由到local类型的请求由网关内部直接响应,无需真实设备

三、安装与编译

# 方式一:源码编译(推荐)
git clone https://github.com/ffutop/modbus-gateway.git
cd modbus-gateway
go build -o modbus-gateway

# 交叉编译(在Linux上编译Windows版本)
GOOS=windows GOARCH=amd64 go build -o modbus-gateway.exe

# 交叉编译ARM版本(Raspberry Pi/嵌入式设备)
GOOS=linux GOARCH=arm GOARM=7 go build -o modbus-gateway-arm

# 方式二:下载预编译二进制
# 从GitHub Releases页面下载对应平台的二进制
# https://github.com/ffutop/modbus-gateway/releases

# 验证安装
./modbus-gateway -help
# 输出命令行参数说明

# 查看版本
./modbus-gateway -version

四、基础配置:TCP转RTU网关

最常见的场景:上位机通过Modbus TCP连接网关,网关通过RS485串口连接现场RTUdevice。

# config-tcp2rtu.yaml - TCP转RTU基础配置
gateways:
  - name: "tcp-to-rtu-gateway"
    # 上游:监听TCP端口,接受上位机连接
    upstreams:
      - type: "tcp"
        tcp:
          address: "0.0.0.0:502"   # 监听所有网卡的502端口

    # 下游:通过RS485串口连接现场设备
    downstreams:
      - type: "rtu"
        slave_ids: "1-10"          # slaveID 1-10的请求路由到此串口
        serial:
          device: "/dev/ttyUSB0"    # USB转RS485设备
          baud_rate: 9600           # Baud rate
          data_bits: 8              # data bit
          parity: "N"               # check digit N=无 E=偶 O=奇
          stop_bits: 1              # stop bit
          timeout: "500ms"          # 读取超时
          rqst_pause: "100ms"       # 请求间最小间隔

log:
  level: "info"                     # 日志级别 debug/info/warn/error
  file: ""                          # 日志文件路径,空=输出到stdout
# 启动网关
./modbus-gateway -config config-tcp2rtu.yaml

# 测试:用pymodbus或QModMaster连接网关
# 连接地址:网关IP:502
# slaveID:1-10(会被路由到RS485串口)
# function code:01/02/03/04/05/06/15/16全部支持

# 查看日志确认请求转发
# INFO tcp master accepted conn from 192.168.1.100:54321
# INFO routing slave_id=1 to downstream rtu:/dev/ttyUSB0
# INFO request FC=03 addr=0 count=10 -> response ok

五、多从站路由配置

当现场有多条RS485总线或多种类型设备时,可以通过Slave ID路由将请求分发到不同下游。

# config-multi-slave.yaml - 多从站路由
gateways:
  - name: "multi-slave-gateway"
    upstreams:
      - type: "tcp"
        tcp:
          address: "0.0.0.0:502"

    downstreams:
      # 下游1:RS485总线A - Temperature & Humidity Sensor(slave1-10)
      - type: "rtu"
        slave_ids: "1-10"
        serial:
          device: "/dev/ttyUSB0"
          baud_rate: 9600
          data_bits: 8
          parity: "N"
          stop_bits: 1
          timeout: "500ms"

      # 下游2:RS485总线B - 电力仪表(slave11-20)
      - type: "rtu"
        slave_ids: "11-20"
        serial:
          device: "/dev/ttyUSB1"
          baud_rate: 19200
          data_bits: 8
          parity: "E"           # 电力仪表常用偶校验
          stop_bits: 1
          timeout: "300ms"

      # 下游3:Modbus TCPdevice - 变频器(slave21)
      - type: "tcp"
        slave_ids: "21"
        tcp:
          address: "192.168.1.50:502"

      # 下游4:本地虚拟从站 - 网关状态(slave100)
      - type: "local"
        slave_ids: "100"
        local:
          persistence:
            type: "memory"      # 内存存储,重启后丢失

log:
  level: "info"

路由规则说明:

  • slave_ids: “1-10”:匹配从站ID 1到10的所有请求
  • slave_ids: “1,2,3”:匹配从站ID 1、2、3
  • slave_ids: “1-5,10,20-25”:混合范围和列表
  • slave_ids: “”(空):匹配所有未被其他下游匹配的请求(默认路由)
  • 如果一个从站ID被多个下游匹配,按配置顺序第一个匹配的下游生效

六、本地虚拟从站

modbus-gateway内置了本地虚拟从站功能,可以在没有真实设备的情况下响应ModbusRequest,支持三种持久化方式。

# config-local-slave.yaml - 本地虚拟从站配置
gateways:
  - name: "local-slave-demo"
    upstreams:
      - type: "tcp"
        tcp:
          address: "0.0.0.0:502"

    downstreams:
      # 虚拟从站1:内存模式(重启数据丢失,适合测试)
      - type: "local"
        slave_ids: "100"
        local:
          persistence:
            type: "memory"

      # 虚拟从站2:文件模式(数据持久化到文件)
      - type: "local"
        slave_ids: "101"
        local:
          persistence:
            type: "file"
            path: "/data/modbus-slave-101/"

      # 虚拟从站3:mmap模式(内存映射文件,高性能+持久化)
      - type: "local"
        slave_ids: "102"
        local:
          persistence:
            type: "mmap"
            path: "/data/modbus-slave-102/"

log:
  level: "debug"

6.1 三种持久化方式对比

方式速度持久化适用场景
memory最快否(重启丢失)测试、临时模拟
file较慢需要持久化但写入不频繁
mmap生产环境,高频读写

七、RTU-over-TCP配置

RTU-over-TCP是将Modbus RTU帧直接封装在TCP中传输(不加MBAP Head),常用于某些串口服务器设备。modbus-gateway支持RTU-over-TCP作为上游或下游。

# config-rtu-over-tcp.yaml - RTU-over-TCP配置
gateways:
  - name: "rtu-over-tcp-gateway"
    upstreams:
      # 上游1:标准Modbus TCP(带MBAP Head)
      - type: "tcp"
        tcp:
          address: "0.0.0.0:502"

      # 上游2:RTU-over-TCP(裸RTU帧)
      - type: "rtu-over-tcp"
        tcp:
          address: "0.0.0.0:503"   # 用不同端口区分

    downstreams:
      # 下游:标准RTUSerial Port Device
      - type: "rtu"
        slave_ids: "1-10"
        serial:
          device: "/dev/ttyUSB0"
          baud_rate: 9600
          data_bits: 8
          parity: "N"
          stop_bits: 1

      # 下游:RTU-over-TCPdevice(如某些串口服务器)
      - type: "rtu-over-tcp"
        slave_ids: "11-20"
        tcp:
          address: "192.168.1.100:4001"  # 串口服务器地址

log:
  level: "info"

八、多网关实例

单个modbus-gateway进程可以运行多个独立的网关实例,每个实例有自己的上游监听和下游连接,互不干扰。

# config-multi-gateway.yaml - 多网关实例
gateways:
  # 实例1:车间A网关
  - name: "workshop-a"
    upstreams:
      - type: "tcp"
        tcp:
          address: "0.0.0.0:502"
    downstreams:
      - type: "rtu"
        slave_ids: "1-20"
        serial:
          device: "/dev/ttyUSB0"
          baud_rate: 9600
          data_bits: 8
          parity: "N"
          stop_bits: 1

  # 实例2:车间B网关
  - name: "workshop-b"
    upstreams:
      - type: "tcp"
        tcp:
          address: "0.0.0.0:503"     # 不同端口
    downstreams:
      - type: "rtu"
        slave_ids: "1-20"
        serial:
          device: "/dev/ttyUSB1"
          baud_rate: 19200
          data_bits: 8
          parity: "E"
          stop_bits: 1

  # 实例3:能源监控网关
  - name: "energy-monitor"
    upstreams:
      - type: "tcp"
        tcp:
          address: "0.0.0.0:504"
    downstreams:
      - type: "tcp"
        slave_ids: "1-5"
        tcp:
          address: "192.168.1.50:502"

# 性能分析(可选)
pprof:
  enabled: true
  address: "localhost:6060"

log:
  level: "info"
  file: "/var/log/modbus-gateway.log"

九、RS485高级控制

对于需要精确控制RS485收发切换的工业场景,modbus-gateway提供了完整的RTS信号时序控制。

# config-rs485.yaml - RS485高级控制
gateways:
  - name: "rs485-industrial"
    upstreams:
      - type: "tcp"
        tcp:
          address: "0.0.0.0:502"
    downstreams:
      - type: "rtu"
        slave_ids: "1-10"
        serial:
          device: "/dev/ttyUSB0"
          baud_rate: 115200
          data_bits: 8
          parity: "N"
          stop_bits: 1
          timeout: "300ms"
          rqst_pause: "50ms"

          # RS485 RTS控制
          rs485: true                          # EnableRTS控制
          delay_rts_before_send: "1ms"         # 发送前RTS置位延迟
          delay_rts_after_send: "1ms"          # 发送后RTS复位延迟
          rts_high_during_send: true           # 发送期间RTS保持高电平
          rts_high_after_send: false           # 发送后RTS低电平

log:
  level: "debug"

9.1 RTS时序说明

  • rs485: true:启用硬件RTS流控,自动切换收发方向
  • delay_rts_before_send:RTS置位后等待多久再发送数据,确保RS485芯片切换到发送模式
  • delay_rts_after_send:数据发送完成后等待多久再复位RTS,确保最后一个字节发送完毕
  • rts_high_during_send:发送期间RTS电平(true=高电平,false=低电平),取决于RS485芯片的极性
  • commonRS485芯片如MAX485:DE/RE引脚通常高电平发送、低电平接收

十、Docker部署

# Dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
RUN apk add --no-cache git
RUN git clone https://github.com/ffutop/modbus-gateway.git .
RUN go build -o modbus-gateway

FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/modbus-gateway /usr/local/bin/
ENTRYPOINT ["modbus-gateway"]
CMD ["-config", "/etc/modbus-gateway/config.yaml"]
# docker-compose.yaml
version: "3.8"
services:
  modbus-gateway:
    build: .
    container_name: modbus-gateway
    restart: unless-stopped
    ports:
      - "502:502"     # Modbus TCP
      - "503:503"     # RTU-over-TCP
      - "6060:6060"   # pprof
    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0"   # RS485串口
      - "/dev/ttyUSB1:/dev/ttyUSB1"
    volumes:
      - ./config.yaml:/etc/modbus-gateway/config.yaml:ro
      - ./data:/data
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
# 构建并启动
docker-compose up -d

# 查看日志
docker-compose logs -f

# 重启
docker-compose restart

十一、完整实战:工厂能源监控网关

以下是一个完整的生产环境配置案例:工厂能源监控系统,通过modbus-gateway将车间的电力仪表、温湿度传感器和PLC统一接入SCADAsystem。

# factory-energy.yaml - 工厂能源监控网关
gateways:
  - name: "factory-energy-gateway"
    upstreams:
      # SCADA系统通过TCPconnect
      - type: "tcp"
        tcp:
          address: "0.0.0.0:502"

    downstreams:
      # 1号RS485总线:电力仪表(slave1-8)
      - type: "rtu"
        slave_ids: "1-8"
        serial:
          device: "/dev/ttyUSB0"
          baud_rate: 9600
          data_bits: 8
          parity: "E"
          stop_bits: 1
          timeout: "500ms"
          rqst_pause: "100ms"
          rs485: true
          delay_rts_before_send: "1ms"
          delay_rts_after_send: "2ms"

      # 2号RS485总线:Temperature & Humidity Sensor(slave9-16)
      - type: "rtu"
        slave_ids: "9-16"
        serial:
          device: "/dev/ttyUSB1"
          baud_rate: 4800
          data_bits: 8
          parity: "N"
          stop_bits: 1
          timeout: "1000ms"

      # 3号RS485总线:PLC(slave17-20)
      - type: "rtu"
        slave_ids: "17-20"
        serial:
          device: "/dev/ttyUSB2"
          baud_rate: 19200
          data_bits: 8
          parity: "N"
          stop_bits: 1
          timeout: "300ms"

      # 以太网设备:智能电表(slave21)
      - type: "tcp"
        slave_ids: "21"
        tcp:
          address: "192.168.1.50:502"

      # 本地虚拟从站:网关自身状态(slave100)
      - type: "local"
        slave_ids: "100"
        local:
          persistence:
            type: "mmap"
            path: "/data/gateway-status/"

# 性能监控
pprof:
  enabled: true
  address: "localhost:6060"

log:
  level: "info"
  file: "/var/log/modbus-gateway/factory-energy.log"

11.1 系统架构说明

  • SCADA系统连接网关TCP 502端口,统一访问所有设备
  • slave1-8的请求路由到USB0(电力仪表,9600偶校验)
  • slave9-16的请求路由到USB1(Temperature & Humidity Sensor,4800无校验)
  • slave17-20的请求路由到USB2(PLC,19200无校验)
  • slave21的请求转发到以太网智能电表
  • slave100由网关本地虚拟从站响应,可写入网关运行状态
  • 每个下游有独立序列化队列,不会因为一条总线慢而影响其他总线

十二、性能优化与监控

12.1 pprof性能分析

# Enablepprof后,访问以下端点:
# http://localhost:6060/debug/pprof/          - 概览
# http://localhost:6060/debug/pprof/heap       - 内存分析
# http://localhost:6060/debug/pprof/profile    - CPU分析(30秒)
# http://localhost:6060/debug/pprof/goroutine  - 协程分析

# 用go tool分析CPU
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
# 进入pprof交互界面后:
# top10          - ViewCPU占用前10的函数
# web            - 生成调用图(需要graphviz)
# list function  - 查看函数级别的耗时

# 分析内存
go tool pprof http://localhost:6060/debug/pprof/heap
# inuse_space    - 当前内存占用
# alloc_space    - 累计分配

12.2 性能优化建议

  • 合理设置timeout:超时时间应略大于设备最大响应时间,过短导致丢包,过长降低效率
  • rqst_pause调优:请求间隔根据设备响应速度调整,慢速设备建议100-200ms
  • 波特率最大化:在通信稳定的前提下尽量使用高波特率(115200)
  • 分批读取:上位机应尽量批量读取连续地址,减少请求次数
  • 连接复用:上位机保持长连接,避免频繁建立TCPconnect
  • slaveID规划:同一总线上的设备使用连续的从站ID,便于路由配置

十三、常见问题与排查

问题原因解决方法
上游连接成功但无响应slaveID未匹配到任何下游检查slave_ids配置,确保请求的从站ID在路由范围内
RTU设备无响应串口参数不匹配核对波特率、data bit、check digit、停止位与设备一致
RS485通信不稳定RTS时序不正确调整delay_rts_before/after_send,检查接线和终端电阻
多主站时数据错乱序列化队列未生效确认每个下游只有一个序列化队列,检查日志
TCP连接被拒绝端口被占用或防火墙检查502端口是否被其他程序占用,开放防火墙
虚拟从站数据丢失使用了memory模式改用file或mmap模式持久化
高延迟timeout设置过大根据设备实际响应时间调小timeout
串口权限不足用户无串口访问权限将用户加入dialout组:sudo usermod -aG dialout $USER
RTU-over-TCP不工作对端是标准TCP而非RTU-over-TCP确认设备协议类型,标准TCP用type: tcp
内存持续增长连接泄漏或数据累积用pprof分析,检查上游连接是否正常关闭

十四、配置参考速查表

配置项Type默认值说明
gateways[].namestring网关名称,用于日志标识
upstreams[].typeenumtcp / rtu / rtu-over-tcp
upstreams[].tcp.addressstringTCPListen address
downstreams[].typeenumtcp / rtu / rtu-over-tcp / local
downstreams[].slave_idsstring“”路由规则,空=匹配所有
serial.devicestring串口设备路径
serial.baud_rateintBaud rate
serial.data_bitsint8data bit
serial.paritystring“N”N/E/O
serial.stop_bitsint1stop bit
serial.timeoutduration“500ms”读取超时
serial.rqst_pauseduration“100ms”请求间最小间隔
serial.rs485boolfalseEnableRTS控制
local.persistence.typeenummemory / file / mmap
local.persistence.pathstring持久化目录
pprof.enabledboolfalse启用性能分析
log.levelstring“info”debug/info/warn/error
log.filestring“”日志文件路径

十五、学习资源

  • 项目地址:https://github.com/ffutop/modbus-gateway
  • 官方文档:http://modbus-gateway.ffutop.com/
  • Modbus协议规范:https://modbus.org/specs.php
  • Go语言官网:https://go.dev/

modbus-gateway作为Go语言编写的高性能Modbus网关,以配置驱动的方式实现了TCP/RTU/RTU-over-TCP的任意协议桥接,基于Slave ID的多从站路由和本地虚拟从站功能使其能够应对复杂的工业现场需求。本文提供的从基础TCP转RTU到多网关实例、RS485高级控制、Docker部署和完整工厂能源监控的实战配置,可直接用于生产环境部署。建议在部署前先用本地虚拟从站测试路由规则,再逐步接入真实设备。

技术术语(共 9 个)—— Click to Expand
Modbus RTU基于串行链路的ModbusProtocol,使用二进制编码和CRC check
Modbus TCP基于以太网的Modbus协议变体,使用TCP/IP传输
RS485工业常用的差分串行通信标准,支持多点通信
PLC可编程逻辑控制器,工业自动化控制的核心设备
SCADA数据采集与监视控制系统,用于远程监控工业过程
Baud rate串行通信每秒传输符号数,Modbus RTU常用9600/19200
网关协议转换设备,如 Modbus RTU ↔ Modbus TCP
serial port计算机与外部设备进行串行通信的物理接口
Sensors将物理量转换为电信号的检测装置
来源/工具信息 —— Click to Expand
来源 Modbus Chinese Network(modbus.cn) —— China leadingModbuscommunication protocol technical community Category Modbus programming development 字数 2673 字 · 阅读约 7 分钟 更新 2026-09-17 永久链接 https://www.modbus.cn/53008.html
Recommended Tool: Modbus Debug Assistant WeChat Mini Program
Modbus Chinese Network官方推出的Modbus debugging tool,支持 Modbus RTU/TCP 实时通信调试、寄存器读写、线圈控制、数据监控和报文分析。 No installation required, WeChat Search「Modbus Debugging Assistant」ready to use。 电脑端入口:https://www.modbus.cn/modbustool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 modbus.cn
Put this resource to use in a real project?

Go to the Tool Center for message parsing, CRC verification and device debugging, or submit your requirements for selection and integration advice.

Engineer Membership

Turn this article into actionable debugging resources

After activation, you can use advanced message parsing, resource pack downloads, code examples, engineering cases and priority technical support, suitable for real project delivery.

Unlimited Advanced Tools
Resource & Code Packs
Complete Engineering Case Library
Priority Technical Support