默认
打赏 发表评论 8
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
魅族2500万长连接的实时消息推送架构的技术实践分享
微信扫一扫关注!

引言


此文内容整理自魅族架构师于小波在“魅族技术开放日”的演讲分享,本次演讲中于小波分享了魅族在实现2500万长连接的实时消息推送系统中所遇到的坑和一些心得体会,希望对实时消息推送技术相关的技术同行有所启发和帮助。

分享者


1.jpg
于小波,魅族系统架构师。2011年加入魅族,现在在移动互联网部门,负责服务器后台架构和开发工作。

系统负载介绍


这个系统数据情况是这样的,实时在线的用户是2500万左右,下面有一个趋势图,从今年1到10月份的都列出来了,这个系统一天PV量是50亿左右,这个系统推送速度可以达到600万条/分钟。

1.jpg

系统架构设计


系统架构逻辑上划分,划分为四层,最下面的一个是提供魅族手机的接入。第二层是消息分发服务,主要的作用就是提供上行消息的路由和用户下行消息的路,这边有一个用户路由表。第三层是订阅信息,第四层是存储,包括离岸消息存储,包括订阅消息的存储。

2.jpg

如上图所示:左上角有一个服务管理和业务监控,其实是两个独立的东西。有一个推送平台,是提供给业务使用的推送业务的接口。我们都有独立的服务,是有单独的DEMO的集群,可以独立的部署和独立的扩容。

魅族踩过的坑和心得总结


1手机的功耗问题


3.jpg

手机功耗问题主要涉及两个点,第一个是流量,第二个是电量

先看流量的问题,怎么样解决流量的问题,通过协议选择,现在传统的互联网上,有比较典型的使用通讯协议的话,是这两个协议,XMPP、SIP,这两个协议有很多的优点,第一个是开元组件非常多,如果想快速的搭建一脱系统出来,这两个协议是比较好的选择。不足的地方是协议很复杂,单独的标准文档就有几十页,如果完全把它看完,弄懂,估计要花长的时间,因为这两个协议是基于互联网的,并不是针对移动互联网进行优化的,所以协议是比较重的,像XMPP,有很多无用的标签,我们根本用不到这些标签,包括SIP协议,也有很多头,和XMPP协议差不多的。最重要的一点是非常的耗流量,所以我们就自己定义了IDG的协议,轻量、编解码属于快,是上面两个协议的10倍左右的编解码速度,最重要的一点是节约流量,使用中发现节约流量到50%到70%。

还有一个电量的问题我们怎么样解决?洲际电量就要涉及到长连接的保持,要想保持,就是要发送心跳包到用户手机上,固定的心跳,固定3分钟、5分钟或者是10分钟来发送心跳,网络情况是比较复杂的,有时候网络情况是好的,有时候网络情况是差的,选择最短的时间。前面有一个协议,IDG的协议来降低用户的流量问题,通过智能心跳的问题,来降低手机的电量的消耗。  

在生产实践中,我们发现有些用户对实时性的要求并不是特别的敏感,比如说系统的升级、应用的升级,早几分钟,或者是晚几分钟,并不会影响用户的使用体验。我们对于这种实时性要求不高的消息,可以使得手机在唤醒的状态下才把信息推送下去,我们怎么知道手机处于唤醒状态呢?这个服务端是可以感知得到的,前面讲过手机要维持长连接,就要发心跳,发心跳就要唤醒手机,服务端收到心跳包的时候,再把消息推送下去,这样就可以相对来说降低一点手机的功耗问题。通过这三个点的优化,基本上相对来说是比较完美的解决了手机的功耗问题,不过这个只是其中一步其中一个坑,我们革命还未成功。

2移动网络的问题


国内的移动网络有一个特点,不稳定,因为我们不知道什么时候会掉线,还有延迟是非常大的,移动网络的不稳定和高延迟,会让我们碰到一些什么问题?首先是碰到的重复消息的问题,重复消息是怎么产生的,可以看这个图的流程。

4.jpg

服务端向客户端推送一条消息的时候,正常情况下,消息推送下去,客户端到这个消息,给它回一个应答,如果回应答的过程中,服务端就收不到这个应答,服务端就有两种处理方式,一种是离线,一种是超时重试,重试几次,直到收到为止,这样服务端要保持每一条推送消息的状态,这样子如果服务端后端因为不单是一个服务组成的,是有很多服务组成的,后端的调动页就会拉得很长,每一个节点上面都需要保持状态,任何一个节点出现问题,整个都会认为这个消息是推送失败了。重复消息的话,客户端发送应答,服务端没有接到这个应答,而网络好的时候,再推送一次,那就出现重复了。

