emqx是怎么实现公网ip访问的 (emqx接入tcp)

引言:统一管理的网关框架

作为一款大规模分布式物联网MQTT消息服务器,EMQX除了完整支持MQTT3.x和5.0,还支持 STOMP、MQTT-SN、LwM2M/CoAP,JT/T808等多种主流协议接入。不仅提供了广泛的连接能力,以处理适用于各类场景的物联网设备;还为后端的物联网管理服务提供了统一接入平台和管理接口,以降低异构协议间的适配成本。

在最新发布的EMQX 5.0中,我们重构了多协议接入的底层架构,统一了配置格式和管理接口,提供了一个全新的扩展网关框架。同时规范了各类网关的实现,使得各个网关功能定义更为清晰。

本文将对EMQX 5.0全新的网关框架及功能使用进行详细解读,帮助读者更好地利用EMQX强大的多协议接入支持能力连接各类协议设备,满足更多物联网场景的数据接入需求。

EMQX网关框架概述

由于设备的接入协议种类繁多,各个协议对连接登录、消息传输等拥有不同定义,这通常要求服务端部署各种协议的接入服务,导致软件和维护的成本急剧上升。EMQX自发布以来就提供了多协议接入的支持,来屏蔽接入层协议的异构,以降低用户的开发和运营成本。

在5.0版本之前,EMQX的多协议支持通过发布各类协议的接入插件来实现,这些独立的插件之间缺乏统一的定义和标准,相对来说有一定的使用难度。

为了给用户带来更加便捷易用的多协议支持,EMQX 5.0对整个多协议接入架构进行了重构。 所有非MQTT协议的接入都被统称为网关(Gateway)。所有网关由一个统一的框架提供通用操作的支持,包括:

  • 统一的用户层接口: 该框架提供了风格统一的配置文件、HTTPAPI和命令行接口。以监听器参数配置为例,4.x版本中不同协议插件对于监听器暴露的参数各不相同,而在5.0版本中这些参数的风格都将是统一的。
  • 统一的统计和监控指标: 提供了网关和客户端级别的统计指标,例如收发字节数、消息等。
  • 独立的连接和会话管理: 每个网关都有在自己的客户端管理页面,且不同的网关允许使用相同的ClientID,而不是像4.x版本一样都混合在MQTT客户端列表中进行管理。
  • 独立的客户端认证: 支持为每个网关配置独立的认证,不再像4.x像一样与MQTT客户端认证混合在一起。
  • 易扩展和规格清晰化: 框架抽象了一套标准的概念和接口使自定义网关变得更加容易。

emqx接入tcp,emqx怎么获取网关数据

网关统一框架

每个网关内的实现,和之前类似:

  • 监听器: 每个网关可以启动多个监听器来接受客户端的网络请求,监听器类型支持TCP、SSL、UDP、DTLS。每类网关支持的监听器类型各有不同。
  • 报文解析: 每个网关都有属于自己的报文解析模块,负责处理该协议的报文。
  • 连接/会话: 负责创建连接、会话,并处理协议中定义的各种行为,例如登录认证、消息收发等。
  • 消息模型转换: 负责处理本网关与MQTT PUB/SUB消息模型的兼容。例如,将LwM2M中的消息转换为EMQX中带主题和QoS的消息。

emqx接入tcp,emqx怎么获取网关数据

网关内部组件

网关通用行为规范

除了上述架构上的重构,EMQX 5.0的网关还对 接入认证 消息收发 这类通用行为进行了统一。

接入认证:客户端信息

网关统一使用 客户端信息 进行认证,客户端信息由网关在处理该客户端接入时创建的,其中:

  • 无论哪种网关,其客户端信息都包含通用字段,例如Client ID、Username、Password等(即使该协议无该字段的定义,网关会为其设置合适的默认值)同样也包括Peername、ProtoName、Peercert等
  • 每种网关也有其特定的客户端信息,例如LwM2M有Endpoint Name和Life Time等
  • 因此,在执行客户端认证时,此类通用的客户端字段和特有的字段都可以作为参数传递给认证器执行验证。

消息收发:PUB/SUB消息模型转换

为了适配MQTT的PUB/SUB消息模型,每类网关都必须完成对这种消息模型的兼容,以达到相互通信的目的。

对于PUB/SUB类型的协议网关, 例如MQTT-SN、STOMP通常定义了主题和消息负载的概念,则:

  • 直接使用客户端指定的主题和消息内容
  • 选择一个合适的值作为消息的QoS。
  • 对于非PUB/SUB类型的协议, 它缺少对主题、发布、订阅等概念的定义,则:
  • 需要为其指定消息主题。例如LwM2M网关,用户可以配置各个类型消息的主题。
  • 需要为其设计消息内容的格式。每种类型的网关都可能会使用不同的消息格式。

EMQX 5.0网关功能详解

客户端认证

EMQX 4.x中每种类型设备都和MQTT使用相同的认证链,这种耦合导致在配置认证器时,需要考虑每种网关的异构情况:

emqx接入tcp,emqx怎么获取网关数据

EMQX 4.x:不同类型网关认证耦合

在EMQX 5.0,网关框架允许为每种类型的网关都配置专属于自己的认证器:

emqx接入tcp,emqx怎么获取网关数据

EMQX 5.0:独立的客户端认证

消息模型转换

