微信后台技术“干货们”带来的启发

标签: 后端 架构 程序员 微信 | 发表时间:2017-02-19 20:58 | 作者:mindwind
出处:https://segmentfault.com/blogs

因为持续写作的缘故,因而有了记录、收藏和整理阅读笔记的习惯。之前春节在家休息无事时就顺便整理了下 2016 一年以来收藏的内容和笔记,发现技术内容中收录了好多篇有关微信后台的技术干货文章。

想到去年中时我还写过一篇 《技术干货的选择性问题》里面提到五年前我们做 IM,那时腾讯公司在技术上保持神秘而低调,去年的腾讯在技术上表现得非常开放,不仅贡献了不少不错的技术干货文章,也开源了不少它们的基础组件库。

本篇算是我阅读完微信后台技术相关的干货文章后得到的一些启发,如果去年中那篇属于技术干货的选择问题,这篇大概就是选择之后的消化吸收问题了。

循证与决策路径

在前文中提过,循证大概是我们读技术干货文章的一个原始诉求,通过分析别人走过的路径,来拨开自己技术道路探索上的迷雾。

关于 IM 类消息应用最重要的一个技术决策就是关于消息模型,微信采用了存储转发模型,其具体描述如下(参考[1]):

消息被发出后,会先在后台临时存储;为使接收者能更快接收到消息,会推送消息通知给接收者;最后客户端主动到服务器收取消息。

简单描述这个模型就是三个步骤:

  1. 消息接收后在服务端临时存储,并通知发送端已发送成功。

  2. 通知接收端有消息,请来拉取。

  3. 接收端收到通知后,再来拉取真正的消息。

初一看这个模型多了一层通知再拉取的冗余,为什么不直接把消息推下去?对,最早期我们自己做 IM 就设计的先尝试直接推消息下去,若接收端没有确认收到,再临时存储的模型。后者减少了临时存储的量和时间,也没有一个多余的通知。

但后面这个模型增加了另一层复杂度,在早期的 PC 互联网时期,推送并确认效率还算挺高的,但在移动环境下,就不太行了。而且引入了移动端,实际就导致了另一层复杂性,多终端在线,多终端确认,多终端已读和未读,都需要在服务端记录各个端的状态。所以,之后我们也就慢慢演变成同时存储和推送消息的并行模型,存储是为了方便各终端拉取各自的离线消息,但推送因为需要考虑旧终端版本的支持,还得直接推消息本身而并不容易简化成消息通知来取消掉消息的接收确认过程。

循证,即便你看到了一个更好的方式,但也要结合自身的实际情况去思考实践的路径。所以,如今我们的模型相比微信是一个更妥协的版本,若是五年多前要改成微信这样的模型,也许只需要一两个程序员一周的时间。但如今也许需要好几个不同的开发团队(各终端和后端)配合弄上一两个季度也未必能将所有用户切换干净了。

切磋与思考方式

IM 中还有个大家特别常用和熟悉的功能 —— 群消息。关于群消息模型,微信采用的是写扩散模型,也就是说发到群里的一条消息会给群里的每个人都存一份(消息索引,参考[1])。这个模型的最大缺点就是要把消息重复很多份,通过牺牲空间来换取了每个人拉取群消息的效率。

好多年前我们刚开始做群时,也是采用了的写扩散模型,后来因为存储压力太大,一度又改成了读扩散模型。在读扩散模型下,群消息只存一份,记录每个群成员读取群消息的偏移量(消息索引号,单调增长)。之所以存储压力大在于当时公司还没有一个统一的存储组件,我们直接采用的 Redis 的内存存储,当时原生的 Redis 在横向和纵向上的扩展性上都比较受限。这在当时属于两害相权取其轻,选择了一个对我们研发团队来说成本更低的方案。

