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

http://blog.csdn.net/houjixin/article/details/46413583

http://houjixin.blog.163.com/blog/static/3562841020155835146428/#

原版的mosquito在移动互联网情况下,其性能不高。实际运营时一个mosquito实例能支持2万连接就不错了。mosquitto在网络状态不好的情况下,随着用户量的上升,其对cpu消耗将大幅添加,基本的CPU主要消耗在下面几个方面:

(1)Poll机制的缺陷。

(2)Mosquitto内部订阅树机制的缺陷;

(3)其它消息发送,数据结构管理方面的缺陷;

本节将针对这些缺陷提出对应的优化策略和方法。

7.1、poll优化

7.1.1、优化原因

在mosquitto原始程序中,核心处理流程是对全部的socket进行监听处理。该部分功能主要使用poll来完毕,可是它的效率较差,尤其当在线活动用户较少的情况下,性能更差,这一定程序上影响了mosquitto性能,epoll效率的低下主要是因为以下3个原因:

1)  poll在每次监听port之前,都须要又一次注冊全部须要监听的socket;

2)  poll返回的结果中,仅仅会改动有事件发生的socket相应的poll结构体,因此,在使用时须要对全部注冊的socket相应的poll结构体进行扫描,才干推断出那些socket有事件发生。

3)  在内部实现上,poll须要查询全部注冊的socket以确定其是否有事件发生。

Poll的上述问题是是其自身实现方式造成的,非常难进行优化。针对poll的这些问题,linux实现了一个更高效的实现方式:epoll,相对而言。epoll则不须要poll这些复杂操作,epoll具有下面3个长处:

1)  epoll中,仅仅须要将被监听的socket注冊进epoll一次。兴许epoll就会监听它,而不须要每次监听之前又一次注冊。

2)  epoll返回结果包括了全部有事件发生的socket,因此处理过程中,扫描全部这些有事件发生的socket就可以,而不须要扫描全部注冊的socket。

3)  在内部实现上,epoll不需查询全部注冊的socket,它内部是:全部有事件发生的socket自己将自己挂载epoll的就绪队列上,epoll仅仅需返回就绪队列中的socket就可以。

因此,本次优化首先选择对poll进行优化。主要使用epoll替换poll,以提升系统的运行效率。

7.1.2、优化方案:

Mosquitto中对poll的使用主要集中在文件loop.c的在函数mosquitto_main_loop中,因此本次改动将使用一个新的函数epoll_mosquitto_main_loop来取代它。另外,在用法上,epoll的监听函数epoll_wait返回全部就绪socket,而mosquitto程序中须要知道socket相应的conetxt才干完毕业务处理,因此,为了支持epoll,须要添加一个hash表t_fd2context来完毕socket到其相应conetxt的映射。

Mosquito的核心处理逻辑主要在函数mosquitto_main_loop中,该函数主要完毕了下面功能:

1)  更新系统topic的信息。

2)  将全部监听socket放入poll结构体pollfds中。

3)  扫描全部context,完毕下列工作:

假设context有消息发送,则将消息依照mqtt协议发送出去;

检查context是否超时;

将context的socket放入poll的结构体pollfds中。

4)  扫描全部conetxt,假设context中有消息,则更新消息的时间戳。

5)  调用poll。轮询poll的结构体pollfds全部的socket;

6)  处理poll的结果,需完毕以下两个工作:

扫描全部的context,查看其相应的socket是否有事件发生,假设有,则进行读写处理。

处理全部的监听socket,假设有新的连接进入。则为之创建相应的context

7)  进行又一次载入配置文件等可选择操作。

在poll的工作过程中。上述操作将会循环运行,使用epoll优化之后的mosquitto的核心流程将会有所改变,为:

1)  向epoll中注冊监听port。该步骤在循环之前运行;以下2)之后的步骤将会放入循环运行。

2)  更新系统topic的信息。

3)  依据策略扫描所有context。完毕以下两个工作:

回收context,并将该context的索引放入空暇索引数组中;

检查超时,假设超时,则将该context与其socket的映射从hash表t_fd2context中删除。

4)  调用epoll的epoll_wait函数获取全部的就绪socket;

5)  对全部的就绪socket进行处理,主要完毕以下的工作:

