在正常业务利用下对付客户真个行为可以利用ACL进行限定,比如A客户端只能订阅 /A/get 行列步队和向 /A/set 发布内容 但是在MYSQL里面处理这样的鉴权就须要写入两条记录,如果设备量有一百万数据库就要承担两百万条鉴权数据量会大大影响数据库的性能 那么有没有什么批量的办法来定义ACL鉴权呢?
在mysql-ACL鉴权的配置文件下关于如何利用鉴权的SQL是可以编辑的,也就意味着你可以通过SQL来实现批量ACL鉴权规则
> vim /usr/local/emqttd/etc/plugins/emq_auth_mysql.conf# 最下面有这样一条配置auth.mysql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'
笔者这里就实现每个设备默认可以订阅 /A/get 行列步队和向 /A/set 发布

笔者现在的规则是客户端只能向hello写其他操作一概不许可,我们先加两条记录
insert `mqtt_acl`(`allow`,`username`,`access`,`topic`) values(1,'$all',1,'/$user/get');insert `mqtt_acl`(`allow`,`username`,`access`,`topic`) values(1,'$all',2,'/$user/set');
然后修正默认的ACL鉴权的SQL语句如下(这里利用的是username作为topic动态名称也可以利用其他字段):
select allow, ipaddr, username, clientid, access, REPLACE(topic,'$user','%u') from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'
这样一来就算没有独立配置/A/set可以写入,作为用户是A的客户端也可以进行的写入了,并且也可以监听/A/get
2.共享订阅
关于行列步队常见的利用中也有这样的场景,一条希望被多个监听程序吸收到,可能的场景如下:
一个程序处理,一个程序记录日志分别处理
批量推送
--------- | | --Msg1,Msg2,Msg3--> Subscriber1Publisher--Msg1,Msg2,Msg3-->| EMQ | --Msg1,Msg2,Msg3--> Subscriber2 | | --Msg1,Msg2,Msg3--> Subscriber3 ---------
多条希望被多个程序中的某个进行处理,场景如下:
并发情形下耗时操作进行并行处理提高系统吞吐量
--------- | | --Msg1--> Subscriber1Publisher--Msg1,Msg2,Msg3-->| EMQ | --Msg2--> Subscriber2 | | --Msg3--> Subscriber3 ---------
在默认情形下有多个客户端监听一个事宜时会受到同样的,但是怎么共享订阅呢?EMQ共享订阅支持两种利用办法:
$queue/如:$queue/topic
$share/<group>/如:$share/group/topic
以上两种都可以实现共享订阅(笔者测试下来值通过了share来完成了订阅),订阅和监听
多个做事端监听 $share/group/topic
客户端向 topic 发送
3.Qos 0/1/2的差异实测
最多一次的传输 是基于TCP/IP网络传输的。没有回应,在协议中也没有定义重传的语义。可能到达做事器1次,也可能根本不会到达。
至少一次的传输 做事器吸收到会被确认,通过传输一个PUBACK信息。如果有一个可以辨认的传输失落败,无论是通讯连接还是发送设备,还是过了一段韶光确认信息没有收到,发送方都会将头的DUP位置1,然后再次发送。最少一次到达做事器。SUBSCRIBE和UNSUBSCRIBE都利用level 1 的QoS。 如果客户端没有吸收到PUBACK信息(无论是运用定义的超时,还是检测到失落败然后通讯session重启),客户端都会再次发送PUBLISH信息,并且将DUP位置1。 当它从客户端吸收到重复的数据,做事看重新发送给订阅者,并且发送另一个PUBACK。
笔者做了一个实现消费端壅塞2秒消费一个内容,发布端1秒发布一个内容,等EMQ的最大拥塞利用完了之后在EMQ缓存的会后就会涌现很多的重复
只有一次的传输 在QoS level 1上附加的协议流担保了重复的不会传送到吸收的运用。这是最高级别的传输,当重复的不被许可的情形下利用。这样增加了网络流量,但是它常日是可以接管的,由于内容很主要。 QoS level 2在头有Message ID。
4.密码加盐
在用户验证中可以利用plain | md5 | sha | sha256 | bcrypt等hash办法(默认利用的sha256),但是出于安全性考虑EMQ也支持对密码加盐,可以解开注释利用一下加盐办法中的一种
vim /usr/local/emqttd/etc/plugins/emq_auth_mysql.conf## sha256 with salt prefix## auth.mysql.password_hash = salt,sha256## bcrypt with salt only prefix## auth.mysql.password_hash = salt,bcrypt## sha256 with salt suffix## auth.mysql.password_hash = sha256,salt## pbkdf2 with macfun iterations dklen## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512## auth.mysql.password_hash = pbkdf2,sha256,1000,20
对应存储的密码就要进行加盐处理了
5.EMQ离线
保留 MQTT客户端向做事器发布(PUBLISH)时,可以设置保留(Retained Message)标志。保留(Retained Message)会驻留在做事器,后来的订阅者订阅主题时仍可以吸收该。 例如mosquitto命令行发布一条保留到主题’a/b/c’: mosquitto_pub -r -q 1 -t a/b/c -m 'hello' 之后连接上来的MQTT客户端订阅主题’a/b/c’时候,仍可收到该: $ mosquitto_sub -t a/b/c -q 1 hello 保留(Retained Message)有两种打消办法: 客户端向有保留的主题发布一个空: mosquitto_pub -r -q 1 -t a/b/c -m '' 做事器设置保留的超期韶光。
cleanSession 清理回话 MQTT客户端向做事器发起CONNECT要求时,可以通过’Clean Session’标志设置会话。 ‘Clean Session’设置为0,表示创建一个持久会话,在客户端断开连接时,会话仍旧保持并保存离线,直到会话超时注销。 ‘Clean Session’设置为1,表示创建一个新的临时会话,在客户端断开时,会话自动销毁。
3 总结
在EMQ和MQTT利用过程中还有很多的细节须要把稳,关注细节才能走的更远
注:笔者能力有限有说的不对的地方希望大家能够指出,也希望多多互换!