那怎么解决这个问题?设置了消息基于序列号的交互方式,首先推送消息的时候,不是把消息直接推送下去,是发一个通知到客户端,告诉你有消息,客户端拿到这个通知,发送一个指令上来,说获取这个消息,会带上一个收到最近消息的最大的序列号。

这里有一个大坑,也就是DNS也容易出现问题,相信很多人都碰到过这样的情况。怎么解决这个问题?用全IP的方式,要接入服务器的话,我们这边有一个WEBService,里面有很多的IP列表,IP列表都拉下来,客户端直接选取一个IP地址直接去连接,看下面第一个图的第一步,通过HTTP访问客户端的,但是也存在一个域名的问题,我们做了预埋,直接用DNS访问,如果这个DNS访问不通,就可以用预埋的IP来访问,就可以拿到一个IP地址。

3海量连接出现问题


解决了IP的DNS的问题,革命胜利还有半天,还有最后一个问题了,就是海量连接的问题。大并发话,我们的目标,单机可以达到400万的长连接,我们实现C++来实现的,是性能的原因才用C++的。还有多进程+epoll,内存池防止内存碎片。这里比较推荐Tcmalloc这个是谷歌开元的组件,非常好用。

最后我们还做了内核参数调优的优化,内核参数调优,系统在一台服务器上跑的时候,达到百万级连接的时候,我们发现有一个问题,其中有一个CPU的负载会非常高,其他的CPU负载相对来说是比较低的,是比较空闲的。最后我们发现,因为网卡是多个,网卡的中断都由这个CPU响应,既要响应网卡的中断,又要响应业务的需求,这个非常的繁忙,怎么解决?把这个网卡中断绑定,转到其他CPU上,达到负载均衡。第二个是TCP RTO修改,我们用2.0的系统内核,默认的只是200毫秒的,如果200毫秒出现超时重传,但是网络延迟比较大的,200毫秒的话,会经常会出现重传,会很频繁的重传,会导致协议站的性能会降低,所以我们就在内核系统打了补丁,改为3秒左右,性能会得到一部分的提升。

解决了大并发,下一个是负载均衡的问题,比较常规的做法是前面加LVS,后台有几台服务器,但是LVS并不适合我们的业务场景,一台服务器可以接受400万的长连接,一个LVS,下面挂三台服务器,LVS首先存在单点问题,LVS一台就要承受1200万连接,这个是肯定扛不住这样多的连接数的,我们就放弃了使用单点运营。第一个是服务端做,第二个是客户端做,前面也讲过,获取IP列表,在获取的时候,我们LVS已经对那些IP进行过排序了,负载比较低的服务器是排在前面,拉下来之后,客户端直接拿前面的IP地址连就可以了,在这个地方直接解决负载均衡。解决负载均衡的同时也解决了跨运营商网络慢的问题。第一次客户端拉取IP列表,前面的服务器都是负载比较低的,但是客户端是对这个IP列表进行缓存的,缓存之后,如果断线重连,再连的时候,就不知道哪台服务器负载高,哪台服务器负载高,这里就有一个策略,客户端把IP划分成多个IP区间,每一个区间有多个IP,选取IP发一个探测包到服务器,服务器会针对探测包有响应包回来的,哪个先回来,就用哪个IP地址,这样就同时解决了跨运营商的网络慢的问题。

但是这样做的话,其实还是有问题的,不能单独在客户端简单做一个发一个探测包,先收到就用这个,这个也不行,服务端也需要做一些相应的策略假设某一台服务器负载比较高的时候,刚好收到探测包,立刻回一个响应,很快的客户端收到这个响应就会连上来,但是本身的负载已经比较高了,那服务端怎么解决这个问题?根据自身的负载情况来做延迟响应,负载达到一定的阀值的时候,比如说是300万,每超过10万,延迟时间稍微加50毫秒,收到你的响应包,我晚个50毫秒之后再回应答,这样跑马策略是可以解决整个的负载均衡。

系统的监控和灰度发布


1系统的监控


