ソースMQTTバージョンのアップグレードプロセスと決意
それは、私がインターネットMQTT上の記事を見つけたこの記事は、導入書く理由についてまず話が小さすぎると、それはまた、この比較的低い周波数を使用することができます!彼が必要としている何人かの人々を助けるために、いくつかの貢献をすることを望んで、この記事を書いたので、あまりにも少しの方法と手段を見つけるとアドレッシングの問題があります。
予想と一直線になるまで、アップグレードバージョン1.2.1の間に発生するトラブルシューティングの問題、ステップ調査、問題の最終的なポイントによって工程を経てソースコードに、元のバージョン1.2.0過程で現れたもの主な問題MQTTレコード。
<! - https://mvnrepository.com/artifact/org.eclipse.paho/org.eclipse.paho.client.mqttv3 - > < 依存> < groupIdを> org.eclipse.paho </ groupIdを> < たartifactId > org.eclipse.paho.client.mqttv3 </ たartifactId > < バージョン> 1.2.1 </ バージョン> </ 依存関係>
MQTTは、ビルドすると、SSL証明書は、このブログを参照することができます。https://www.cnblogs.com/yueli/p/7490453.html 慎重にこのに記載されていません
QoSの導入
QoSをいくつかの意味を初めて目の冒頭では、ヒューズのための問題があります
-
伝送にQoS = 0アップ
発行元、すなわち、送信が破棄され、サーバ(ブローカ)にメッセージをパブリッシュ。いいえ確認メッセージが、私は相手が受信されたかどうか知りません。ネットワークレベル、小さな圧力伝達
-
= 1つの少なくとも一つの送信のQoS
それが削除されたように、出版社は、サーバーにメッセージのPUBACKを受けた後のメッセージ、そして加入者を削除させて戻って出版社にPUBACK情報に保存したメッセージ、サーバー(ブローカー)メッセージを、サーバー(ブローカー)加入者サーバ(ブローカー)にPUBLISHを受信を発表しましたメッセージ。それが失敗した場合、一定の期間にわたって受信何ら確認情報がない、送信者はDUPヘッダが1に設定されているだろう、とサービスに到達するために一度、その後、少なくとも、もう一度メッセージをメッセージを送信します。このようなネットワークの遅延やその他の問題として、発行元の繰り返しは、メッセージを送信するために、加入者は、メッセージを複数回繰り返すようにサブスクライブ
-
QoS = 2つのみ送信
実際には、QoSは= 2がちょうど1に基づいて足を取り除くためにラッシュをした、発行者は、以上の確認メッセージ、およびより後にサーバにパブリッシュニュースMSGIDキャッシュ情報の重いを繰り返します、。サブスクライバサーバの後、確認メッセージよりも多くのことをPUBLISH。
3例との違い
0保存されていないメッセージは、再送メカニズムが存在しない、サーバーがメッセージを保存しているどのような、1およびパブリッシャーの2と分からない、出版社は、サーバがPUBLISHた後に再送信メカニズム、確認機構PUBACKがありますが、サーバー2キャッシュは複数のメッセージの繰り返し送信を防止するために、重複除外機能を提供する機能をMSGID、及びメッセージは、肯定応答機構を受け取りました。加入者のここでの導入が、理解して行くために、より興味を持って。
MQTT1.2.1バージョン新興問題
問題の説明:より多くの場所は、通常のQoS = 0の形でMQTT通信プロジェクトを使用するので、この時間は、それは常に、あまりにも多くのエラーが進行(32202)で公開するソースコードのエラーを見て場所を思い出させるました
ここからあなただけのmaxInflightも役に立たないmaxInflightを高めるための試みによって引き起こされた最大値を超えますが、遅延誤差時間actualInFlight独自の判断を設定することができます
トラブルシューティングのプロセス
まず、インターネットは確かにバディを満たしてい、同様の問題があるかどうかを確認するために、検索、ブログのアドレス:https://blog.csdn.net/lblblblblzdx/article/details/81159478 この記事では、私のブロガーのおかげで多くの援助を与えたが、最終的な解決策は非常に良いではありません。
ソース論理トラックリリースプロセス
最初のステップ:プロセスが公開
// 1 公共IMqttDeliveryToken公開(文字列トピック、MqttMessageメッセージ、オブジェクトuserContext、IMqttActionListenerコールバック) // 2 公共 ボイドsendNoWait(MqttWireMessageメッセージ、MqttTokenトークン) // 3 ボイドでinternalSend(MqttWireMessageメッセージ、MqttTokenトークン) // 4 公共 ボイド送信(MqttWireMessageメッセージ、MqttTokenトークン)
ステップ2:すべてのタイプのQosを、最上位の親で構成されたパブリッシュメッセージのデフォルト設定MSGID = 0
第三段階:メッセージはsendメソッドでは、主要な取引をしました
ステップ4:QoSを私たちはHashtableに置かれ、実際には、すべてのキャッシュされたトークンここでこの場所のニュースを公開することと、QoS上記の説明によると、関係なく、どのレベル
これらの工程では、良いニュースは、すでにロック機構を説明することはあまりないような、非同期に送信する準備ができて、キャッシュされています
ステップ5:彼は、接続の流れを聞くために始めたとき、非同期送信には、それは完全にクライアントのリンクに主です
1 //1 2 public IMqttToken connect(MqttConnectOptions options) 3 4 //2 异步链接 5 ConnectActionListener connectActionListener = new ConnectActionListener(this, persistence, comms, options,userToken,userContext, callback, reconnecting); 6 connectActionListener.connect(); 7 8 //3 客户端的通信链接,包括发送和接收 9 ClientComms.connect(options, token); 10 11 //4 个人理解是 将通信信息塞进线程池中,分别开启发送和接收的线程处理 12 ConnectBG conbg = new ConnectBG(this, token, connect, executorService); 13 conbg.start();
第六步:在ConnectBG的run中 new CommsSender. start线程run中while循环发送的信息流程,一直发送消息中
第七步:在notifySent的方法中判断Qos = 0 的作出了判断及操作
这些差不多就是发布过程的主题流程结构,了解这些才会知道让你解决问题更加的容易
问题点
在上面的第六步的图中黄色箭头指出了问题出现的点,主要是在大数据量高并发的时候,因为在Qos = 0 的时候,在tokens(Hashtable)中的key一直是0,默认初始化。后面的流程中并没有改变过,在黄色那块tokenStore.getToken 在发送之后才remove数据,但是多条数据高并发的时候,在remove数据之后,后一条在get的时候会出现空的状况,不发送信息,导致actualInFlight没有减,一直增加,一定时间后就会超出最大值。Qos =1 、2 是不会发送这样的情况,因为他们的messageId是唯一的。
解决办法
- 将Qos设置为1 (这是网上主流的解决办法,但是这个太耗费资源问题,在我看来只是规避问题点而已)
- 升级MQTT版本1.2.1 (这个版本解决了刚才说的bug)
- 也可以想想在不升级版本的情况下如何去改善这个问题,重写那些类可以实现···
解决过程
既然说了第一种解决办法不是很赞同,那就直接进去第二种办法吧。升级到1.2.1版,时间:Feb, 2019,但是在升级版本的时候又出现了一些问题,因为改动还是有点多的。
接下来说说1.2.1版本的改动了什么呢
首先主要改动的是在Qos = 0 的不放入tokens中了,首先想到的是不会get到了,也不用担心重复了,直接从集合pendingMessages中拿
然后从信息的自身获取数据的token,获取不到再去tokens中拿
以上两个就是主要解决这个高并发冲突的原因
跳入另一个坑中···
为什么这么说呢,在我们开发的意识中,升级版本怎么也要向下兼容吧,那就顺其自然的换个版本就完事了,结果一跑起来,一堆红色的出现,那心情···我太南了。以我的性子,就是不能惯着她,继续深挖为什么,既然坑已经有了,就不怕有多深。
另一个坑的过程
第一时间也是上网搜一些为啥,大家的解决也差不多,都是SSL验证出现问题,但是解决方案也是五花八门
解决方案
第一种:设置系统属性 类似这样的文章 https://blog.csdn.net/hxpjava1/article/details/77937026
第二种:有看了一些代码了,就是重写X509TrustManagerImpl,绕过SSL的验证,试过有用,类似这样的文章 https://blog.csdn.net/iverson_AL/article/details/100669777
第三种:再深入看一些源码,你会看到会什么会报错,为什么会验证,主要是你的属性没有设置好,采用了默认验证导致
解决过程
这里主要说一下解决的过程,如何从这些网络文章种找出适合自己的出路。
首先 第一种我就不咋喜欢,动不动就设置了系统全局属性,第二种方案,有两种可能性,一是这个api真的有问题或是不符合自己的项目需要重写代码逻辑结构,二是在不了解的情况下直接绕过验证。我在测试第二个的时候就是如此只是稍微看了一下源码,没有深入看进去,试了一下,果真可以实现我想要目的。
但是过后又想了一下,不该如此,既然开源出来的东西,不可能如此**,应该会有什么地方可以简单设置一下的。既然有这个想法就一直深入探究下去,果不其然,真相出来了。
在1.2.1版本中MqttConnectOptions 的httpsHostnameVerificationEnabled属性默认true,导致不是Https的被验证不通过导致的,也可能MQTT开发人员安全意识很强,在1.2.0版本中没有这个概念存在,所以在版本升级的时候需要加上MqttConnectOptions.setHttpsHostnameVerificationEnabled(false);
以下源码查看的过程
若是有Https证书是不会有问题的。
总结一下
其实很简单的问题,居然整的时候那么复杂,原因是我们不够强,面对源码的时候还是比较害怕的,还有比较懒吧。
整个过程比较繁琐,啰嗦吧,耐心看下来,应该有收获。
操作总结:
-
- 升级MQTT版本1.2.1
- 若不是https的需要设置为false
- 不要走,跑起来
扩展点及疑惑地点可以供参考
转载请注明出处 https://www.cnblogs.com/zhouguanglin/p/11986446.html