zoukankan      html  css  js  c++  java
  • 系统学习消息队列分享(十) 如何实现高性能的异步网络传输?

    异步与同步模型最大的区别是,同步模型会阻塞线程等待资源,而异步模型不会阻塞线程,它是等资源准备好后,再通知业务代码来完成后续的资源处理逻 辑。这种异步设计的方法,可以很好地解决IO等待的问题。

    我们开发的绝大多数业务系统,它都是IO密集型系统。跟IO密集型系统相对的另一种系统叫计算密集型系 统。通过这两种系统的名字,估计你也能大概猜出来IO密集型系统是什么意思。

    IO密集型系统大部分时间都在执行IO操作,这个IO操作主要包括网络IO和磁盘IO,以及与计算机连接的一 些外围设备的访问。与之相对的计算密集型系统,大部分时间都是在使用CPU执行计算操作。我们开发的业 务系统,很少有非常耗时的计算,更多的是网络收发数据,读写磁盘和数据库这些IO操作。这样的系统基本 上都是IO密集型系统,特别适合使用异步的设计来提升系统性能。

    应用程序最常使用的IO资源,主要包括磁盘IO和网络IO。由于现在的SSD的速度越来越快,对于本地磁盘的 读写,异步的意义越来越小。所以,使用异步设计的方法来提升IO性能,我们更加需要关注的问题是,如何 来实现高性能的异步网络传输。

    理想的异步网络框架应该是什么样的?

        在我们开发的程序中,如果要实现通过网络来传输数据,需要用到开发语言提供的网络通信类库。大部分语 言提供的网络通信基础类库都是同步的。一个TCP连接建立后,用戶代码会获得一个用于收发数据的通道。 每个通道会在内存中开辟两片区域用于收发数据的缓存。

    发送数据的过程比较简单,我们直接往这个通道里面来写入数据就可以了。用戶代码在发送时写入的数据会 暂存在缓存中,然后操作系统会通过网卡,把发送缓存中的数据传输到对端的服务器上。

    只要这个缓存不满,或者说,我们发送数据的速度没有超过网卡传输速度的上限,那这个发送数据的操作耗 时,只不过是一次内存写入的时间,这个时间是非常快的。所以,发送数据的时候同步发送就可以了,没有 必要异步。

         比较麻烦的是接收数据。对于数据的接收方来说,它并不知道什么时候会收到数据。那我们能直接想到的方 法就是,用一个线程阻塞在那儿等着数据,当有数据到来的时候,操作系统会先把数据写入接收缓存,然后 给接收数据的线程发一个通知,线程收到通知后结束等待,开始读取数据。处理完这一批数据后,继续阻塞 等待下一批数据到来,这样周而复始地处理收到的数据。

    这就是同步网络IO的模型。同步网络IO模型在处理少量连接的时候,是没有问题的。但是如果要同时处理非 常多的连接,同步的网络IO模型就有点儿力不从心了。

    因为,每个连接都需要阻塞一个线程来等待数据,大量的连接数就会需要相同数量的数据接收线程。当这些 TCP连接都在进行数据收发的时候,会导致什么情况呢?对,会有大量的线程来抢占CPU时间,造成频繁的 CPU上下文切换,导致CPU的负载升高,整个系统的性能就会比较慢。

    所以,我们需要使用异步的模型来解决网络IO问题。怎么解决呢?

    你可以先抛开你知道的各种语言的异步类库和各种异步的网络IO框架,想一想,对于业务开发者来说,一个 好的异步网络框架,它的API应该是什么样的呢?

    我们希望达到的效果,无非就是,只用少量的线程就能处理大量的连接,有数据到来的时候能第一时间处理 就可以了。

    对于开发者来说,最简单的方式就是,事先定义好收到数据后的处理逻辑,把这个处理逻辑作为一个回调方 法,在连接建立前就通过框架提供的API设置好。当收到数据的时候,由框架自动来执行这个回调方法就好了。

  • 相关阅读:
    USACO2018 DEC(Platinum) (树上乱搞,期望+凸包)
    USACO2018 DEC (Gold) (dp,容斥+哈希,最短路)
    《信息学奥赛一本通》题库 1034 计算三角形面积——基础
    UNR#3 Day1——[ 堆+ST表+复杂度分析 ][ 结论 ][ 线段树合并 ]
    bzoj 4298 [ONTAK2015]Bajtocja——哈希+启发式合并
    玲珑杯#20 C 漆黑的太阳——莫队
    链表写法
    传址函数写法
    bzoj 4650 & 洛谷 P1117 优秀的拆分 —— 枚举关键点+后缀数组
    bzoj 2119 股市的预测 —— 枚举关键点+后缀数组
  • 原文地址:https://www.cnblogs.com/wt645631686/p/11581933.html
Copyright © 2011-2022 走看看