我们的系统是由很多小服务组成的,我们很难依靠简单的业务监控来发现未来可能存在的问题,为什么要用“可能”这个词?假如说每一个业务都是有一个单独的集群,集群中有一个节点如果出了问题,并不会影响整个业务的使用,只有当累加到足够大的程度的时候,错误累积到很大的程度,才会导致整个系统不可用,这样其实是不行的,所以我们必须要引入一套严格的监控体系,来发现未来可能发生的问题,快速的定位出来,所以针对每一个集群里面的每一个节点都要有监控,有一些比较严格的监控指标,这里列了几个我们认为比较重要的。

第一个是错误计数,假如说我有一个节点出现了很多的错误计数,其实这个是需要报警通知开发人员。

第二个是接发队列,接收和发送队列,如果队列中积累很多的服务,那这个很可能是过载了。

第三个是请求数,为什么要做请求数的监控和报警呢?假如说请求开始前面是一个比较低的水平,慢慢的用户量越来越多,如果没有很好的报警体系的话,有可能有一天瞬间把你整个集群冲垮,也就是说达到一定量的时候提前预警,整个业务需要加服务器了。

第四个是处理的接口的调用延时,正常业务调用是1毫秒以内,如果超过了,假如说某一天发现有大狼的100毫秒或者是200毫秒的处理延时,这个业务可能是出现问题的。最后是服务可用性检查,是系统服务不可用了,这个肯定是需要报警的,这个是强指标。

2灰度发布


灰度发布,是用户无感知的发布,还有用户可以平滑的迁移,用户平滑迁移之后,我们做在灰度里面,负载均衡里面也是可以用到这个功能,假设一个集群里面,某一个节点的用户数比较多的时候,可以把负载高的迁一部分用户到负载比较低的节点上面去。

5.jpg

灰度发布的流程是这样的,首先是一个节点的发布,一个节定发布之后,跑几天看一下,如果没有什么问题,灰度放量,扩散到几个节点,这个集群里面选几个节点,让这些用户去用,如果还是OK,没有什么问题,我们就扩散到全部的节点。

在没有灰度发布之前,开发人员的状态大概是这样的:因为以前发布的话,基本上都是深夜,都是夜深人静的时候发布,看是否有异常的情况。引入了灰度之后,对于开发人员来说,这种状态就是大有改善的了。

(原文链接:点此进入

更多推送技术资料


[1] 更多推送技术文章:
iOS的推送服务APNs详解:设计思路、技术原理及缺陷等
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
扫盲贴:认识MQTT通信协议
一个基于MQTT通信协议的完整Android推送Demo
IBM技术经理访谈:MQTT协议的制定历程、发展现状等
求教android消息推送:GCM、XMPP、MQTT三种方案的优劣
移动端实时消息推送技术浅析
扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别
绝对干货:基于Netty实现海量接入的推送服务技术要点
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
为何微信、QQ这样的IM工具不使用GCM服务推送消息?
极光推送系统大规模高并发架构的技术实践分享
从HTTP到MQTT:一个基于位置服务的APP数据通信实践概述
魅族2500万长连接的实时消息推送架构的技术实践分享
专访魅族架构师:海量长连接的实时消息推送系统的心得体会
>> 更多同类文章 ……

[11] 更多即时通讯技术好文分类:
http://www.52im.net/forum.php?mod=collection&op=all

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:从HTTP到MQTT:一个基于位置服务的APP数据通信实践概述下一篇:专访魅族架构师:海量长连接的实时消息推送系统的心得体会

本帖已收录至以下技术专辑

推荐方案
评论 8
这样的文章适合有经验的开发者看,还是有些干货的
还是手机厂商自己做起来最爽,根本不必关心保活问题,聊一下智能心跳别太耗电就可以了。
签名: 该会员没有填写今日想说内容.
引用:researchboy 发表于 2017-03-07 18:52
还是手机厂商自己做起来最爽,根本不必关心保活问题,聊一下智能心跳别太耗电就可以了。

如果GCM在国内能用,根本就不需要现在这么乱:自已弄推送就算了,华为小米还得强迫用他们的推送,各厂商的api又不一样,更坑爹
引用:JackJiang 发表于 2017-03-07 19:16
如果GCM在国内能用,根本就不需要现在这么乱:自已弄推送就算了,华为小米还得强迫用他们的推送,各厂商 ...

膜拜大神 您做的这个网站真的很不错 干货满满 !
签名: 该会员没有填写今日想说内容.
引用:researchboy 发表于 2017-03-08 09:15
膜拜大神 您做的这个网站真的很不错 干货满满 !

GCM还是不错的,国内环境不行啊……
签名: 啊送达
不错,
谢谢分享
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部