再后来公司有了扩展性和性能都比较好的统一存储组件后,实际再换回写扩散模型则更好。毕竟读扩散模型逻辑比较复杂,考虑自己不知道加了多少个群了,每次打开应用都要检查每个群是否有消息,性能开销是呈线程递增的。唯一的问题是,写好、测好、上线运行稳定几年的程序,谁也不想再去换了对吧,每一次的技术升级和架构优化其实是需要一个契机的。

另外一个是所有分布式后台系统都有的共性问题 —— 性能问题。只要你的用户量到了一定规模,比如 100 万,以后每上一个量级,对技术支撑的挑战实际上并不是呈线性的。微信春晚红包的案例(参考[2])给出了一个很好的参考和启发,因为市面上几乎很少有系统能到这个量级了。

微信 2015 年春节的红包峰值请求是 1400 万每秒,而微信后台其实也采用了微服务的架构,其拆分原则如下(参考[1]):

实现不同业务功能的 CGI 被拆到不同 Logicsrv,同一功能但是重要程度不一样的也进行拆分。例如,作为核心功能的消息收发逻辑,就被拆为 3 个服务模块:消息同步、发文本和语音消息、发图片和视频消息。

服务拆散了,在自动化基础设施的辅助下,运维效率下降不大,而开发协作效率会提升很多,但性能会下降。那么在面对微信春晚红包这样的极端性能场景下,该如何应对?在电商里,正常下单和秒杀下单多是分离的两套系统来支撑,秒杀专为性能优化,简化了很多正常流程,而且秒杀本身需要支持的 sku 不多,所以它具备简化的基础。而微信给出的方案中实际也是类似的思路,但它有个特殊点在于,能把拆散的服务为了性能又合并回去。

在如此海量请求之下,在这个分布式系统中,任何一点网络或服务的波动都可能是灾难性的。最终我们选择把摇一摇服务去掉,把一千万每秒的请求干掉了,把这个服务挪入到接入服务。但这样做,有一个前提:不能降低接入服务的稳定性。因为不单是春晚摇一摇请求,微信消息收发等基础功能的请求也需要通过接入服务来中转,假如嵌入的摇一摇逻辑把接入服务拖垮,将得不偿失。

这里面的黑科技在于 C++ 技术栈的优势,同一台接入服务器上实际由不同的进程来处理不同的功能,达到了隔离的效果。而不同进程间又可以通过共享内存来通信,这比用 Socket 网络通信高效多了,又有效的规避了网络层带来的波动性影响,这是我们用 Java 做后台没法做到的事。

切磋,你不能看见别人的功夫套路好,破解难题手到擒来,就轻易决定改练别人的功夫。表面的招式相同,内功可能完全不同,就像金庸小说里的鸠摩智非要用小无相功催动少林七十二绝技,最后弄的自废武功的结局。切磋主要是带给你不同的思维方式,用自己的功夫寻求破解之道。

连结与有效提取

如何选择干货,我在前文 《技术干货的选择性问题》中最后给出的结论是,给自己结一张网,形成知识体系。暂时离你的网太远的技术潮流性的东西,可以暂不考虑,结合功利性和兴趣原则去不断编织和扩大自己的技术之网。在编织了一些新结点入网后,就需要进一步有效提取这些结点的价值。

刚做 IM 时,曾经有个疑惑,就是 IM 的长连接接入系统,到底单机接入多少长连接算合适的?很早时运维对于长连接有个报警指标是单机 1 万,但当时我用 Java NIO 开 2G 最大堆内存,在可接受的 GC 停顿下,在一台 4 核物理机上测试极限支撑 10 万长连接是可用的。那么平时保守点,使用测试容量的一半 5 万应该是可以的。

之后一次机会去拜访了当时阿里旺旺的后端负责人,我们也讨论到了这个长连接的数量问题。当时淘宝有 600 万卖家同时在线,另外大概还有 600 万买家实时在线。所以同时大概有 1200 万用户在线,而当时他们后端的接入服务器有 400 台,也就是每台保持 3 万连接。他说,这不是一个技术限制,而是业务限制。因为单机故障率高,一旦机器挂了,上面的所有用户会短暂掉线并重连。若一次性掉线用户数太多,恢复时间会加长,这会对淘宝的订单交易成交产生明显的影响。