消息模型转换不适用于已定义PUB/SUB等概念的网关。 例如MQTT-SN协议已经定了发布/订阅的行为,则MQTT-SN网关会:

  • 将协议中的PUBLISH报文,作为消息发布,其主题和QoS都由该报文指定。
  • 将协议中的SUBSCRIBE报文,作为订阅操作,其主题和QoS都由该报文指定。
  • 将协议的UNSUBSCRIBE报文,作为取消订阅操作,其主题由该报文指定。
  • 消息模型转换也不适用于具有与PUB/SUB模型概念相近的网关。 例如STOMP协议完全兼容此消息模型,则STOMP网关会:
  • 将协议中的SEND报文作为消息发布。其主题为SEND报文中的destination字段,消息内容为SEND报文的消息体内容,QoS固定为0。
  • 将协议中的SUBSCRIBE报文作为订阅请求。其主题为SUBSCRIBE报文中的destination字段,QoS固定为0。且支持MQTT协议中定义的通配符。
  • 将协议中UNSUBSCRIBE报文作为取消订阅请求。其主题为UNSUBSCRIBE报文中的destination字段。

消息模型转换仅适用于未定义PUB/SUB等概念的网关。 例如LwM2M协议,则需要为其新增一些配置,来指定使用的主题格式,以及网关会内置一些规则来组织消息内容的格式:

gateway.lwm2m{

mountpoint="lwm2m/${endpoint_name}/"

translators{
//下行命令主题。
//对于每个成功上线的新LwM2M客户端,网关会创建一个订阅关系来接收下行消息并将其发送给客户端
command{
topic="dn/#"
qos=0
}

//用于发布来自LwM2M客户端的注册事件的主题
register{
topic="up/register"
qos=0
}
...
}
}

如果一个endpoint_name为epn1的客户端上线后:

  • 网关会为其代理订阅lwm2m/epn1/dn/#主题,以期望接收下行的控制消息
  • 网关会将该客户端的REGISTER消息,发布到lwm2m/epn1/up/register主题上。其消息格式由LwM2M网关的定义的数据转换规则决定,例如REGISTER消息的格式为:
{ "msgType": "register",                                                
  "data": {                                                             
    "ep": "epn1",                                            
    "lt": 6400,                                                
    "sms": "sms_no_example",                                                 
    "lwm2m": "1.2",          
    "objectList": ["1/0", "3/0", "19/0"]                                       
  }                                                                     
}

发布订阅授权

网关中无独立的主题授权管理,他们都集中在AuthZ中。

*注:使用PUB/SUB模型转换的网关无需对其设置的主题配置权限,因为这类客户端的主题规则是强制性的。

钩子支持性

EMQX依赖钩子实现各种功能的扩展,例如上下线消息、规则引擎的触发。因此,网关必须将关键性的事件发布到钩子上,以获取与EMQX其他功能的兼容。

在v4.x,每种钩子的支持并没有规范,v5.0中我们对其进行了总结,以下为必须支持的钩子:

emqx接入tcp,emqx怎么获取网关数据

自定义认证

网关与MQTT客户端一样,也基于认证链分发认证请求,直到链上的某个认证器、插件或ExHook返回允许/拒绝:

emqx接入tcp,emqx怎么获取网关数据

5.0认证链

因此,同样可以通过 自定义认证插件或使用ExHook 来扩展对认证的支持。每个认证器的语义可简写为:

fun authenticate(ClientInfo, LastAuthResult)  // 入参为:客户端信息、和上次认证器的执行结果
    -> {stop, NewAuthResult}                  // 返回情况1:终止链执行,并返回新的认证结果
     | ignore                                 // 返回情况2:忽略,并继续执行链上的下一个认证器

*注:所有协议都会将认证请求发布到该认证链上,所以需要通过protocol、listener_id等字段区分客户端是来自于哪类网关和监听器

用户层接口

网关框架为所有的网关提供了统一的用户层接口,例如,可以使用网关的HTTP API达到:

  • 对某网关的启用、停止和配置更新等
  • 启用、关闭、更新某网关的认证器等
  • 添加、删除、更新某网关的监听器等
  • 查询、踢出某网关的客户端,或为某客户端添加、取消订阅等

emqx接入tcp,emqx怎么获取网关数据

EMQX 5.0网关HTTPAPI接口示例

未来展望

网关框架的全新升级为用户使用EMQX 5.0进行多协议设备接入带来了诸多便利,未来我们还将在以下方面持续优化这一功能:

  • 监控信息支持输出到Prometheus和StatsD,以增加可观测性。
  • 各个协议实现的标准化测试。
  • 完善个性化管理接口、客户端信息。例如针对LwM2M设备的资源模型进行操作。
  • LwM2M等UDP类型的协议接入,需要支持NAT网络下的会话识别。一旦设备休眠后,由于NAT转换会导致LwM2M的设备唤醒后,到服务端的地址和端口发生了变化,因此应该设计某类机制来识别这种变化。
  • 为ExProto实现更轻量的设计,以降低gRPC的使用难度,提高运行效率。

通过全新网关框架实现多种协议的接入和统一管理,进一步提升了EMQX的易用性。结合强大的数据集成、安全可靠的认证授权,以及亿级的水平扩展能力等诸多优势功能特性,各行业的物联网用户可以在多种业务场景中使用EMQX实现物联网实时数据的高效连接、移动与处理。