Mosquito的优化——epoll优化(七)

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

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事件处理流程

时间: 05-28

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

Android性能优化方法(七)

Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 这里重点介绍一下软引用和弱引用. 如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它:如果内存空间不足了,就会回收这些对象的内存.只要垃圾回收器没有回收它,该对象就可以被程序使用.软引用可用来实现内存敏感的高速缓存.软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,J

性能优化——算法优化

背景 由于某种原因,我们系统需要记录另一个系统中一个表里的id.但是,当我们记录完了以后,别人系统可能会删除那个表里的一些数据,这样的话,我们这边就多了一些无效数据,所以,我们必须的找到这些无效的id,然后将其删除. 开始,我们的实现是这样:我们将记录下来的所有id放在一个list里,然后传到另一个系统,他将他们已经删除的id返回.具体处理代码如下: <pre name="code" class="java">public String findDele

凸优化之优化、对偶、KKT-七月算法(julyedu.com)4 月机器学习算法班学习笔记

优化 一般优化问题的基本形式 凸优化的基本形式 共轭函数 共轭函数是凸函数 对偶问题 拉格朗日函数 拉格朗日对偶函数 KKT条件 小结 优化 一般优化问题的基本形式 minimizef0(x),x∈Rn s.t.fi(x)≤0,i=1?m s.t.hj(x)=0,j=1?n 定义域为 当 m=n=0 时,约束优化问题退化成无约束优化问题 注意:这是是优化问题的一般形式,对 fi(x) 和 hi(x) 无特殊要求.就是并不要求这些函数一定可导,也不要求只有一个极值点,就是啥要求都没. 凸优化的基本

Unity3D优化技巧系列七

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144. 上篇博客实现了LoginState的封装,其实作为UI的各个窗口,每个窗口都对应着自己的State也就是状态类.这么多状态类,不能鼓孤立的存在着,它也需要我们封装一个状态管理类去处

前端性能优化之优化图片

前端图片优化一直以来都是热门话题,从需求上来看,很多站点往往是图片体积大于代码体积, 图片请求多余代码文件请求, 给前端的性能带来了很大的困扰,那么应该如何解决呢? 零. 认识图片 我们通常使用的图片就是gif.png和jpg了. 其中,gif格式是比较老的图片格式,它的色彩效果最低(就是不清楚!!!),如果想要使用gif保存鲜艳图片会让你的网站看上去非常可怕. 但是gif有着不可忽视的优点:体积小.有着极好的压缩效果,支持动画,并且支持透明效果,虽然这个透明没有PNG格式图片支持的强大... 

刚搭建的linux环境的基本优化以及优化脚本---菜鸟初写

本篇博文主要是参考并借鉴老男孩老师的优秀博文外加自己总结及写的优化脚本!博文地址:http://oldboy.blog.51cto.com/2561410/1336488 虽然我并没有参加过老男孩老师的培训但是看过他的优秀视频和优秀博文,接受过他的熏陶与教育,在这里十分感谢老男孩老师!!! 还有这篇博文之中一些操作与脚本的编写非常感谢京峰老师们的帮助! 主要优化的目录 我使用的linux版本是CentOS6.6 x86_64 1.网络配置优化 2.关闭selinux及清除iptables链 3.

mysql优化-数据库优化、SQL优化

我有一张表w1000,里面有1000万条数据,这张表结构如下:CREATE TABLE `w1000` ( `id` varchar(36) NOT NULL, `name` varchar(10) DEFAULT NULL, `age` int(3) DEFAULT NULL, `money` double(8,2) DEFAULT NULL, `address` varchar(100) DEFAULT NULL, `create_date` datetime(3) DEFAULT NULL

nginx1.10.3一键安装/系统内核优化/配置文件优化/https/日志切割

下面的是一键安装nginx 1.10.3 最新稳定版本,编译参数是官方推荐的. yum groupinstall "Development Tools"   -y yum  install wget   zlib-devel openssl-devel pcre-devel -y cd /usr/local/src wget http://nginx.org/download/nginx-1.10.3.tar.gz tar zxvf nginx-1.10.3.tar.gz cd ngi

网站优化—MySQL优化

MySQL优化 简介 由于页面静态化技术可以实现对动态数据的缓存,但是有的时候还是需要去请求数据库.所以对数据库的优化也是不可缺少的. 优化思路 设计:存储引擎,字段,范式 自身:索引,自身的缓存 架构:读写分离 ? 存储引擎: MyISAM和InnoDB之间的对比.当然需要知道MySQL除了这两种存储引擎还有其他的存储引擎(memory存储引擎). MySQL在5.5版本之后默认的存储引擎为InnoDB 在面试的过程中,只要说出MyISAM和InnoDB的区别即可 ? 字段选择: 合适即好,能

iOS 25个性能优化/内存优化常用方法

1. 用ARC管理内存 ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露.它自动为你管理retain和release的过程,所以你就不必去手动干预了.忘掉代码段结尾的release简直像记得吃饭一样简单.而ARC会自动在底层为你做这些工作.除了帮你避免内存泄露,ARC还可以帮你提高性能,它能保证释放掉不再需要的对象的内存. 2. 在正确的地方使用 reuseIdentifier 一