专访魅族架构师:关于实时推送系统的那点事

2021-10-27 00:00:00 业务 系统 接入 推送 单点



嘉宾介绍

于小波,系统架构师,2011年加入魅族,主要从事服务端后台开发工作,专注于系统高并发,分布式等解决方案。


duke217(Q1):于老师,您好,很高兴有机会采访到您!您能否先和大家介绍一下自己?

于小波(A1):各位网友,大家好,我是于小波,来自魅族移动互联网部门,2011年加入魅族,目前主要从事服务端后台架构设计和开发工作。


duke217(Q2):我们了解到,您在魅族已经工作四年多了,一直专注于探索分布式系统和消息的高并发,能给我们分享下您的研究经验和心得么?

于小波(A2):我觉得并发和分布是两个不同的概念,并发反应的是量(请求量、用户量), 单台机器也可以有很高的并发量。但是单台机器的性能毕竟是有限的,同时存在单点问题,这种情况下我们引入多台机器来共同协作,提高性能的同时也解决了单点问题,这就是分布式。
在高并发的分布式系统中,个人认为比较重要的几个点:
1)大系统小做,把一个大的系统拆分成很多小的独立的服务,降低系统的复杂性
2)需要一套成熟的通信框架,来提高开发效率。
3)尽量避免使用多线程,好是多进程、无锁设计。
4) 做好过载保护、监控和灰度。(这个很重要)


duke217(Q3):近几年,魅族正处于移动互联网的转型期,这个过程中,有没有遇到令您印象深刻的技术难题?

于小波(A3):碰到的问题很多,有些是技术上的问题有些不是技术上的。比如说在开发语言的选择上纠结了挺久。后我们选择了c++语言,基于以下原因:
1) 性能。
2) 人员招聘, c++是比较大众的语言,相对来说人员比较好招
3) 内存可控,这是我们选择c++的一个很重要的原因,内存的使用尽量掌控在自己的手上。因为千万级的用户,如果出现一点内存不可控,后累积下来是很可怕的。
技术问题我这里就分享一个我印象比较深刻的。
我们是长连接服务,手机端和服务端要维持这个长连接,需要定期的发送心跳消息,我们为了节约电量和流量,手机端采用的是智能心跳模式。那么对服务端来说,它是不知道手机端下次是几分钟之后会发送心跳上来的,那么这个连接在服务端的超时时间应该设置多久就是一个问题了。
客户端在每一次的心跳消息中携带下一次的心跳时间。服务端就根据这个时间来设置连接的超时时间。


duke217(Q4):随着用户量从百万级快速增长到千万级,魅族的实时消息推送系统压力也肯定大增,那是用什么办法解决的呢?

于小波(A4):其实魅族的推送系统并不是一开始就按照千万级的用户量来设计的,我们的架构也是根据实际情况一步一步演化来的。初,我们做这个推送系统只是为了推送手机固件升级。而且用户量也没有那么多,估计也就是几十万,我们使用很多开源的组件快速把系统搭建出来。这套系统可以满足我们的要求。
随着魅族用户量的快速增长,我们的系统就暴露出了很多问题,只能一个一个坑去填。
1) 接入层性能问题
原来的接入层单台服务器多接入30W长连接,而且很多业务逻辑也放在了接入层处理,导致接入层性能低下,而且代码很臃肿,维护成本很高,特别是新员工进来之后拿到这么一大堆代码,都不知道如何下手。所以我们对接入层做重构,把业务逻辑拆分出来,接入层只做简单的用户接入。所有的业务逻辑都在后端处理。也就是现在比较流行的微服务的架构。
2) 带宽问题
初我们的系统使用的是文本协议,每次做全网推送都占用了IDC大量的带宽,导致用户访问其他业务非常慢,我们就自定义了一套二进制协议,降低了50%-70%的带宽。
3) 服务化的基础组件
点里面提到 我们的一些业务逻辑是和接入层搅在一起的,我们需要把业务逻辑拆分成单独的服务。服务之间的互相调用就需要一套成熟的网络通讯框架。我们就做了一套RPC的框架,来提高开发的效率。初这套框架用的多线程+同步调用,在实际的使用中发现,多线程有很多坑,各种锁,特别是新员工写代码一不小心就死锁了。而且同步调用的性能并不理想,虽然开了多线程,但是线程又不能开的太多(大家都懂的)。针对以上情况,我们做了第二版的框架,使用了多进程+异步,服务的性能提高了10倍,但是又面对另外一个问题,因为异步,就没有办法避免各种回调,本来很连续的一个业务逻辑流程被打散在了各种回调函数里面,看代码的人非常痛苦,而且很容易产生内存泄露问题,比如:我申请的内存传递到回调函数中,结果忘记释放了(我们发现的内存泄露问题95%都是这样产生的)。
后,我们参照go语言的特性使用协程来做了第三版的框架,业务开发人员再也不用考虑同步的性能和异步的回调问题。同步调用方式、异步的性能。
4) 存储
引入了redis和mongodb来做缓存和消息存储。
因为redis是有单点问题,我们开发了一套redis集群,一是提高redis的存储容量,二是解决单点的风险。
Mongodb的使用过程中我们也碰到了很多的坑,主要就是集群的分片,这里我不详细讲了,主要列几个注意的地方:
根据业务形态选择合理的片键,尽量手动分片。
mongodb自带的balancer好在业务低峰期做。
合适的索引。


duke217(Q5):提到灰度发布,那我想跟您请教一下,灰度发布推送的消息,和其他APP推送的消息有何不同?(例如微信)

于小波(A5):灰度发布的本质是没有区别的,都是一种平滑过渡的发布方式,只是实现方式不同而已吧。
和微信对比,我们的推送系统功能比较单一,只要做到让用户无感知的发布即可,另外重要的一点就是降低发布的风险。


duke217(Q6):我们了解到,您主要从事服务端后台的开发工作,那有没有什么“过来人”的经验可以介绍给刚入行的朋友呢?

于小波(A6):
1) 保持对技术的专注和热情
2) 多研究一些的开源代码,比如nginx、redis等
3) 多逛一下技术论坛 比如chinaunix、csdn等
4) 多交流开阔视野 多参加一些技术沙龙的活动。
5) 后还是自己多思考多实践,读万卷书不如行万里路。


duke217(Q7):大家都知道,您本周四将在我们ChinaUnix的IT运维技术趋势群(微信)中进行直播活动,能稍稍给我们透露一下有哪些技术干货么?

于小波(A7):其实我们用的一些技术点在前面都已经提到过了,如果大家对其中一个点或者几个点有兴趣的话可以一起深入探讨下。

相关文章