本文由逍遥子撰写,转发请标注原址:

http://write.blog.csdn.net/postedit/21463965

3.1.2、使用订阅树发布消息

在Mosquito程序中,消息发送过程主要通过遍历订阅树来完成,具体为:递归遍历订阅树找到指定的订阅列表,并将消息挂到订阅列表中的每个contextg的消息队列中,如果消息的retain字段被设置为1,则mosquitto还需要保存此消息,以备新订阅的客户端可以立即收到上次发送的消息;另外,发往系统topic的消息也会被mosquitto保存起来。上述消息发送过程主要通过函数mqtt3_db_messages_queue来完成。另外,根据mqtt协议,mosquitto还对#和+两个通配符提供支持,通配符#可放在topic的第一级之外的其他topic片段中,用以表示匹配所有后续topic片段,例如:a/# 可以匹配a/b、a/b/c、a等,但是#需要独立为一个分级才能起作用,即a/b#c/d这种情形不被支持。通配符用“+”用以匹配一级topic,例如a/+/c可以匹配a/b/c、a/d/c但是不能匹配a/d/f。另外消息的qos等级不同,mosquitto对消息的发送过程也不一样。

例如,在如图3-8所示的订阅树中, 以qos为0时发布消息为例,消息发布时通过mqtt3_db_messages_queue完成。

图3-8 订阅树的遍历

向topic:year/month/events1发送消息,其发送过程为:

1) 将topic按照”/”分成topic片段:year、month、event1s三个topic片段;该topic分片过程在函数mqtt3_db_messages_queue中完成。

2) 遍历订阅树根的子节点,并根据第一级topic分片的类型是否为“$SYS”选择业务子树还是系统子树进行递归遍历。同时还需判断消息中retain标识位是否设置为1,如果是,则需将该topic的所有后续分片加入到订阅树中,经过该添加之后,订阅树中就存在了该topic,这一添加topic片段的过程在函数_sub_add中完成。

3) 递归遍历子树,每次选取一个topic分片,将之与当前的节点的所有子节点进行比较,以找到匹配的节点,然后继续递归匹配下去,递归处理过程主要由函数_sub_search完成;

4) 当匹配完所有的topic分片或者遇到topic分片为#时,进行如下处理:

5) 当消息的retain字段被设置为1之后,需要将该消息持久化,即保存下来,以备有新订阅者订阅该topic的消息时可以收到上一条消息。

6) 遍历当前订阅树节点的订阅列表,将消息挂载所有订阅者的消息队列中,此过程通过函数mqtt3_db_message_insert完成。

mosquitto消息发送过程中所调用函数的关系如下图3-9所示:

图3-9          消息发布函数调用关系图

3.1.3、从订阅树中删除订阅客户端

在Mosquitto程序中,客户端可以向mosquitto服务器发送取消对某个topic的订阅请求,服务器收到请求之后,将从订阅树中删除该客户端,该过程需要遍历订阅树以找该topic在订阅树中的位置,进而获得到订阅该topic的订阅列表,从而将其从订阅树中删掉。该过程与发送消息类似,首先将topic进行分片,然后根据topic片段遍历订阅树找到该topic的订阅列表;然后遍历订阅列表,将该客户端从订阅列表中删除。

取消订阅的函数调用关系如图3-10所示。

图3-10 取消订阅函数调用关系

3.1.4、订阅树机制的优缺点分析

Mosquito程序采用订阅树形式维护客户端之间的订阅与发布消息,这种方式优点是逻辑清晰,便于开发和维护。缺点是其遍历过程效率较低。同时,程序中存在很多对订阅树的遍历过程:订阅、发布消息、取消订阅等,在客户端数量增加时,该功能对效率的影响将更为明显。

因此,在mosquitto的实际应用中很难支持5万以上的客户端,尤其在客户端网络状态不好时,其断开重练操作将非常频繁,这样也造成大量对订阅树的遍历操作,从而严重影响mosquitto的效率。

3.2、mosquitto的消息收发机制

Mosquito最主要的功能就是对消息的正确接收、维护和转发,因此其消息的接、收功能非常重要。Mosquitto的消息收发主要通过poll机制来完成。