假设就绪的socket是监听接口,则对监听接口进行处理。为每一个新进来的业务socket建立context,并将其注冊进epoll;

假设不是监听socket,则从socket到cotext的hash表t_fd2context中找到该socket相应的context。然后完毕相应的处理,假设找不到。则断开此socket的连接。

6)  进行又一次载入配置文件等可选择操作。

因为epoll和poll的工作方式不同,因此须要对上述流程进行改动以使其能适应epoll的要求,主要改动之处包含:

1)  Socket注冊方式;poll中每次循环都须要将socket又一次注冊入poll。而epoll仅仅须要開始注冊一次就可以;

2)  返回结果处理。poll中须要对所有注冊的socket结构体进行扫描,才干推断某个socket是否有数据处理;epoll直接返回就绪socket,因此无需所有遍历注冊的socket结构体。

3)  添加socket到相应context的映射,因为epoll直接返回就绪socket,而mosquitto中须要找到该socket相应的context才干进行上层应用的处理,因此须要添加一个hash表完毕socket到context的映射。

4)  改动消息发送部分的功能

7.1.3、详细实现

Epoll的优化也採用原来的单线程结构,并使用一个大循环“while”完毕对任务的处理,该大循环被放在函数epoll_mosquitto_main_loop中,该函数与函数mosquitto_main_loop(该函数是使用poll时的主要业务处理)的參数全然同样,并在函数mosquitto_main_loop中调用epoll_mosquitto_main_loop。因此程序中原来调用poll的主业务处理函数mosquitto_main_loop的地方将会被转向调用epoll的主业务处理函数epoll_mosquitto_main_loop。从而实现对epoll功能的调用,系统的流程例如以下图5-1所看到的。

图7-1 使用epoll之后的系统流程图

1、socket注冊

epoll在使用时仅仅需将待监控的socket增加一次就可以。这一点与poll在用法上有区别。在mosquitto程序中,须要epoll监控的socket包含监听socket和业务socket;Socket的注冊过程由函数reg_socket完毕,注冊socket的监听类型为EPOLLIN,採用默认的水平触发模式。

1)  监听socket。此类型socket负责接收client的新连接。比如程序中默认的1883port相应的socket,client将使用该port连接到mosquitto。在函数epoll_mosquitto_main_loop的主循环開始直接之前完毕注冊,仅仅进行一次注冊,兴许不再反复注冊。

2)  业务socket,该类型socket负责完毕client和mosquitto之间的业务数据的传输;业务socket将在新连接进入时完毕注冊,此过程在函数epoll_loop_handle_result中完毕。

2、Epoll的事件处理

Epoll事件处理将由函数epoll_loop_handle_result来完毕,在该函数中将循环扫描epoll返回的全部就绪socket。并对每一个就绪的socket进行处理,处理的方式为:

1)  假设为监听socket,则首先调用mqtt3_socket_accept函数对新连接进来的socket进行处理,处理过程包含:为socket创建相应的context等。其次将socket注冊入epoll。

2)  假设监听port为业务socket,则读取该结构体上的数据。然后对数据进行处理。

图7-2 epoll事件处理流程