他还说了一次事故,整个机房故障,导致单机房 600 万用户同时掉线。整个故障和自动切换恢复时间持续了数十分钟,在此期间淘宝交易额也同比下降了约 40% 左右。因为这种旺旺在线和交易的高度相关性,所以才限制了单机长连接的数量,而当时已经有百万级的单机长连接实验证明是可行的。

在微信春晚红包的那篇文章里提到:

在上海跟深圳两地建立了十八个接入集群,每个城市有三网的接入,总共部署了 638 台接入服务器,可以支持同时 14.6 亿的在线。

简单算一下,大概就是 228.8 万单机长连接的容量规划,14.6 亿怕是以当时全国人口作为预估上限了。实际当然没有那么多,但估计单机百万长连接左右应该是有的。这是一个相当不错的数量了,而采用 Java 技术栈要实现这个单机数量,恐怕也需要多进程,不然大堆的 GC 停顿就是一个不可接受和需要单独调优的工作了。

连结,便是这样一个针对同一个问题或场景,将你已知的部分连结上新的知识和实践,形成更大的网,再去探索更多的未知。

...

如何去吸收和消化信息,这是一个智者见智的事情,但在信息爆炸的时代都在忙于过滤和收集信息,却从不分配点时间去处理和提炼信息,也许你已经忘记了收集的初心了。


最后,是有关微信后台技术的一些参考文章, 有些在本文中引用了,有些没引用,但都值得一看。

参考与文后阅读

[1] 张文瑞. 从0到1:微信后台系统的演进之路. 2016.01
[2] 张文瑞. 100亿次的挑战:如何实现一个“有把握”的春晚摇一摇系统. 2016.12
[3] 陈明. 微信朋友圈技术之道:三个人的后台团队与每日十亿的发布量. 2015.12
[4] 曾钦松. 万亿级调用系统:微信序列号生成器架构设计及演变. 2016.06


写点文字,画点画儿,记录成长瞬间。
微信公众号「瞬息之间」,既然遇见,不如一起成长。

相关 [微信 后台 技术] 推荐:

微信后台技术“干货们”带来的启发

- - SegmentFault 最新的文章
因为持续写作的缘故,因而有了记录、收藏和整理阅读笔记的习惯. 之前春节在家休息无事时就顺便整理了下 2016 一年以来收藏的内容和笔记,发现技术内容中收录了好多篇有关微信后台的技术干货文章. 想到去年中时我还写过一篇 《技术干货的选择性问题》里面提到五年前我们做 IM,那时腾讯公司在技术上保持神秘而低调,去年的腾讯在技术上表现得非常开放,不仅贡献了不少不错的技术干货文章,也开源了不少它们的基础组件库.

从零开始搭建创业公司后台技术栈

- - 胖胖的空间
说到后台技术栈,脑海中是不是浮现的是这样一幅图. 有点眼晕,以上只是我们会用到的一些语言的合集,而且只是语言层面的一部分,就整个后台技术栈来说,这只是一个开始,从语言开始,还有很多很多的内容. 今天要说的后台是大后台的概念,放在服务器上的东西都属于后台的东西,比如使用的框架,语言,数据库,服务,操作系统等等,整个后台技术栈我的理解包括4个层面的内容:.

摩拜单车微信小程序开发技术总结

- - SegmentFault 最新的文章
摩拜单车小程序已于微信小程序上线第一天正式发布,刷爆微博媒体朋友圈. 本文主要讲讲技术方向的总结,在段时间的开发周期内内如何一步步从学习到进阶. 微信小程序没有HTML的常用标签,而是类似. React的微信自定义组件,比如. window变量,但微信提供了. React的state)来改变视图展现.

