<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>MQTT on Hacper&#39;s Blog</title>
    <link>https://hacperme.com/tags/mqtt/</link>
    <description>Recent content in MQTT on Hacper&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh</language>
    <lastBuildDate>Fri, 09 Sep 2022 22:09:22 +0800</lastBuildDate>
    <atom:link href="https://hacperme.com/tags/mqtt/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>MQTT 应用笔记</title>
      <link>https://hacperme.com/posts/notes/20220909_mqtt_notes/</link>
      <pubDate>Fri, 09 Sep 2022 22:09:22 +0800</pubDate>
      <guid>https://hacperme.com/posts/notes/20220909_mqtt_notes/</guid>
      <description>cleansession 与 Qos 的配置关系 cleanSession的语义 cleanSession标志是MQTT协议中对一个消费者客户端建立TCP连接后是否关心之前状态</description>
      <content:encoded><![CDATA[<h2 id="cleansession-与-qos-的配置关系">cleansession 与 Qos 的配置关系</h2>
<ol>
<li>
<p>cleanSession的语义</p>
<p><strong>cleanSession</strong>标志是MQTT协议中对一个消费者客户端建立TCP连接后是否关心之前状态的定义，与消息发送端的设置无关。具体语义如下： - <strong>cleanSession=true</strong>：消费者客户端再次上线时，将不再关心之前所有的订阅关系以及离线消息。（服务器不保存之前的topic历史关系和不存储离线消息，客户连接需要重新订阅topic且不会收到离线消息） - <strong>cleanSession=false</strong>：消费者客户端再次上线时，还需要处理之前的离线消息，而之前的订阅关系也会持续生效。（服务器会保存之前的topic订阅关系，客户端连接之后不需要重新订阅topic，且会收到离线消息）</p>
</li>
<li>
<p>cleanSession 与 Qos 配置的关系</p>
</li>
</ol>
<table>
<thead>
<tr>
<th style="text-align:left">QoS级别</th>
<th style="text-align:left">cleanSession=true</th>
<th style="text-align:left">cleanSession=false</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">QoS0</td>
<td style="text-align:left">无离线消息，在线消息只尝试推一次。</td>
<td style="text-align:left">无离线消息，在线消息只尝试推一次。</td>
</tr>
<tr>
<td style="text-align:left">QoS1</td>
<td style="text-align:left">无离线消息，在线消息保证可达。</td>
<td style="text-align:left">有离线消息，所有消息保证可达。</td>
</tr>
<tr>
<td style="text-align:left">QoS2</td>
<td style="text-align:left">无离线消息，在线消息保证只推一次。</td>
<td style="text-align:left">有离线消息，所有消息保证只推一次。（也需要服务器支持该功能才有效）</td>
</tr>
</tbody>
</table>
<h2 id="发布订阅消息不同-qos-配置的作用交互流程及其特点">发布、订阅消息不同 Qos 配置的作用、交互流程及其特点</h2>
<ol>
<li>mqtt 消息发布者和消息订阅者之间的 Qos 配置关系</li>
</ol>
<p>MQTT发布消息QoS保证不是端到端的，是客户端与服务器之间的。订阅者收到MQTT消息的QoS级别，最终取决于发布消息的QoS和主题订阅的QoS。</p>
<table>
<thead>
<tr>
<th>发布消息的 QoS</th>
<th>主题订阅的 QoS</th>
<th>接收消息的 QoS</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>2</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>2</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>2</td>
</tr>
</tbody>
</table>
<ol start="2">
<li>不同 Qos 消息在消息发布者、服务器、消息订阅者之间的交互流程</li>
</ol>
<ul>
<li>Qos0 的交互流程</li>
</ul>
<p><img loading="lazy" src="https://github.com/hacperme/picx_hosting/raw/master/20210507/mqtt-qos0-2022-08-11-1819.3pyah3ua5t00.png" alt="mqtt-qos0-2022-08-11-1819"  />
</p>
<p>特点：</p>
<ol>
<li>没有重发机制，消息订阅者不一定能收到消息。</li>
</ol>
<ul>
<li>Qos1的交互流程</li>
</ul>
<p><img loading="lazy" src="https://github.com/hacperme/picx_hosting/raw/master/20210507/mqtt-qos1-2022-08-11-1819.1qw727hrf20w.png" alt="mqtt-qos1-2022-08-11-1819"  />
</p>
<p>特点：</p>
<ol>
<li>有重传机制，消息发送者PUBLISH消息之后，在特定时间之内没有收到 PUBACK 确认消息，就会触发重传。</li>
<li>重传对象为 PUBLISH 报文，重传动作在发送端进行。</li>
<li>一般重传有次数限制，比如腾讯云 iot 平台，3s 内没有收到ACK触发重传，重传次数最大为3次。</li>
<li>由于有重传，在应用层有可能会收到重复消息，需要根据应用场景判断要不要增加消息去重处理。</li>
</ol>
<ul>
<li>Qos2的交互流程</li>
</ul>
<p><img loading="lazy" src="https://github.com/hacperme/picx_hosting/raw/master/20210507/mqtt-qos2-2022-08-11-1819.72y1jwbvcd80.png" alt="mqtt-qos2-2022-08-11-1819"  />
</p>
<p>特点：</p>
<ol>
<li>Qos2 不一定服务器都支持。</li>
<li>Qos2 发送消息，发送端和接收端需要个发两次报文才完成整个流程，共4次报文传输，流程更复杂，开销相对较大。</li>
<li>重传动作发生在消息发送端，重传对象有 PUBLISH 报文和 PUBREL 报文。</li>
<li>虽然有重传，但是应用层不会收到重复消息。</li>
</ol>
<h2 id="搭建-mqtt-测试服务器">搭建 mqtt 测试服务器</h2>
<ul>
<li>搭建 emqx</li>
</ul>
<p>推荐使用 docker 的方式，部署简单，一条命令搞定。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx:latest
</span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded>
    </item>
  </channel>
</rss>