Mosquito的优化——epoll优化(七)的更多相关文章

  1. SQL Server 优化存储过程的七种方法

    原文:SQL Server 优化存储过程的七种方法 优化存储过程有很多种方法,下面介绍最常用的7种. 1.使用SET NOCOUNT ON选项 我们使用SELECT语句时,除了返回对应的结果集外,还会 ...

  2. spark优化之优化数据结构

    概序: 要减少内存的消耗,除了使用高效的序列化类库以外,还有一个很重要的事情,就是优化数据结构.从而避免Java语法特性中所导致的额外内存的开销,比如基于指针的Java数据结构,以及包装类型. 有一个 ...

  3. c/c++性能优化--- cache优化的一点杂谈

    之前写了一篇关于c/c++优化的一点建议,被各种拍砖和吐槽,有赞成的有反对的,还有中立的,网友对那篇博客的的评论和吐槽,我一个都没有删掉,包括一些具有攻击性的言论.笔者有幸阅读过IBM某个项目的框架代 ...

  4. [原]Android开发优化-Adapter优化

    ListView作为Android开发中使用频率最高的一个控件,保证ListView的流畅运行,对用户体验的提高至关重要.Adapter是ListView和数据源之间的中间人,当每条数据进入可见区时, ...

  5. SqlServer 数据库引擎优化顾问优化数据库

    现在一直在做的项目,数据量相对也不小,开始的时候没有觉得,因为是刚开始,数据量还很小,在程序使用过程中速度还挺快,但是随着数据量的不停的增长,发现程序越来越慢,甚至出现了超时的问题,因此要对程序和数据 ...

  6. Mysql优化之优化工具profiling

    程序员的成长之路 2016-11-23 22:42 Mysql优化之优化工具profiling 前言 mysql优化技术: mysql优化不是做一个操作就可以的优化,它包含很多的细节,需要一点一点的优 ...

  7. QRowTable表格控件(四)-效率优化之-优化数据源

    目录 一.开心一刻 二.问题分析 三.重写数据源 1.自己存储数据 2.重写data接口 四.比较 五.相关文章 原文链接:QRowTable表格控件(四)-效率优化之-优化数据源 一.开心一刻 一程 ...

  8. 知识点整理-mysql怎么查看优化器优化后的sql

    背景 1.新建两张表 CREATE TABLE t1 (m1 )); CREATE TABLE t2 (m2 )); 2.插入些数据 INSERT INTO t1 VALUES(, , , 'c'); ...

  9. Android 性能优化 ---- 启动优化

    Android 性能优化 ---- 启动优化 1.为什么要进行启动优化 一款应用的第一印象很重要,第一印象往往决定了用户的去留.打开一款应用,如果速度很快,很顺畅,那么很容易让人觉得这款应用背后的技术 ...

随机推荐

  1. Jasperreport+ireport 实践操作及web应用

    Jasperreport+ireport 实践操作及web应用   学习完jasperreports+ireport,给我感觉深刻,不仅掌握了报表开发技术,还掌握了怎样在web中生成pdf,xls,r ...

  2. Unreal Engine 4 C++ 为编辑器中Actor创建自己定义图标

    有时候我们创建场景的时候,特定的Actor我们想给它一个特定的图标,便于观察.比方这样: 实现起来也非常easy.须要编写C++代码: 我们创建一个Actor,叫AMyActor.它包括一个Sprit ...

  3. invalidate

    转载请注明出处:                前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时真挚地向渴望了解      A ...

  4. hdoj--1171--Number Sequence(KMP)

    Number Sequence Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. 存储概念解析:NAS与SAN的区别

    目前存储网络技术领域中的两个主旋律是SAN(存储区域网络)和NAS(网络连接区域存储),两者都宣称是解决现代企业高容量数据存储需求的最佳选择. 正如在餐厅就餐时大厨不会为您传菜,跑堂不会为您烹制鲜橙烩 ...

  6. Core篇——初探Core配置管理

    文章目录 1.命令行配置 2.Json文件配置 3.配置文件文本至C#对象实例的映射 4.配置文件热更新 5.总结 命令行的配置 我们首先来创建一个.net core 的控制台项目,然后引入.net ...

  7. input 框输入数字相关

    input框限制只能输入正整数,逻辑与和或运算 有时需要限制文本框输入内容的类型,本节分享下正则表达式限制文本框只能输入数字.小数点.英文字母.汉字等代码. 例如,输入大于0的正整数 代码如下: &l ...

  8. 使用pgpool管理数据库集群故障的问题

    pgpool如何选举master角色 在pgpool启动的过程中通过对 pgpoo.conf配置文件中的数据库节点条目信息,对集群中的数据库节点从0开始一个个的遍历,并发送SQL语句“select p ...

  9. css——overflow

    Overflow:属性规定当前内容溢出元素框时发生的事情 1.当内容过多,元素框溢出 1)hidden:隐藏超出部分(overflow: hidden;) 2)auto:有下拉滚动条(overflow ...

  10. Day 07 -02 拷贝 浅拷贝 深拷贝

    必考 存一个值还是多个值 一个值:整型/浮点型/字符串 多个值:列表/元祖/字典/集合 有序or 无序 有序:字符串/列表/元祖 无序:字典/集合 可变or 不可变 可变:列表/字典/集合 不可变:整 ...