mosquitto源码分析(四)相关推荐

  1. ABP源码分析四十七:ABP中的异常处理

    ABP源码分析四十七:ABP中的异常处理 参考文章: (1)ABP源码分析四十七:ABP中的异常处理 (2)https://www.cnblogs.com/1zhk/p/5538983.html (3 ...

  2. 【投屏】Scrcpy源码分析四(最终章 - Server篇)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  3. gSOAP 源码分析(四)

    gSOAP 源码分析(四) 2012-6-2 邵盛松 前言 本文主要说明gSOAP中对Client的认证分析 gSOAP中包含了HTTP基本认证,NTLM认证等,还可以自定义SOAP Heard实现认 ...

  4. Spring 源码分析(四) ——MVC(二)概述

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) from:Spring 源码分析(四) --MVC(二)概述 - 水门-kay的个人页面 - OSCHINA ...

  5. mosquitto源码分析

    mosquitto源码分析 一.mosquitto简介 二.主要目录 三.客户端源码 结构体 重要函数 1.mosquitto_lib_init 2.mosquitto_new 3.mosquitto ...

  6. 【转】ABP源码分析四十七:ABP中的异常处理

    ABP 中异常处理的思路是很清晰的.一共五种类型的异常类. AbpInitializationException用于封装ABP初始化过程中出现的异常,只要抛出AbpInitializationExce ...

  7. 【转】ABP源码分析四:Configuration

    核心模块的配置 Configuration是ABP中设计比较巧妙的地方.其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配 ...

  8. 谷歌chrome浏览器的源码分析(四)

    上一次说到需要调用这个OpenURLFromTab函数,那么这个函数是做什么的呢?从名称上可能猜到它是打开网页,但是是从目前TAB页里打开呢?还是新建一个?或者使用每个TAB页一个进程呢?这些疑惑,只 ...

  9. 【转】ABP源码分析四十六:ABP ZERO中的Ldap模块

    通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供Defaut ...

  10. 【转】ABP源码分析四十五:ABP ZERO中的EntityFramework模块

    AbpZeroDbContext:配置ABP.Zero中定义的entity的Dbset EntityFrameworkModelBuilderExtensions:给PrimitiveProperty ...

最新文章

  1. ARP欺骗防御工具arpon
  2. Firefox无法加载12306自家证书
  3. Jenkins拾遗--第三篇(用户权限管理)
  4. BJUI选择时间后点击导出提示未选择时间
  5. 【转】C# 正则表达式 使用介绍
  6. 【uni-app】 rich-text 中图片溢出
  7. exec go 重启_如何用 Go 实现热重启
  8. B树、B+树到底是什么?
  9. Jar 包依赖冲突排查思路和解决方法
  10. 1537 学生干部虚基类
  11. docker 镜像源_前端 Docker 镜像体积优化
  12. 机械硬盘提示:使用驱动器中的光盘之前需要将其格式化怎么办?
  13. 2022-2028全球与中国卡个性化设备市场现状及未来发展趋势
  14. 查看详细Windows VISTA 或Windows 7激活状态
  15. python中encode用法_Python中encode()方法的使用简介
  16. 画笔Paint及模拟画图工具
  17. 【Pygame实战】强烈推荐:教你用百行代码编写一款《小蜜蜂历险记》不信?来看看(玩儿嗨了~)
  18. Pycharm正版2022.2.2 | 官方翻译插件更新tkk失败解决
  19. Internet Download Manager v6.41.3中文特别版IDM下载器免费下载
  20. 几种主要的神经网络----全连接神经网络、前馈神经网络、卷积神经网络、循环神经网络

热门文章

  1. linux 网络命令 dns,[LN_03] Linux网络环境查看(网卡|路由|DNS|IP)、网络测试命令(端口探测|路由跟踪|抓包|ssh连接)...
  2. 油猴脚本使用waitForKeyElements报错eslint: no-undef - `waitForKeyElements` is not defined
  3. 肺功能曲线图怎么看_QQ或将推出已读功能?!你怎么看?| 微博报
  4. 软件架构设计_软件架构设计的三个维度,软件架构师需要知道的点,了解一下吧...
  5. 什么是静态,静态有什么作用呢?
  6. java 反射调用set方法_java反射调用set方法时如果让参数做自动类型转换
  7. 在matlab中function,Matlab中function函数使用操作方法
  8. ipfs操作mysql_IPFS 使用入门
  9. 前端如何查看音频的长度_Android音频可视化
  10. 提高linux运行速度,提高Linux操作系统的运行速度