2020-02-15
EMQX v4
EMQX (Erlang/Enterprise/Elastic MQTT Broker) 是基于 Erlang/OTP 平台开发的开源物联网MQTT消息服务器; Erlang/OTP 是出色的软实时(Soft-Realtime), 低延时(Low-Latency), 分布式(Distributed) 的语言平台; MQTT 是轻量的(Lightweight), 发布订阅模式(PubSub) 的物联网消息协议;
安装
软件源安装一堆问题,
启动/停止
bin/./emqx start #启动
bin/./emqx restart #重启
bin/./emqx stop #停止
bin/./emqx install #安装为服务
bin/./emqx_ctl status #查看状态目录结构:
| 描述 | 使用 ZIP 压缩包安装 | 使用二进制包安装 |
|---|---|---|
| 可执行文件目录 | ./bin | /usr/lib/emqx/bin |
| 数据文件 | ./data | /var/lib/emqx/data |
| Erlang 虚拟机文件 | ./erts-* | /usr/lib/emqx/erts-* |
| 配置文件目录 | ./etc | /etc/emqx/etc |
| 依赖项目录 | ./lib | /usr/lib/emqx/lib |
| 日志文件 | ./log | /var/log/emqx |
| 启动相关的脚本, schema 文件 | ./releases | /usr/lib/emqx/releases |
for windows系统./bin 目录下有个 emqx.cmd 脚本
usage: emqx (install|uninstall|start|stop|restart|console|ping|list|attach)
emqx start
配置
| 配置文件 | 说明 |
|---|---|
emqx.conf | EMQ X 配置文件 |
acl.conf | EMQ X 默认 ACL 规则配置文件 |
plugins/*.conf | EMQ X 各类插件配置文件 |
certs | EMQ X SSL 证书文件 |
emqx.lic | License 文件仅限 EMQ X Enterprise |
vi etc/emqx.conf
# 1883 MQTT TCP 协议端口
listener.tcp.external = 0.0.0.0:1883
# 8883 MQTT/TCP SSL 端口
listener.ssl.external = 8883
# 8083 MQTT/WebSocket 端口
listener.ws.external = 8083
# 8084 MQTT/WebSocket SSL 端口
listener.wss.external = 8084
# MQTT 是否允许匿名用户登录系统; (注意默认是true)
allow_anonymous = false
# 是否允许匿名用户登录系统;
zone.internal.allow_anonymous = false踩坑指南
配置更新的问题
Linux 修改完配置文件后,我们需要重新启动 emqtt 服务才能生效, 这里有个比较坑的地方在于: 如果直接用重启命令时会不起作用, 要先关闭再启动! ! !
windows
windows系统下更新也是有问题的, 通过 emqx install 后会在data目录生成一个缓存配置文件./data/configs/app..xxxxx.config , 服务启动命令会指向此文件; 重启服务是不会更新此文件, 所以修改配置不生效. 需再次通过命令行emqx start更新配置, emqx uninstall 卸载服务, 再安装服务!!!
URL Not Found
管理页 404 URL Not Found; 看下日志文件./emqx/log/xxx.log
[error] [Plugins] Load plugin emqx_management failed… Start http:management listener on 8081 unsuccessfully: the port is occupied 端口冲突
插件
EMQ X 发行包中, 包含了大量的官方插件, 提供了一些基础的, 或各类扩展的功能; 它们依赖于 emqx (opens new window)的代码 API 或者 钩子 进行实现其特殊的功能; 然后通过打包编译工具 emqx-rel (opens new window)将其与 emqx (opens new window)核心项目一起编译并打包至一个可运行的软件包中;
./etc/emqx/plugins/*.conf: EMQ X 插件配置文件, 每个插件都有单独的配置文件
启停插件 目前启动插件有以下四种方式:
- 默认加载
- 命令行启停插件
- 使用 Dashboard 启停插件
- 调用管理 API 启停插件
如需在 EMQX 启动时就默认启动某插件,则直接在 data/loaded_plugins 添加需要启动的插件名称。
Dashboard 插件
emqx_dashboard 是 EMQ X 消息服务器的 Web 管理控制台, 该插件默认开启; 当 EMQ X 启动成功后, 可访问 http://localhost:18083 进行查看, 默认用户名/密码: admin/public;
etc/plugins/emqx_dashboard.conf
## Dashboard 默认用户名/密码
dashboard.default_user.login = admin
dashboard.default_user.password = public
## Dashboard HTTP 服务端口配置
dashboard.listener.http = 18083
dashboard.listener.http.acceptors = 2
dashboard.listener.http.max_clients = 512
(https://docs.emqx.io/broker/latest/cn/plugins.html#dashboard)
认证插件
emqx_auth_username 目前只支持连接认证, 通过 username 和 password 认证客户端; 此插件在存储密码时会按照配置的 hash 算法将明文加密后存入;
用户名认证配置
(旧版本)etc/plugins/emqx_auth_username.conf
(新版本)etc/plugins/emqx_auth_mnesia.conf
## 基于 clientid 认证数据, (注意1 不是客户端ID啊)
auth.client.1.clientid = admin
auth.client.1.password = public
## username 认证数据
auth.user.2.username = admin
auth.user.2.password = public
## 密码加密方式
## 枚举值: plain | md5 | sha | sha256
auth.user.password_hash = sha256(https://docs.emqx.cn/broker/v4.3/advanced/auth-mnesia.html)
_fin_timeout=15
## Erlang 虚拟机参数
优化设置 Erlang 虚拟机启动参数, 配置文件 emqx/etc/emqx.conf:
```s
## Erlang Process Limit
node.process_limit = 2097152
## Sets the maximum number of simultaneously existing ports for this system
node.max_ports = 1048576
EMQ X 消息服务器参数
设置 TCP 监听器的 Acceptor 池大小, 最大允许连接数; 配置文件 emqx/etc/emqx.conf:
## TCP Listener
listener.tcp.external = 0.0.0.0:1883
listener.tcp.external.acceptors = 64
listener.tcp.external.max_connections = 1024000EMQX v5
https://github.com/emqx/emqx 文档 V5.1 EMQX last 文档
EMQX 版本 v4 升级到 v5 是个大修改.. 从 v4 迁移到 v5
配置文件
EMQX 的配置文件格式是 HOCON (opens new window)。 HOCON(Human-Optimized Config Object Notation)是一个JSON的超集,非常适用于易于人类读写的配置数据存储。
./etc/emqx.conf
分层结构
EMQX的配置文件可分为三层,自底向上依次是:
不可变的基础层 emqx.conf 加上 EMQX_ 前缀的环境变量。
修改这一层的配置之后,需要重启节点来使之生效。 集群范围重载层:EMQX_NODE__DATA_DIR/configs/cluster-override.conf 节点本地重载层:EMQX_NODE__DATA_DIR/configs/local-override.conf 如果环境变量 $EMQX_NODE__DATA_DIR 没有设置,那么该目录会从 emqx.conf 的 node.data_dir配置中读取。
配置文件 cluster-override.conf 的内容会在运行时被EMQX重写。 这些重写发生在 dashboard UI,管理HTTP API,或者CLI对集群配置进行修改时。 当EMQX运行在集群中时,一个EMQX节点重启之后,会从集群中其他节点复制该文件内容到本地。
从V4迁移到V5
认证授权插件(emqx_auth_*)已被移除,相关能力以内置功能的形式迁移到 EMQX 中,支持用户以 Dashboard 或配置文件的方式配置。 发布订阅 ACL 更名为 授权,认证与发布订阅 ACL 功能进行了拆分。
此前的官方插件已迁移到 EMQX 中成为内置功能
原dashboard 插件被合并到主配置文件里去了, ./etc/emqx.conf 可以找到
dashboard {
listeners.http {
bind = 18083
}
default_username = "admin"
default_password = "public"
}认证改成 authorization 必须配置ACL??
authorization {
deny_action = ignore
no_match = allow
sources = [
{
type = file
enable = true
# This file is immutable to EMQX.
# Once new rules are created from dashboard UI or HTTP API,
# the file 'data/authz/acl.conf' is used instead of this one
path = "etc/acl.conf"
}
]
}um.. 启动后可以通过管理页面配置认证 认证-> 创建认证
访问控制
认证 身份认证是物联网应用的重要组成部分,可以帮助有效阻止非法客户端的连接。为了提供更好的安全保障,EMQX 支持多种认证机制,如密码认证,JWT 认证,以及基于 MQTT 5.0 协议的增强认证。本章将介绍 EMQX 支持的密码认证、 JWT 认证和 MQTT 5.0 增强认证。
授权 在 EMQX 中,授权是指对 MQTT 客户端的发布和订阅操作进行权限控制。本章将介绍如何通过内置数据库、文件、或通过集成 MySQL、PostgreSQL、MongoDB 和 Redis 进行授权相关操作。
认证
身份验证是大多数应用程序的重要组成部分。MQTT 协议支持用户名/密码认证以及增强认证,例如 SASL/SCRAM 身份验证。启用认证可以有效防止非法客户端连接。
默认情况下,EMQX 将允许任何客户端连接,直到用户创建了认证器。认证器将根据客户端提供的认证信息对其进行身份验证,只有认证通过,客户端才能成功连接。
授权 ACL
5.x 现在 EMQX 所有认证跟授权检查功能中使用了新的语法 {username}、${clientid},该语法与规则 SQL 一致。
ACL 文件
(https://www.emqx.io/docs/zh/v5.1/access-control/authz/file.html#%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F)
基于文件的授权权限列表简单轻量,适合配置通用的规则。对于上百条或者更面向客户端的规则,推荐使用其他授权来源。基于文件的权限列表可以作为防护置于授权链末端。 EMQX 已默认配置了基于文件的授权检查器。您可点击 File 数据源对应的操作栏下的 设置 按钮查看或更改 ACL 文件中配置的授权规则。
基本语法和概念如下: 元组是用花括号包起来的一个列表,各个元素用逗号分隔 每条规则应以 . 结尾 注释行以 ` 允许用户名是 dashboard 的客户端订阅 “SYS/#" 这个主题 {allow, {user, "dashboard"}, subscribe, ["SYS/#”]}.
拒绝其他所有用户订阅 “SYS/#" 和 "#" 主题 {deny, all, subscribe, ["SYS/#”, {eq, ”#”}]}.
内部使用 {allow, {username, “tny”}, all, [”#”]}. {allow, {username, “reforward”}, all, [”#”]}.
{allow, {username, “szhtx”}, publish, [“/SZHTX/#”]}.
%% 拒绝所有 {deny, all}.
1. 授权
第一个元素表示该条规则对应的权限;可选值:
allow (允许)
deny(拒绝)
2. 客户端
第二个元素用来指定适用此条规则的客户端,比如:
{username, "dashboard"}:用户名为 dashboard 的客户端;也可写作{user, "dashboard"}
{username, {re, "^dash"}}:用户名匹配 正则表达式 (opens new window)^dash 的客户端
{clientid, "dashboard"}:客户端 ID 为 dashboard 的客户端,也可写作{client, "dashboard"}
{clientid, {re, "^dash"}}:客户端 ID 匹配 正则表达式 (opens new window)^dash 的客户端
3. 订阅和发布
第三个元素用来指定该条规则对应的操作:
publish:发布消息
subscribe:订阅主题
all:发布消息和订阅主题
4. 主题匹配
第四个元素用于指定当前规则适用的 MQTT 主题,支持通配符(主题过滤器),可以使用主题占位符:
`t/${clientid}`:使用了主题占位符,当客户端 ID 为 emqx_c 的客户端触发检查时,将精确匹配 t/emqx_c 主题
`$SYS/#`:通过通配符匹配 `$SYS/` 开头的所有主题,如 `$SYS/foo`、 $SYS/foo/bar
`S`:精确匹配 foo/# 主题,主题 foo/bar 将无法匹配,此处 eq 表示全等比较(equal)
另外还有 2 种特殊的规则,通常会用在 ACL 文件的末尾作为默认规则使用。
{allow, all}:允许所有请求
{deny, all}:拒绝所有请求
### 认证链
EMQX 允许创建多个认证器,这些认证器将按照在认证链中的位置顺序运行,如果在当前认证器中未检索到匹配的认证信息,将会切换至链上的下一个认证器继续认证过程。以 Password-Based 认证为例,通常这会产生以下 3 种情况:
某个认证器运行时检索到了可能匹配的认证信息,例如用户名一致,且剩余认证信息完全匹配,那么客户端将被允许连接。
某个认证器运行时检索到了可能匹配的认证信息,例如用户名一致,但剩余认证信息无法匹配,例如密码不一致,那么客户端将被拒绝连接。
链上所有的认证器都未检索到任何可能匹配的身份信息,那么这个客户端将被拒绝连接。
# 数据集成(Data Integration)
数据集成通过规则引擎和数据桥接,将物联网数据无缝传输到不同的数据系统。数据桥接是用来对接 EMQX 和外部数据系统的通道,比如 MySQL、MongoDB 等数据库,Kafka,RabbitMQ 等消息中间件或 HTTP 服务等。
通过数据集成,用户可以实时地将消息从 EMQX 发送到外部数据系统。如果使用双向数据桥接,用户还可以从外部数据系统拉取数据并发送到 EMQX 的某个主题。
## 规则 Rules
点击左侧导航目录中的 **集成** -> **规则**。然后点击**创建**按钮,跳转至**规则**页面。在这里,您可以定义规则的数据源,并确定数据过滤的后续操作,例如重新发布、将结果打印到控制台或通过数据桥接进行转发。
### 重发布主题(路由)
https://www.emqx.io/docs/zh/latest/data-integration/rule-get-started.html
本页面的演示以消息重发布动作作为示例,描述了如何创建一个规则,处理接收到的主题为 `t/#` 的消息,并消息重新发布到主题 `a/1`。然而,在[添加动作](https://www.emqx.io/docs/zh/latest/data-integration/rule-get-started.html#%E6%B7%BB%E5%8A%A0%E5%8A%A8%E4%BD%9C)中也描述了“控制台输出”和“使用数据桥接转发”这两类规则动作。
# 压力测试
## 测试工具 mqttbox
[install_on_windows](http://workswithweb.com/html/mqttbox/installing_apps.html#install_on_windows)
菜单里面有个`MQTTLOAD` -> `Create MQTT load ` 创建 负载测试 配置`测试指标`
如果要发布的消息数(of messages to publish)= 20, 运行时(Run time )= 5, 则每个实例( of instances to run)在5秒内总共发布20条消息; 对于每个实例给定的主题, 其大约(20/5)= 4消息/秒的发布速度;
[MQTT load test settings 文档](http://workswithweb.com/html/mqttbox/mqtt_load_test_settings.html)
> 这只是测试 消息并发
## 测试工具 emqtt_benchmark
需要安装 erlang
(https://www.erlang.org/downloads)
[emqtt-bench](https://github.com/emqx/emqtt-bench)
## 测试工具 JMeter
Apache JMeter是Apache组织开发的基于Java的压力测试工具; 用于对软件做压力测试, 它最初被设计用于Web应用测试, 但后来扩展到其他测试领域;
[参考 MQTT 压力测试](N_Jmeter.md)
# 参数调优
### Linux 操作系统参数
- 系统全局允许分配的最大文件句柄数:
`vim /etc/sysctl.conf`
追加
```s
#内核可分配的最大文件数
fs.file-max=1048576
#单个进程可分配的最大文件数
fs.nr_open=2097152
#是所允许的并发请求的最大个数。
fs.aio-max-nr=1048576
#每个用户最大可创建inotify instances数量
fs.inotify.max_user_instances = 1048576
#每个用户可同时添加的watch数量
fs.inotify.max_user_watches = 102400
确保配置立即生效
sysctl -p
sysctl -w 可以临时设置
sysctl -w fs.file-max=2097152
sysctl -w fs.nr_open=2097152- 允许当前会话/进程打开文件句柄数:
vim /etc/security/limits.conf追加
* soft nofile 1048576
# * 代表任意用户
* hard nofile 1048576 查看值 ulimit -n
vi /etc/systemd/system.conf
DefaultLimitNOFILE=1048576TCP 协议栈网络参数
#并发连接 backlog 设置:
sysctl -w net.core.somaxconn=32768
sysctl -w net.ipv4.tcp_max_syn_backlog=16384
sysctl -w net.core.netdev_max_backlog=16384
#可用知名端口范围:
sysctl -w net.ipv4.ip_local_port_range='1000 65535'
#TCP Socket 读写 Buffer 设置:
sysctl -w net.core.rmem_default=262144
sysctl -w net.core.wmem_default=262144
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.core.optmem_max=16777216
#sysctl -w net.ipv4.tcp_mem='16777216 16777216 16777216'
sysctl -w net.ipv4.tcp_rmem='1024 4096 16777216'
sysctl -w net.ipv4.tcp_wmem='1024 4096 16777216'
TCP 连接追踪设置:
sysctl -w net.nf_conntrack_max=1000000
sysctl -w net.netfilter.nf_conntrack_max=1000000
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
TIME-WAIT Socket 最大数量, 回收与重用设置:
sysctl -w net.ipv4.tcp_max_tw_buckets=1048576
# 注意: 不建议开启該设置, NAT模式下可能引起连接RST
# sysctl -w net.ipv4.tcp_tw_recycle=1
# sysctl -w net.ipv4.tcp_tw_reuse=1
FIN-WAIT-2 Socket 超时设置:
sysctl -w net.ipv4.tcp
MQTT客户端工具
mqttorg-graphics
这是一个用java开发的开源MQTT客户端
MQTTX
MQTTX 具备以下特性:
可以创建任何 MQTT Broker 连接 支持 MQTT/WebSocket 连接和 MQTT/TCP 连接 支持订阅主题 支持消息的发送和接收 跨平台桌面, 支持 Windows, MacOS 和 Linux MQTTX 是最新推出的产品, 采用了 Electron 跨平台技术, 界面美观且资源占用较低; MQTTX 在交互上一改常见的单一客户端模式, 按照 Broker 配置来组织客户端信息, 允许在同一份 Broker 配置下保存多个客户端信息; 以消息聊天的交互形式收发消息, 允许同时建立多个客户端连接并自由切换互相通信, 有较好的交互性, 大大提高了交互调试的效率;
<!> 这个默认连接到官方实例的一个地址…
MQTT协议实现方式
实现MQTT协议需要客户端和服务器端通讯完成, 在通讯过程中, MQTT协议中有三种身份:发布者(Publish), 代理(Broker)(服务器), 订阅者(Subscribe); 其中, 消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者;
MQTT传输的消息分为: 主题(Topic)和负载(payload)两部分:
(1)Topic, 可以理解为消息的类型, 订阅者订阅(Subscribe)后, 就会收到该主题的消息内容(payload); (2)payload, 可以理解为消息的内容, 是指订阅者具体要使用的内容;
消息发布服务质量
有三种消息发布服务质量:
“至多一次”, 消息发布完全依赖底层TCP/IP网络; 会发生消息丢失或重复; 这一级别可用于如下情况, 环境传感器数据,丢失一次读记录无所谓, 因为不久后还会有第二次发送; 这一种方式主要普通APP的推送, 倘若你的智能设备在消息推送时未联网, 推送过去没收到, 再次联网也就收不到了;
“至少一次”,确保消息到达, 但消息重复可能会发生;
“只有一次”, 确保消息到达一次; 在一些要求比较严格的计费系统中, 可以使用此级别; 在计费系统中, 消息重复或丢失会导致不正确的结果; 这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到一次;
MQTT 协议中文版
MQTT 协议中文版 MQTT 中文版- PDF 3.1.1
主题名和主题过滤器
主题层级(topic level)分隔符用于将结构化引入主题名。如果存在分隔符,它将主题名分割为多个主题层 级 topic level 。 订阅的主题过滤器可以包含特殊的通配符,允许你一次订阅多个主题。 主题过滤器中可以使用通配符,但是主题名不能使用通配符
多层通配符 (#)
数字标志(‘#’ U+0023)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。多层通配符必须位于它自己的层级或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主题过滤器的最后一个字符。
非规范评注
例如,如果客户端订阅主题 sport/tennis/player1/#,它会收到使用下列主题名发布的消息:
sport/tennis/player1sport/tennis/player1/rankingsport/tennis/player1/score/wimbledon非规范评注sport/#也匹配单独的sport,因为 # 包括它的父级。#是有效的,会收到所有的应用消息。sport/tennis/#也是有效的。sport/tennis#是无效的。
单层通配符 (+)
加号 (‘+’ U+002B) 是只能用于单个主题层级匹配的通配符。 在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。然而它必须占据过滤器的 整个层级。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起使用。
非规范评注
例如,sport/tennis/+ 匹配 sport/tennis/player1 和 sport/tennis/player2 ,但是不匹配
sport/tennis/player1/ranking 。同时,由于单层通配符只能匹配一个层级, sport/+ 不匹配
sport 但是却匹配 sport/。
非规范评注
+是有效的。+/tennis/#是有效的。sport+是无效的。sport/+/player1也是有效的。/finance匹配+/+和/+,但是不匹配+。
以$开头的主题
服务端不能将 字符开头的主题名匹配通配符 (#或+) 开头的主题过滤器。 服务端应该阻止客户端使用这种主题名与其它客户端交换消息。服务端实现可以将 开头的主题名用作其他目的。
非规范评注
- $SYS/ 被广泛用作包含服务器特定信息或控制接口的主题的前缀。
- 应用不能使用 $ 字符开头的主题。
非规范评注
- 订阅
#的客户端不会收到任何发布到以$开头主题的消息。 - 订阅
+/monitor/Clients的客户端不会收到任何发布到$SYS/monitor/Clients的消息。 - 订阅
$SYS/#的客户端会收到发布到以$SYS/开头主题的消息。 - 订阅
$SYS/monitor/+的客户端会收到发布到$SYS/monitor/Clients主题的消息。 - 如果客户端想同时接受以
$SYS/开头主题的消息和不以 开头主题的消息,它需要同时 订阅 `#` 和 ``SYS/#`。
Retained
发布者发布消息时,如果 Retained 标记被设置为 true,则该消息即是 MQTT 中的保留消息(Retained Message)。 MQTT 服务器会为每个主题存储最新一条保留消息,以方便消息发布后才上线的客户端在订阅主题时仍可以接收到该消息。
QoS
为适应设备不同的网络环境,MQTT 设计了 3 个 QoS 等级,0, 1, 2:
QoS-0
QoS 0 是一种 “fire and forget” 的消息发送模式:Sender (可能是 Publisher 或者 Broker) 发送一条消息之后,就不再关心它有没有发送到对方,也不设置任何重发机制。 (性能最好)
QoS-1
QoS 1 包含了简单的重发机制,Sender 发送消息之后等待接收者的 ACK,如果没收到 ACK 则重新发送消息。这种模式能保证消息至少能到达一次,但无法保证消息重复。
QoS-2
QoS 2 设计了略微复杂的重发和重复消息发现机制,保证消息到达对方并且严格只到达一次。