MQTT研究之EMQ:【eclipse的paho之java客户端使用注意事项】
这里,简单记录一下自己在最近项目中遇到的paho的心得,这里也涵盖EMQX的问题。
1. cleanSession
这个标识,是确保client和server之间是否持久化状态的一个标志,不管是client还是server重启还是连接断掉。下面是来自paho客户端源码的注释。
Sets whether the client and server should remember state across restarts and reconnects.
- If set to false both the client and server will maintain state across restarts of the client, the server and the connection. As state is maintained:
- Message delivery will be reliable meeting the specified QOS even if the client, server or connection are restarted.
- The server will treat a subscription as durable.
 
- If set to true the client and server will not maintain state across restarts of the client, the server or the connection. This means
- Message delivery to the specified QOS cannot be maintained if the client, server or connection are restarted
- The server will treat a subscription as non-durable
 
1)。 这个标志位,设置为true,那么,当连接断掉,例如,调用EMQX的接口踢掉连接,此时,即便重连上了(无论是通过autoconnect设置为true,还是在connectonLost这个回调函数里面配置上重连的逻辑),MQTT客户端程序都是无法进行重新订阅数据的。这个行为,说明session里面保存了会话所采用的topic信息。
2)。这个标志位,设置为true,autoconnect设置为false,在connectLost这个回调函数里面,自行实现重新连接的逻辑,并且再次针对相同的topic和qos进行订阅的话,当连接被踢掉,这个时候,会重新连接上,并且也会订阅上数据,只是会出现很奇怪的现象,CPU占用率比连接断开前提高很多。 我的应用(订阅到数据后,对数据进行相应的逻辑处理,正常情况下,一条数据大概1~5ms处理完)压测环境下,连接未断前,1.3W的并发,CPU空闲率在40%左右,重连之后,CPU的空闲率只有10%左右,这个地方是个大坑,目前我还没有搞清楚到底是什么原因导致,若有人遇到类似问题同仁,请给我留言,告知可能的原因。(我的paho是1.2.0版本,EMQX:V3.1.1)
3)。这个标志位,设置为false,autoconnect设置为false,在connectLost这个回调函数里面,自行实现重连的逻辑,但是不对topic进行重新订阅,即便连接断掉,重新连接上的话,依然会进行连接断开之前的业务逻辑,订阅到所需的数据,CPU的负荷也不会变大,基本和断开之前的状态持平。
下面配上connectLost这个回调函数(MqttCallback接口的一个方法)相关代码:
public void connectionLost(Throwable cause) {
        // 连接丢失后,一般在这里面进行重连
        System.out.println(">>>>>>>>>>>>>>>" + cause.getMessage());
        System.out.println("连接断开,可以做重连");
        for (int i = ; i < ; i++) {
            if(reconnect()) {
                break;
            }else{
                try {
                    Thread.sleep(i * );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private boolean reconnect() {
        try {
            mqttClient.connect(mqttConnectOptions);
            Thread.sleep();
            if( mqttClient.isConnected() ) {
                //mqttClient.subscribe(this.topic, 0);
                return true;
            }
        } catch (MqttException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return  false;
    }
2. EMQX的承压能力
网上标榜EMQX单节点处理能力多么牛逼,100W连接毫无压力,这个数值,其实呢,我觉得要仔细看测试场景,单单看连接数,其实没有什么意义,要看生产者消费者都存在的情况下,还有数据流通这种场景,连接能力或者数据处理能力如何。 我不是说100W连接能力是虚构的,我是想说纯粹的连接其实没有多大的价值,因为EMQX是消息总线,只有连接,不存在数据流动,有多大意义呢?
还是接着我上面的应用压测,我们团队开发的一个规则引擎,1.6W的消息并发(4000设备,每个设备每秒4条消息,当然是程序模拟出来的),规则引擎4C16G的服务器2台,每台跑3个实例,共享订阅两个EMQX节点(EMQX是集群),EMQX服务器配置4C16G。结果跑不了多久时间(1个小时不到,有时半个小时),就会出现EMQX平凡踢掉消费者连接的情况。
-- ::42.710 [error] 0ba45c9872464c609c150f156e3f2a7e@10.95.198.25: [Connection] Shutdown exceptionally due to message_queue_too_long
-- ::55.746 [error] 4014030aed1642bba6ecec85debed172@10.95.198.26: [Connection] Shutdown exceptionally due to message_queue_too_long
-- ::08.131 [error] dde7f075ab2d45fdabfd192b5c6a4a30@10.95.198.25: [Connection] Shutdown exceptionally due to message_queue_too_long
-- ::14.374 [error] 72a25aca01164c8c8b4cf48451c4e316@10.95.198.25: [Connection] Shutdown exceptionally due to message_queue_too_long
-- ::41.686 [error] cd56963bfb4e4c0c8275abe9a24078de@10.95.198.26: [Connection] Shutdown exceptionally due to message_queue_too_long
-- ::52.638 [error] 4014030aed1642bba6ecec85debed172@10.95.198.26: [Connection] Shutdown exceptionally due to message_queue_too_long
-- ::06.015 [error] dde7f075ab2d45fdabfd192b5c6a4a30@10.95.198.25: [Connection] Shutdown exceptionally due to message_queue_too_long
-- ::13.541 [error] 0ba45c9872464c609c150f156e3f2a7e@10.95.198.25: [Connection] Shutdown exceptionally due to message_queue_too_long
针对这个问题,我咨询过青云的EMQ团队的工程师,也在Github上咨询过EMQX的维护者,都反馈说是消费者处理速度太慢,emq的消息队列消息堆积导致。现象如此,怎么解决呢,似乎只能添加消费者服务,或者降低消息压力,EMQX能否提升性能呢?我觉得EMQX现在共享订阅的能力不行,就这4000个连接投递消息,1.6W的并发,4000个topic,采用共享订阅的方式,性能感觉不是很好,是我们程序设计的有问题,还是EMQX共享订阅性能真的有待提升?为什么这么说能,我们测试过非共享订阅,就是明确订阅某个指定topic。非共享订阅情况下,相同的服务器上,比共享订阅性能好很多很多(差不多一半)。。。(欢迎探讨)
从EMQX的配置中,针对上面这种消息队列太长的问题,emqx.conf的配置文件中有相关信息,参考下面这个错误找到了相关的配置参数,EMQX的官方参数解释或者支持真心跟不上,没有国外开源组织社区营造的好,这个需要努力。
-- ::30.362 [error] f2ac199b0314449d822e150c8d51de93 crasher:
initial call: emqx_session:init/
pid: <0.20141.>
registered_name: []
exception exit: killed
in function emqx_session:handle_info/ (src/emqx_session.erl, line )
in call from gen_server:try_dispatch/ (gen_server.erl, line )
in call from gen_server:handle_msg/ (gen_server.erl, line )
ancestors: [emqx_session_sup,emqx_sm_sup,emqx_sup,<0.1386.>]
message_queue_len:
messages: []
links: [<0.1577.>]
dictionary: [{force_shutdown_policy,
#{max_heap_size => 838860800,message_queue_len => 8000}},
{deliver_stats,},
{'$logger_metadata$',
#{client_id => <<"f2ac199b0314449d822e150c8d51de93">>}}]
trap_exit: true
status: running
heap_size:
stack_size:
reductions:
neighbours:
再看看emqx.conf的配置文件中,和这个queue相关的配置:
## Max message queue length and total heap size to force shutdown
## connection/session process.
## Message queue here is the Erlang process mailbox, but not the number
## of queued MQTT messages of QoS and .
##
## Numbers delimited by `|'. Zero or negative is to disable.
##
## Default:
## - |800MB on ARCH_64 system
## - |100MB on ARCH_32 sytem
## zone.external.force_shutdown_policy = |800MB
有人会说,你可以将这里的消息数量调大点啊,没错,这个调一下是可以改善,但是不能根治问题,自己想想吧,大点最多也就是对消息速率波动的韧性加大了,但是不能解决持续生成高于所谓的消费慢这种情况下的问题。 EMQ方说辞其实,在我们的这个场景下,我是不那么认同的,为什么这么说呢, 我的规则引擎消费日志里面显示,每条消息处理的时间并没有变长,CPU的忙碌程度并没有恶化, 添加共享订阅实例变多,EMQX性能下降了,我觉得EMQX在共享订阅变多的情况下,对消费者端投递消息的速率或者效率下降了,但是呢,EMQX这个broker从消息生产者这边接收消息的能力没有改变,导致EMQX的消息队列消息积压,最终出现踢连接的policy得以执行。。。
还有一个问题,不知道细心的读者有没有发现,消费者这边消息消费的好好的,消息积压了,EMQX为何要把消费者的连接给踢掉呢,为何不是将生产者的连接踢掉呢?这个逻辑我觉得有点不是很好理解,本来消息就积压了,是不是要加快消费才能缓解或者解除消息积压的问题?读者你们是如何理解的,也可以留言探讨!
MQTT研究之EMQ:【eclipse的paho之java客户端使用注意事项】的更多相关文章
- MQTT研究之EMQ:【EMQ之HTTP认证/访问控制】
		今天进行验证的逻辑是EMQ的http的Auth以及ACL的逻辑. 首先,参照HTTP插件认证配置的说明文档进行基本的配置, 我的配置内容如下: ##-------------------------- ... 
- MQTT研究之EMQ:【SSL证书链验证】
		1. 创建证书链(shell脚本) 客户端证书链关系: rootCA-->chainca1-->chainca2-->chainca3 ca caCert1 caCert2 caCe ... 
- MQTT研究之EMQ:【CoAP协议应用开发】
		本博文的重点是尝试CoAP协议的应用开发,其中包含CoAP协议中一个重要的开源工具libcoap的安装和遇到的问题调研.当然,为了很好的将EMQ的CoAP协议网关用起来,也调研了下EMQ体系下,CoA ... 
- MQTT研究之EMQ:【JAVA代码构建X509证书【续集】】
		openssl创建私钥,获取公钥,创建证书都是比较简单的,就几个指令,很快就可以搞定,之所以说简单,是因为证书里面的基本参数配置不需要我们组装,只需要将命令行里面需要的几个参数配置进去即可.但是呢,用 ... 
- MQTT研究之EMQ:【JAVA代码构建X509证书】
		这篇帖子,不会过多解释X509证书的基础理论知识,也不会介绍太多SSL/TLS的基本信息,重点介绍如何用java实现SSL协议需要的X509规范的证书. 之前的博文,介绍过用openssl创建证书,并 ... 
- MQTT研究之EMQ:【EMQX使用中的一些问题记录(4)】
		最近比较忙,有些关于EMQ的使用问题,没有时间记录了,趁这个周末抽点时间,将最近遇到的,觉得比较有价值的一个问题,分享给大家吧. 这里是针对前面的一篇博客,做的一个深入研究,关于订阅系统总线判断设备上 ... 
- MQTT研究之EMQ:【基础研究】
		EMQ版本V2, emqttd-centos7-v2.3.11-1.el7.centos.x86_64.rpm 下载地址:http://emqtt.com/downloads/2318/centos7 ... 
- MQTT研究之EMQ:【EMQX使用中的一些问题记录(2)】
		我的测试环境: Linux: CentOS7 EMQX:V3.2.3 题外话: 这里主要介绍Websocket的支持问题. 对ws的支持比较正常,但是对wss的支持,调了较长的时间,没有成功. Jav ... 
- MQTT研究之EMQ:【EMQX使用中的一些问题记录(1)】
		issue 1. EMQX的共享订阅 EMQX是一个非常强大的物联网通信消息总线,基于EMQX开展应用开发,要注意很多配置细节问题,这里要说到的就是共享订阅以及和cleanSession之间的关系问题 ... 
随机推荐
- NVM 安装(window/mac/linux)
			一.window版 1.nvm-windows下载 [下载地址](https://github.com/coreybutler/nvm-windows/releases),下载 nvm-setup.z ... 
- postgresql基于备份点PITR恢复
			实验目的: 01.基于备份点直接恢复数据库 02.基于备份点后续增量wal日志恢复到特定的时间点 实验环境: centos7 postgresql9.5 01.安装postgresql9.5 post ... 
- 解决网页刷新时,隐藏div元素闪现问题
			最近项目遇到一个问题,需要对一个div中的元素设置根据不同的情况进行显示和隐藏. 因为默认该div是显示的,所以在刷新页面的时候,会先加载这个div进行显示,加载完成后又执行到 hide() 方法,使 ... 
- linux lvm管理基础教程
			linux lvm管理基础教程 本人是在redhat7.x系统上亲测lvm管理功能,至于文中所受的CentOS 6 没有亲自试过. 本文来自:https://geekpeek.net/lvm-phys ... 
- 行业——5G
			1. 概述 1.1 定义 5G:5th Generation Mobile Networks / 5th Generation Wireless Systems,第5代移动通信技术 1.2 商标 ... 
- Spring Boot属性配置文件:application.properties 详解
			学习资料 网址 官方说明文档 https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-pro ... 
- iis7设置http跳转https实测可用
			前面ytkah和大家聊了Apache设置http如何301到https,现在我们说说iis7设置http跳转https,因为还是有很多人在用iis服务器.首先要先安装url rewrite modul ... 
- eclipse 中的注释 快捷键  多行注释快捷键   单行注释快捷键
			Eclipse 中的两种注释方法: (1)多行注释(2)单行注释 一. 多行注释快捷键 1:添加注释Ctrl+Shift+/ : 添加/* */注释 示例:选中代码块后按下快捷键即可 /* fl ... 
- Ruby Raise rescue
			ruby1.9以上,retry只能支持在rescue里面使用,不支持在block里面用:你要去用ruby1.8 rescue使用代码例子 # -*- coding: UTF-8 -*- n = 0 b ... 
- RxSwift 在本质上简化了开发异步程序
			RxSwift 是一个组合异步和事件驱动编程的库,通过使用可观察序列和功能样式运算符来,从而允许通过调度程序进行参数化执行. RxSwift 在本质上简化了开发异步程序,允许代码对新数据作出反应,并以 ... 
