专栏名称: InfoQ
有内容的技术社区媒体。
目录
相关文章推荐
新浪科技  ·  【#白象商标争议再升级# ... ·  13 小时前  
虎嗅APP  ·  暴跌的榴莲 ·  昨天  
新浪科技  ·  【#曝iOS26适配iPhone11及更新机 ... ·  2 天前  
36氪  ·  当代禁欲青年,敞开欲望的100个瞬间 ·  2 天前  
51好读  ›  专栏  ›  InfoQ

微信异步化改造实践:8亿月活、万台机器背后的解决方案

InfoQ  · 公众号  · 科技媒体  · 2016-12-07 08:00

正文

请到「今天看啥」查看全文


综合以上考虑,最终我们选择了B方案,通过协程的方式对微信后台上百个模块进行了异步化改造。

接管历史遗留的同步风格API

方案敲定之后,接下来做的就是实现异步化的同时尽可能地少做代码修改。

通常而言,一个常规的网络后台服务需要connect、write、read等系列步骤,如果使用同步风格的API对网络进行调用,整个服务线程会因为等待网络交互而挂起,这就会造成等待并占用资源。原来的这种情况很明显地影响到了系统的并发性能,但是当初这样的选择是因为对应的 同步编程风格具有其独特的优势:代码逻辑清晰、易于编写并且支持业务快速迭代敏捷开发。

我们的改造方案需要消除同步风格API的缺点,但是同时还希望保持同步编程的优点。

最后在不修改线上已有的业务逻辑代码的情况下,我们的libco框架创新地接管了网络调用接口(Hook)。把协程的让出与恢复作为异步网络IO中的一次事件注册与回调。当业务处理遇到同步网络请求的时候,libco层会把本次网络请求注册为异步事件,当前的协程让出CPU占用,CPU交给其它协程执行。在网络事件发生或者超时的时候,libco会自动的恢复协程执行。

libco的架构

libco架构从设计的时候就已经确立下来了,最近的在GitHub上一次较大更新主要是功能上的更新。注:libco为开源项目,源码同步更新,可移步:

https://github.com/tencent/libco

libco框架有三层,分别是协程接口层、系统函数Hook层以及事件驱动层。


协程接口层实现了协程的基本源语。co_create、co_resume等简单接口负责协程创建于恢复。co_cond_signal类接口可以在协程间创建一个协程信号量,可用于协程间的同步通信。

系统函数Hook层负责主要负责系统中同步API到异步执行的转换。对于常用的同步网络接口,Hook层会把本次网络请求注册为异步事件,然后等待事件驱动层的唤醒执行。

事件驱动层实现了一个简单高效的异步网路框架,里面包含了异步网络框架所需要的事件与超时回调。对于来源于同步系统函数Hook层的请求,事件注册与回调实质上是协程的让出与恢复执行。

相比线程,选择协程意味着什么?

比起线程,对于很多人而言,协程的应用并不是那么轻车熟路。

线程和协程的相同点是什么?我们可以简单认为协程是一种用户态线程,它与线程一样拥有独立的寄存器上下文以及运行栈,对程序员最直观的效果就是,代码可以在协程里面正常的运作,就像在线程里面一样。但是线程和协程还是有区别的,我们需要重点关注是运行栈管理模式与协程调度策略。关于这两点的具体执行,在本文后续部分会谈及。

那两者的不同点呢?协程的创建与调度相比线程要轻量得多,而且协程间的通信与同步是可以无锁的,任一时刻都可以保证只有本协程在操作线程内的资源。

我们的方案是使用协程,但这意味着面临以下挑战:

  1. 业界协程在C/C++环境下没有大规模应用的经验;

  2. 如何处理同步风格的API调用,如Socket、mysqlclient等;

  3. 如何控制协程调度;

  4. 如何处理已有全局变量、线程私有变量的使用。

下面我们来探讨如何攻克这4个挑战。

挑战一







请到「今天看啥」查看全文