微信收费事件背后被广泛忽略的技术细节

- - Oasis Feng
作为一个横跨通信与互联网两大行业的从业者,前四年的核心网经验和后五年的互联网经验让我不得不感慨一个非常遗憾的现实:通信与互联网两大行业本来可以有珠联璧合的技术协同,为移动互联网提供近乎零耗电零流量的PUSH机制,但由于两个行业之间长期以来的价值观隔阂和互防心态,导致如今的手机PUSH技术不仅为用户增加了显著的电量消耗,还对移动运营商的基础设施造成了完全不必要的信令压力.

腾讯微信技术总监周颢:一亿用户增长背后的架构秘密

- - 互联网的那点事
微信——腾讯战略级产品,创造移动互联网增速记录,10个月5000万手机用户,433天之内完成用户数从零到一亿的增长过程,千万级用户同时在线,摇一摇每天次数过亿…在技术架构上,微信是如何做到的. 日前,在腾讯大讲堂在中山大学校园宣讲活动上,腾讯广研助理总经理、微信技术总监周颢在两小时的演讲中揭开了微信背后的秘密.

技术贴:微信公共账号会对新浪微博造成多大的杀伤力

- - 微博之博
微信公共账号最近是个热门话题,新浪微博上在一周之内突然遍地是微信二维码,不失为一道奇异的风景线. 不少人联想起两年前腾讯微博与 新浪微博的公开竞争,认为腾讯微博未尽的事业,终究让微信完成了. 微信的公共账号业务,对新浪微博究竟有多大的杀伤力. 公共账号这种东西,并不算是新玩意,早在MySpace时代,娱乐明星的公共账号就是文娱营销的重要阵地.

5分钟看懂NB-IoT技术与典型场景应用-微信公众号精选-华为开发者论坛

- -
NB-IoT 技术一直以来都备受关注. 小编特意为大家整理了一份 NB-IoT 技术实用宝典,帮助大家一起揭开 NB-IoT 的神秘面纱. 为了应对日渐强烈的物联网需求,于是国际移动通信标准化组织 3GPP 决定制订一个新的蜂窝物联网(CIOT:Cellular Internet of Thing)的标准.

linux后台执行

- otter - 博客园-首页原创精华区
 最近被很多人问,想退出secureCRT后,能够继续跑自己的进程,应该怎么实现,可以说这个方法不少,我就随便说说吧.      为什么会有这样的需求. 作为系统管理员,经常遇到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,需要运行了一些耗时较长的任务,例如批量ping一些网段之类, 有时候却由于网络的不稳定导致任务中途失败,或者需要中途离开,总不会在等它结束吧,如果你退出SSH登陆的话,那么你的任务也会被终止了,岂不是白费精 力了.

前端技术

- - CSDN博客综合推荐文章
随着互联网产业的爆炸式增长,与之伴生的Web前端技术也在历经洗礼和蜕变. 尤其是近几年随着移动终端的发展,越来越多的人开始投身或转行至新领域,这更为当今的IT产业注入了新的活力. 尽管Web前端技术诞生至今时日并不长,但随着Web技术的逐渐深入,今后将会在以下几方面发力. JavaScript的兄弟们.

SSI技术

- - 开源软件 - ITeye博客
1.       SSI,通常称为“服务器端包含”技术. 使用了SSI技术的文件默认的后缀名为.shtml,SSI技术通过在html文件中加入SSI指令让web服务器在输出标准HTML代码之前先解释SSI指令,并把解释完后的输出结果和HTML代码一起返回给客户端. 2.       SSI技术的优点:SSI技术是通用技术,它不受限于运行环境,在java、dotnet、CGI、ASP、PHP下都可以使用SSI技术;解释SSI的效率比解释JSP的效率快很多,因为JSP规范提供了太多的功能,这些功能都需要servlet引擎一一进行解释,所以效率比较低.