共计 9498 个字符,预计需要花费 24 分钟才能阅读完成。
本文援用了“一文读懂什么是过程、线程、协程”一文的次要内容,感激原作者的自私分享。
1、系列文章引言
1.1 文章目标
作为即时通讯技术的开发者来说,高性能、高并发相干的技术概念早就了然与胸,什么线程池、零拷贝、多路复用、事件驱动、epoll 等等名词信手拈来,又或者你对具备这些技术特色的技术框架比方:Java 的 Netty、Php 的 workman、Go 的 gnet 等熟练掌握。但真正到了面视或者技术实际过程中遇到无奈释怀的纳闷时,方知自已所把握的不过是皮毛。
返璞归真、回归实质,这些技术特色背地的底层原理到底是什么?如何能通俗易懂、毫不费力真正透彻了解这些技术背地的原理,正是《从根上了解高性能、高并发》系列文章所要分享的。
1.2 文章源起
我整顿了相当多无关 IM、音讯推送等即时通讯技术相干的资源和文章,从最开始的开源 IM 框架 MobileIMSDK,到网络编程经典巨著《TCP/IP 详解》的在线版本,再到 IM 开发纲领性文章《新手入门一篇就够:从零开发挪动端 IM》,以及网络编程由浅到深的《网络编程懒人入门》、《脑残式网络编程入门》、《高性能网络编程》、《鲜为人知的网络编程》系列文章。
越往常识的深处走,越感觉对即时通讯技术理解的太少。于是起初,为了让开发者门更好地从根底电信技术的角度了解网络(尤其挪动网络)个性,我跨专业收集整理了《IM 开发者的零根底通信技术入门》系列高阶文章。这系列文章未然是一般即时通讯开发者的网络通信技术常识边界,加上之前这些网络编程材料,解决网络通信方面的常识盲点根本够用了。
对于即时通讯 IM 这种零碎的开发来说,网络通信常识的确十分重要,但回归到技术实质,实现网络通信自身的这些技术特色:包含下面提到的线程池、零拷贝、多路复用、事件驱动等等,它们的实质是什么?底层原理又是怎么?这就是整顿本系列文章的目标,心愿对你有用。
1.3 文章目录
《从根上了解高性能、高并发(一):深刻计算机底层,了解线程与线程池》
《从根上了解高性能、高并发(二):深刻操作系统,了解 I / O 与零拷贝技术》
《从根上了解高性能、高并发(三):深刻操作系统,彻底了解 I / O 多路复用》
《从根上了解高性能、高并发(四):深刻操作系统,彻底了解同步与异步》
《从根上了解高性能、高并发(五):深刻操作系统,了解高并发中的协程》
《从根上了解高性能、高并发(六):通俗易懂,高性能服务器到底是如何实现的》
《从根上了解高性能、高并发(七):深刻操作系统,一文读懂过程、线程、协程》(* 本文)
1.4 本篇概述
本系文章中的《从根上了解高性能、高并发(一):深刻计算机底层,了解线程与线程池》、《从根上了解高性能、高并发(五):深刻操作系统,了解高并发中的协程》两篇文章,尽管都有波及到过程、线程、协程常识,但感觉还是不够零碎,零碎独自整顿了本文,心愿将这方面的常识零碎梳理和总结,达到彻底解惑的目标。
本篇是本系列文章的长期续篇,本篇将由浅入深,总结过程、线程、协程这 3 个技术概念,将 3 者的技术原理、用处、关系进行了零碎梳理和总结,心愿有助于解决你这方面的技术困惑。
本文已同步公布于“即时通讯技术圈”公众号,欢送关注。公众号上的链接是:点此进入。
2、本文原作者
本文内容援用了“一文读懂什么是过程、线程、协程”一文的次要内容(原文地址已无奈查到),原作者:luoweifu,毕业于江西农业大学,现就职于阿里钉钉。集体博客地址:https://blog.csdn.net/luoweifu。
3、什么是过程?
3.1 基本常识
咱们须要明确一下几个常识:
- 1)计算机的外围是 CPU,它承当了所有的计算工作;
- 2)操作系统是计算机的管理者,它负责工作的调度、资源的调配和治理,统领整个计算机硬件;
- 3)应用程序则是具备某种性能的程序,程序是运行于操作系统之上的。
过程是一个具备肯定独立性能的程序在一个数据集上的一次动静执行的过程,是操作系统进行资源分配和调度的一个独立单位,是利用程序运行的载体。过程是一种形象的概念,素来没有对立的规范定义。
过程个别由程序、数据汇合和过程管制块三局部组成:
- 1)程序用于形容过程要实现的性能,是管制过程执行的指令集;
- 2)数据汇合是程序在执行时所须要的数据和工作区;
- 3)程序控制块(Program Control Block,简称 PCB),蕴含过程的形容信息和管制信息,是过程存在的惟一标记。
过程具备的特色:
- 1)动态性:过程是程序的一次执行过程,是长期的,有生命期的,是动静产生,动静沦亡的;
- 2)并发性:任何过程都能够同其余过程一起并发执行;
- 3)独立性:过程是零碎进行资源分配和调度的一个独立单位;
- 4)结构性:过程由程序、数据和过程管制块三局部组成。
3.2 为什么要有多过程?
多过程目标:进步 cpu 的使用率。
一个例子:一个用户当初既想应用打印机,又想玩游戏。
假如只有一个过程(先不谈多线程):
从操作系统的层面看,咱们应用打印机的步骤有如下:
- 1)应用 CPU 执行程序,去硬盘读取须要打印的文件,而后 CPU 会长工夫的期待,直到硬盘读写实现;
- 2)应用 CPU 执行程序,让打印机打印这些内容,而后 CPU 会长工夫的期待,期待打印完结。
在这样的状况下:其实 CPU 的使用率其实十分的低。
打印一个文件从头到尾须要的工夫可能是 1 分钟,而 cpu 应用的工夫总和可能加起来只有几秒钟。而前面如果单过程执行游戏的程序的时候,CPU 也同样会有大量的闲暇工夫。
应用多过程后:
当 CPU 在期待硬盘读写文件,或者在期待打印机打印的时候,CPU 能够去执行游戏的程序,这样 CPU 就能尽可能高的进步使用率。
再具体一点说,其实也进步了效率。因为在期待打印机的时候,这时候显卡也是闲置的,如果用多过程并行的话,游戏过程齐全能够并行应用显卡,并且与打印机之间也不会相互影响。
3.3 小结一下
过程,直观点说:保留在硬盘上的程序运行当前,会在内存空间里造成一个独立的内存体,这个内存体有本人独立的地址空间,有本人的堆,下级挂靠单位是操作系统。
操作系统会以过程为单位,调配系统资源(CPU 工夫片、内存等资源),过程是资源分配的最小单位。
4、什么是线程?
4.1 基本常识
晚期:操作系统中并没有线程的概念,过程是能领有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采纳的是工夫片轮转的抢占式调度形式,而过程是任务调度的最小单位,每个过程有各自独立的一块内存,使得各个过程之间内存地址互相隔离。
起初:随着计算机的倒退,对 CPU 的要求越来越高,过程之间的切换开销较大,曾经无奈满足越来越简单的程序的要求了。于是就创造了线程。
线程是程序执行中一个繁多的顺序控制流程:
- 1)是程序执行流的最小单元;
- 2)是处理器调度和分派的根本单位。
一个过程能够有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在过程的内存空间)。一个规范的线程由线程 ID、以后指令指针(PC)、寄存器和堆栈组成。而过程由内存空间(代码、数据、过程空间、关上的文件)和一个或多个线程组成。
PS:读到这里可能有的读者迷糊,感觉这和 Java 的内存空间模型不太一样,但如果你深刻的读过《深刻了解 Java 虚拟机》这本书的话你就会豁然开朗。
如上图所示:在工作管理器的过程一栏里,有道词典和有道云笔记就是过程,而在过程下又有着多个执行不同工作的线程。
4.2 任务调度
线程是什么?要了解这个概念,须要先理解一下操作系统的一些相干概念。
大部分操作系统(如 Windows、Linux)的任务调度是采纳工夫片轮转的抢占式调度形式。
在一个过程中:当一个线程工作执行几毫秒后,会由操作系统的内核(负责管理各个工作)进行调度,通过硬件的计数器中断处理器,让该线程强制暂停并将该线程的寄存器放入内存中,通过查看线程列表决定接下来执行哪一个线程,并从内存中复原该线程的寄存器,最初复原该线程的执行,从而去执行下一个工作。
上述过程中:工作执行的那一小段时间叫做工夫片,工作正在执行时的状态叫运行状态,被暂停的线程工作状态叫做就绪状态,意为期待下一个属于它的工夫片的到来。
这种形式保障了每个线程轮流执行,因为 CPU 的执行效率十分高,工夫片十分短,在各个工作之间疾速地切换,给人的感觉就是多个工作在“同时进行”,这也就是咱们所说的并发(别感觉并发有多浅近,它的实现很简单,但它的概念很简略,就是一句话:多个工作同时执行)。
多任务运行过程的示意图如下:
▲ 操作系统中的任务调度
4.3 过程与线程的区别
后面讲了过程与线程,但可能你还感觉迷糊,感觉他们很相似。确实,过程与线程有着千头万绪的关系。
上面就让咱们一起来理一理:
- 1)线程是程序执行的最小单位,而过程是操作系统分配资源的最小单位;
- 2)一个过程由一个或多个线程组成,线程是一个过程中代码的不同执行路线;
- 3)过程之间互相独立,但同一过程下的各个线程之间共享程序的内存空间(包含代码段、数据集、堆等)及一些过程级的资源(如关上文件和信号),某过程内的线程在其它过程不可见;
- 4)线程上下文切换比过程上下文切换要快得多。
以下线程与过程关系的示意图。
▲ 过程与线程的资源共享关系
▲ 单线程与多线程的关系
总之:线程和过程都是一种形象的概念,线程是一种比过程更小的形象,线程和过程都可用于实现并发。
在晚期的操作系统中并没有线程的概念,过程是能领有资源和独立运行的最小单位,也是程序执行的最小单位。它相当于一个过程里只有一个线程,过程自身就是线程。所以线程有时被称为轻量级过程(Lightweight Process,LWP)。
▲ 晚期的操作系统只有过程,没有线程
起初:随着计算机的倒退,对多个工作之间上下文切换的效率要求越来越高,就形象出一个更小的概念——线程,个别一个过程会有多个(也能够是一个)线程。
▲ 线程的呈现,使得一个过程能够有多个线程
4.4 多线程与多核
下面提到的工夫片轮转的调度形式说一个工作执行一小段时间后强制暂停去执行下一个工作,每个工作轮流执行。很多操作系统的书都说“同一时间点只有一个工作在执行”。
那有人可能就要问双核处理器呢?难道两个核不是同时运行吗?
其实:“同一时间点只有一个工作在执行”这句话是不精确的,至多它是不全面的。那多核处理器的状况下,线程是怎么执行呢?这就须要理解内核线程。
_多核 (心) 处理器是指:_在一个处理器上集成多个运算外围从而进步计算能力,也就是有多个真正并行计算的解决外围,每一个解决外围对应一个内核线程。
内核线程(Kernel Thread,KLT):就是间接由操作系统内核反对的线程,这种线程由内核来实现线程切换,内核通过操作调度器对线程进行调度,并负责将线程的工作映射到各个处理器上。
个别一个解决外围对应一个内核线程,比方单核处理器对应一个内核线程,双核处理器对应两个内核线程,四核处理器对应四个内核线程。
当初的电脑个别是双核四线程、四核八线程,是采纳超线程技术将一个物理解决外围模仿成两个逻辑解决外围,对应两个内核线程,所以在操作系统中看到的 CPU 数量是理论物理 CPU 数量的两倍,如你的电脑是双核四线程,关上“工作管理器 -> 性能”能够看到 4 个 CPU 的监视器,四核八线程能够看到 8 个 CPU 的监视器。
▲ 双核四线程在 Windows8 下查看的后果
超线程技术:就是利用非凡的硬件指令,把一个物理芯片模仿成两个逻辑解决外围,让单个处理器都能应用线程级并行计算,进而兼容多线程操作系统和软件,缩小了 CPU 的闲置工夫,进步的 CPU 的运行效率。这种超线程技术(如双核四线程)由处理器硬件的决定,同时也须要操作系统的反对能力在计算机中体现进去。
程序个别不会间接去应用内核线程,而是去应用内核线程的一种高级接口——轻量级过程(Lightweight Process,LWP),轻量级过程就是咱们通常意义上所讲的线程,也被叫做用户线程。
因为每个轻量级过程都由一个内核线程反对,因而只有先反对内核线程,能力有轻量级过程。
用户线程与内核线程的对应关系有三种模型:
- 1)一对一模型;
- 2)多对一模型;
- 3)多对多模型。
在上面的文字中,将以 4 个内核线程、3 个用户线程为例对三种模型进行阐明。
4.5 一对一模型
对于一对一模型来说:一个用户线程就惟一地对应一个内核线程(反过来不肯定成立,一个内核线程不肯定有对应的用户线程)。
这样:如果 CPU 没有采纳超线程技术(如四核四线程的计算机),一个用户线程就惟一地映射到一个物理 CPU 的内核线程,线程之间的并发是真正的并发。
一对一模型使用户线程具备与内核线程一样的长处:一个线程因某种原因阻塞时其余线程的执行不受影响(此处,一对一模型也能够让多线程程序在多处理器的零碎上有更好的体现)。
但一对一模型也有两个毛病:
- 1)许多操作系统限度了内核线程的数量,因而一对一模型会使用户线程的数量受到限制;
- 2)许多操作系统内核线程调度时,上下文切换的开销较大,导致用户线程的执行效率降落。
▲ 一对一模型
4.6 多对一模型
多对一模型将多个用户线程映射到一个内核线程上,线程之间的切换由用户态的代码来进行,零碎内核感触不到线程的实现形式。用户线程的建设、同步、销毁等都在用户态中实现,不须要内核的染指。
因而,绝对一对一模型:
- 1)多对一模型的线程上下文切换速度要快许多;
- 2)多对一模型对用户线程的数量简直无限度。
但多对一模型也有两个毛病:
- 1)如果其中一个用户线程阻塞,那么其它所有线程都将无奈执行,因为此时内核线程也随之阻塞了;
- 2)在多处理器零碎上,处理器数量的减少对多对一模型的线程性能不会有显著的减少,因为所有的用户线程都映射到一个处理器上了。
▲ 多对一模型
4.7 多对多模型
多对多模型联合了一对一模型和多对一模型的长处:将多个用户线程映射到多个内核线程上,由线程库负责在可用的可调度实体上调度用户线程。
这使得线程的上下文切换十分快:因为它防止了零碎调用。然而减少了复杂性和优先级倒置的可能性,以及在用户态调度程序和内核调度程序之间没有宽泛(且昂扬)协调的次优调度。
多对多模型的长处有:
- 1)一个用户线程的阻塞不会导致所有线程的阻塞,因为此时还有别的内核线程被调度来执行;
- 2)多对多模型对用户线程的数量没有限度;
- 3)在多处理器的操作系统中,多对多模型的线程也能失去肯定的性能晋升,但晋升的幅度不如一对一模型的高。
▲ 多对多模型
在当初风行的操作系统中,大都采纳多对多的模型。
4.8 查看过程与线程
一个应用程序可能是多线程的,也可能是多过程的,如何查看呢?
在 Windows 下咱们只须关上工作管理器就能查看一个应用程序的过程和线程数。按“_Ctrl+Alt+Del_”或右键快捷工具栏关上工作管理器。
查看过程数和线程数:
在“过程”选项卡下,咱们能够看到一个应用程序蕴含的线程数。
如果一个应用程序有多个过程,咱们能看到每一个过程,如在上图中,Google 的 Chrome 浏览器就有多个过程。
同时,如果关上了一个应用程序的多个实例也会有多个过程,如上图中我关上了两个 cmd 窗口,就有两个 cmd 过程。如果看不到线程数这一列,能够再点击“查看 -> 抉择列”菜单,减少监听的列。
查看 CPU 和内存的使用率:在性能选项卡中,咱们能够查看 CPU 和内存的使用率,依据 CPU 应用记录的监视器的个数还能看出逻辑解决外围的个数,如我的双核四线程的计算机就有四个监视器。
▲ 查看 CPU 和内存的使用率
4.9 线程的生命周期
当线程的数量小于处理器的数量时,线程的并发是真正的并发,不同的线程运行在不同的处理器上。
但当线程的数量大于处理器的数量时,线程的并发会受到一些妨碍,此时并不是真正的并发,因为此时至多有一个处理器会运行多个线程。
在单个处理器运行多个线程时,并发是一种模仿进去的状态。操作系统采纳工夫片轮转的形式轮流执行每一个线程。当初,简直所有的古代操作系统采纳的都是工夫片轮转的抢占式调度形式,如咱们相熟的 Unix、Linux、Windows 及 macOS 等风行的操作系统。
咱们晓得线程是程序执行的最小单位,也是工作执行的最小单位。在晚期只有过程的操作系统中,过程有五种状态,创立、就绪、运行、阻塞(期待)、退出。晚期的过程相当于当初的只有单个线程的过程,那么当初的多线程也有五种状态,当初的多线程的生命周期与晚期过程的生命周期相似。
▲ 晚期过程的生命周期
过程在运行过程有三种状态:就绪、运行、阻塞,创立和退出状态形容的是过程的创立过程和退出过程。
晚期过程的生命周期具体阐明如下:
创立:过程正在创立,还不能运行。操作系统在创立过程时要进行的工作包含调配和建设过程管制块表项、建设资源表格并分配资源、加载程序并建设地址空间;
就绪:工夫片已用完,此线程被强制暂停,期待下一个属于它的工夫片到来;
运行:此线程正在执行,正在占用工夫片;
阻塞:也叫期待状态,期待某一事件 (如 IO 或另一个线程) 执行完;
退出:过程已完结,所以也称完结状态,开释操作系统调配的资源。
▲ 线程的生命周期
线程的生命周期跟过程很相似:
创立:一个新的线程被创立,期待该线程被调用执行;
就绪:工夫片已用完,此线程被强制暂停,期待下一个属于它的工夫片到来;
运行:此线程正在执行,正在占用工夫片;
阻塞:也叫期待状态,期待某一事件 (如 IO 或另一个线程) 执行完;
退出:一个线程实现工作或者其余终止条件产生,该线程终止进入退出状态,退出状态开释该线程所调配的资源。
5、什么是协程?
5.1 基本常识
协程:英文 Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员本人写程序来治理的轻量级线程叫做“用户空间线程”,具备对内核来说不可见的个性。
因为是自主开拓的异步工作,所以很多人也更喜爱叫它们纤程(Fiber),或者绿色线程(GreenThread)。
正如一个过程能够领有多个线程一样,一个线程也能够领有多个协程。
5.2 协程的目标
对于 Java 程序员来说,在传统的 J2EE 零碎中都是基于每个申请占用一个线程去实现残缺的业务逻辑(包含事务)。所以零碎的吞吐能力取决于每个线程的操作耗时。
如果遇到很耗时的 I / O 行为,则整个零碎的吞吐立即降落,因为这个时候线程始终处于阻塞状态,如果线程很多的时候,会存在很多线程处于闲暇状态(期待该线程执行完能力执行),造成了资源利用不彻底。
最常见的例子就是 JDBC(它是同步阻塞的),这也是为什么很多人都说数据库是瓶颈的起因。这里的耗时其实是让 CPU 始终在期待 I / O 返回,说白了线程基本没有利用 CPU 去做运算,而是处于空转状态。而另外过多的线程,也会带来更多的 ContextSwitch 开销。
对于上述问题:现阶段行业里的比拟风行的解决方案之一就是单线程加上异步回调。其代表派是 node.js 以及 Java 里的新秀 Vert.x。
而协程的目标就是当呈现长时间的 I / O 操作时,通过让出目前的协程调度,执行下一个工作的形式,来打消 ContextSwitch 上的开销。
5.3 协程的特点
协程的特点总结一下就是:
- 1)线程的切换由操作系统负责调度,协程由用户本人进行调度,因而缩小了上下文切换,进步了效率;
- 2)线程的默认 Stack 大小是 1M,而协程更轻量,靠近 1K。因而能够在雷同的内存中开启更多的协程;
- 3)因为在同一个线程上,因而能够防止竞争关系而应用锁;
- 4)实用于被阻塞的,且须要大量并发的场景。但不适用于大量计算的多线程,遇到此种状况,更好实用线程去解决。
5.4 协程的原理
当呈现 IO 阻塞的时候,由协程的调度器进行调度,通过将数据流立即 yield 掉(被动让出),并且记录以后栈上的数据,阻塞完后立即再通过线程复原栈,并把阻塞的后果放到这个线程下来跑。
这样看上去如同跟写同步代码没有任何差异,这整个流程能够称为 coroutine,而跑在由 coroutine 负责调度的线程称为 Fiber。比方:Golang 里的 go 关键字其实就是负责开启一个 Fiber,让 func 逻辑跑在下面。
因为协程的暂停齐全由程序控制,产生在用户态上;而线程的阻塞状态是由操作系统内核来进行切换,产生在内核态上。
因而:协程的开销远远小于线程的开销,也就没有了 ContextSwitch 上的开销。
5.5 协程和线程的比拟
6、总结一下
针对下面的内容,咱们总结一下。
过程和线程的区别就是:
- 1)调度:线程作为调度和调配的根本单位,过程作为领有资源的根本单位;
- 2)并发性:不仅过程之间能够并发执行,同一个过程的多个线程之间也可并发执行;
- 3)领有资源:过程是领有资源的一个独立单位,线程不领有系统资源,但能够拜访隶属于过程的资源;
- 4)零碎开销:在创立或吊销过程时,因为零碎都要为之调配和回收资源,导致系统的开销显著大于创立或吊销线程时的开销。
过程和线程之间的分割就是:
- 1)一个线程只能属于一个过程,而一个过程能够有多个线程,但至多有一个线程;
- 2)资源分配给过程,同一过程的所有线程共享该过程的所有资源;
- 3)处理机分给线程,即真正在处理机上运行的是线程;
- 4)线程在执行过程中,须要合作同步。不同过程的线程间要利用音讯通信的方法实现同步。
那么,既然有了线程,为啥还要有协程?
思考这一样一种场景:
开发者在每个线程中只做十分轻量的操作,比方拜访一个极小的文件,下载一张极小的图片,加载一段极小的文本等。然而,这样”轻量的操作“的量却十分多。
在有大量这样的轻量操作的场景下,即便能够通过应用线程池来防止创立与销毁的开销,然而线程切换的开销也会十分大,甚至于靠近操作自身的开销。
对于这些场景,就十分须要一种能够缩小这些开销的形式。于是,协程就应景而出,非常适合这样的场景。
7、参考资料
[1] 过程、线程和协程之间的区别和分割
[2] 一篇文章了解过程、线程、协程
[3] 多过程、多线程与协程的引入
[4] 深刻计算机底层,了解线程与线程池
[5] 深刻操作系统,了解高并发中的协程
附录:更多高性能、高并发文章精选
《高性能网络编程 (一):单台服务器并发 TCP 连接数到底能够有多少》
《高性能网络编程(二):上一个 10 年,驰名的 C10K 并发连贯问题》
《高性能网络编程(三):下一个 10 年,是时候思考 C10M 并发问题了》
《高性能网络编程(四):从 C10K 到 C10M 高性能网络应用的实践摸索》
《高性能网络编程(五):一文读懂高性能网络编程中的 I / O 模型》
《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》
《高性能网络编程(七):到底什么是高并发?一文即懂!》
《以网游服务端的网络接入层设计为例,了解实时通信的技术挑战》
《知乎技术分享:知乎千万级并发的高性能长连贯网关技术实际》
《淘宝技术分享:手淘亿级挪动端接入层网关的技术演进之路》
《一套海量在线用户的挪动端 IM 架构设计实际分享(含具体图文)》
《一套原创分布式即时通讯(IM) 零碎实践架构计划》
《微信后盾基于工夫序的海量数据冷热分级架构设计实际》
《微信技术总监谈架构:微信之道——大道至简(演讲全文)》
《如何解读《微信技术总监谈架构:微信之道——大道至简》》
《疾速裂变:见证微信弱小后盾架构从 0 到 1 的演进历程(一)》
《17 年的实际:腾讯海量产品的技术方法论》
《腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面》
《以微博类利用场景为例,总结海量社交零碎的架构设计步骤》
《新手入门:零根底了解大型分布式架构的演进历史、技术原理、最佳实际》
《从老手到架构师,一篇就够:从 100 到 1000 万高并发的架构演进之路》本文已同步公布于“即时通讯技术圈”公众号。
▲ 本文在公众号上的链接是:点此进入。同步公布链接是:http://www.52im.net/thread-3357-1-1.html