这篇微信开发教程将为大家讲解微信后台技术“干货”带来的启发,看完本文你将对微信开发的知识点有更加清晰的理解和运用。
因为不断的写作,让我养成了记录、收藏、整理读书笔记的习惯,春节在家休息的时候整理了一下自己2016年收藏的内容和笔记,发现技术内容包括很多关于微信后端的技术文章。
记得去年年中我写过一篇文章《技术内容的选择性问题》,文中提到,五年前做IM的时候,腾讯在技术上还是很神秘很低调的,而去年腾讯在技术上非常开放,不仅贡献了很多很好的技术内容文章,还开源了很多基础组件库。
这篇文章是我在看了一些微信后台技术相关的实战文章之后得到的一些启发,如果说去年年中那篇文章是讲技术实战文章的甄选的话,这篇文章大概就是讲甄选之后的消化吸收了。
循证决策途径
上一篇文章提到过,循证大概是我们看技术文章的本源诉求之一,通过分析别人走过的路,可以拨开自己在技术探索中的迷雾。
IM 消息应用最重要的技术决策之一就是消息模型。微信采用的是存储转发模型,详细描述如下(参考文献 [1]):
消息发送之后会先暂时存储在后台;为了让接收者能够更快的收到消息,会向接收者推送消息通知;最后客户端主动去服务端接收消息。
简单描述这个模型就是三个步骤:
1、消息收到后,暂存于服务器端,并通知发送方已发送成功。
2.通知接收端有消息过来拉。
3.接收端收到通知后,会拉取真实的消息。
这个模型乍一看,多一层通知再拉取的冗余,为什么不直接推送消息呢?没错,我们自己做IM早期的时候,就设计过一个模型,先尝试直接推送消息,如果接收端没有确认收到,再进行暂存。后者减少了暂存的量和时间,而且也没有多余的通知。
但后面这种模型又增加了一层复杂度,在PC互联网早期,推送和确认的效率相当高,但在移动端环境下就没那么好了。另外移动端的引入其实又带来了一层复杂度,多端在线,多端确认,多端有已读未读消息,这些都需要服务器记录每个终端的状态。所以我们逐渐演变成了存储和推送同时并行的模型。存储是为了方便每个终端拉取自己的离线消息,但是因为推送需要考虑老终端版本的支持,所以只能直接推送消息本身,也不容易简化成消息通知取消消息接收确认流程。
实事求是,即使看到了更好的方法,也要结合自己的实际情况去思考实践的路径。所以我们的模式是相对于微信来说比较折中的版本。五年多前如果要改成微信那样的模式,可能只需要一两个程序员一个星期。但现在可能需要几个不同的开发团队(各种终端和后端)一起努力一两个季度才能把所有用户都切换过来。
讨论和思考方式
IM 中还有一个非常常用、大家都很熟悉的功能——群发消息。关于群发消息模型,微信采用的是写入-扩散模型,也就是说发给群的消息会为群里的每个人保存一份(消息索引,参见 [1])。这个模型最大的缺点就是需要多份消息,牺牲空间换取每个人拉群消息的效率。
很多年前,我们刚开始做群的时候,也是采用写扩散模型,后来由于存储压力太大,就改用读扩散模型。读扩散模型下,群消息只存储一份,记录每个群成员读该群消息的偏移量(消息索引号,单调递增)。存储压力大的原因是当时公司还没有统一的存储组件,我们直接采用了内存存储,水平和垂直扩展性都比较有限。这在当时是两害相权取其轻,选择了对我们研发团队来说成本更低的方案。
后来等公司有了扩展性和性能都很好的统一存储组件,其实还是换回写扩散模型比较好,毕竟读扩散模型的逻辑更复杂,考虑到我不知道自己加入了多少个群,每次打开应用都要去检查各个群里有没有消息,性能开销是线程递增的。唯一的问题是,谁也不想改一个写好、测试好、在线稳定运行了几年的程序吧?每一次技术升级、架构优化其实都需要一个契机。
所有分布式后端系统的另一个常见问题是性能。一旦你的用户群达到一定规模,比如 100 万,对技术支持的挑战实际上并不是随着后续规模的每次增加而线性增加的。微信春晚红包案例(参考 [2])提供了很好的借鉴和启发,因为市面上能达到这个规模的系统非常少。
2015年春节期间微信红包请求峰值为1400万次/秒。微信后端其实也采用了微服务架构,其拆分原则如下(参考[1]):
将实现不同业务功能的CGI划分为不同的模块,将功能相同但重要性不同的模块也进行划分,例如核心功能的消息收发逻辑,划分为消息同步、文字语音消息发送、图片视频消息发送三个业务模块。
服务分离了,借助自动化基础设施,运维效率不会下降太多,开发协同效率会大大提升,但性能会下降。那么微信春晚红包这种极端性能场景该如何应对呢?在电商中,普通订单和秒杀订单大多由两个独立的系统支撑。秒杀针对性能进行了专门的优化,简化了很多正常的流程,而且秒杀本身需要支持的SKU很少,所以它有简化的基础。微信提供的解决方案其实也有类似的思路,但是它比较特别的一点就是可以将分离出来的服务重新合并回来,以提升性能。
如此海量的请求,在这个分布式系统中,任何网络或服务的波动都可能是灾难性的。最终我们选择移除每秒挂掉千万请求的摇一摇服务,将这个服务移到服务上。但这么做有个前提,就是不能降低服务的稳定性。因为不仅仅是春晚摇一摇的请求,微信消息收发等基础功能的请求也需要经过服务中转,如果内嵌的摇一摇逻辑拖累了服务,那就得不偿失了。
这里的黑科技在于C++技术栈的优势,同一个接入服务器上不同的进程其实处理不同的功能,达到隔离的效果。不同的进程之间可以通过共享内存进行通信,比网络通信效率高很多,有效避免了网络层带来的波动性,这是我们用Java做后端做不到的。
互相学习,不能因为别人功夫好,能轻松解决问题,就改变思路去学习。动作表面上可能一样,但内在的力量可能完全不同,就像金庸小说里的鸠摩智,非要用小无相功来激发少林七十二功夫,结果自毁武功。互相学习,主要是让自己的思维方式不一样,用自己的功夫去寻找解决问题的方法。
连接与有效提取
如何挑选干货?我在上一篇文章《干技术货的选择性》中给出的最终结论是,为自己搭建人脉,形成知识体系。你可以暂时忽略那些距离你人脉太远的技术动向,结合功利和兴趣的原则,不断编织和拓展自己的技术人脉。在编织出一些新的节点进入人脉后,你需要进一步有效地提取这些节点的价值。
刚开始做IM的时候,我就有个疑问:IM的长连接接入体系,单机应该支持多少个长连接?早期运维有单机1万个长连接的报警指标,但当时我用Java NIO开最大堆内存2G,在可以接受的GC暂停下,测试发现4核物理机上10万个长连接的极限支持是可以的。所以平时保守一点,用一半的测试容量,5万个应该是可以的。
后来有机会去拜访了当时阿里旺旺的后端经理,我们还讨论了长连接数的问题。当时淘宝有600万卖家同时在线,买家实时在线大概有600万。所以同时在线的用户大概有1200万,当时他们有400台后端接入服务器,也就是说每台服务器维持着3万个连接。他说这不是技术限制,是业务限制。因为单台机器故障率高,一旦机器挂了,上面所有的用户都会暂时离线,重新连接。如果一次性离线的用户太多,恢复时间会比较长,对淘宝的订单成交会造成很大影响。
他还讲到过一次整个机房故障的事故,导致单机房600万用户同时下线。整个故障和自动切换恢复时间只有几十分钟,这期间淘宝的交易量也同比下降了40%左右。因为旺旺在线和交易相关性很高,单机长连接数是有限的,而且当时百万级单机长连接的实验已经证明是可行的。
在微信春晚红包的文章中提到:
上海、深圳两地已建立18个接入集群,各城市接入3张网络,共部署638台接入服务器,可支持14.6亿用户同时在线。
简单算一下,容量规划大概是228.8万单机长连接,14.6亿大概是当时全国人口的上限,当然现实中没有这么多,但预估单机长连接应该在百万左右,这个数字已经很不错了,而使用Java技术栈实现单机这个数字,恐怕也需要多进程,否则大量的GC停顿是无法接受的,需要单独调优。
联结意味着将已经了解的部分与针对同一问题或场景的新知识、新实践联系起来,形成更大的网络,探索更多的未知。
...
如何吸收、消化信息,这是一个见仁见智的问题,但在信息爆炸的时代,我们忙着过滤、搜集信息,却从来没有抽出一点时间去加工、提炼信息,或许你已经忘记了收集信息的初衷。
最后,附上一些关于微信后台技术的参考文章,有些是本文引用的,有些没有,但都值得一看。
参考文献及阅读后
[1] 张文瑞. 从0到1:微信后台系统的演进. 2016年1月
[2] 张文瑞. 百亿倍的挑战:如何实施“稳妥”的春晚摇头制度. 2016年12月.
[3] 陈明. 微信朋友圈技术:三人后台团队,日发数十亿条帖子. 2015年12月。
[4] 曾钦松. 万亿级通话系统: 微信序列号生成器架构设计与演进. 2016.06
以上,关于微信开发的内容就讲解完毕了,欢迎继续关注!更多微信开发资讯,请关注智作微信开发频道!