课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
网络协程技术是程序员在学习高并发开发的时候需要重点掌握的编程技术之一,下面我们就通过案例分析来了解一下网络协程基本原理,下面就一起来了解一下具体情况吧。
网络协程的本质是将应用层的阻塞式IO过程在底层转换成非阻塞IO过程,并通过程序运行栈的上下文切换使IO准备就绪的协程交替运行,从而达到以简单方式编写高并发网络程序的目的。既然网络协程的底层也是非阻塞IO过程,所以在介绍网络协程基本原理前,我们先了解一下非阻塞网络通信的基本过程。
1、网络非阻塞编程
使用操作系统提供的多路复用事件引擎API(select/poll/epoll/kqueueetc),将网络套接字的网络读写事件注册到事件引擎中;
当套接字满足可读或可写条件时,事件引擎设置套接字对应的事件状态并返回给调用者;
调用者根据套接字的事件状态分别『回调』对应的处理过程;
对于大部分基于TCP的网络应用,数据的读写往往不是一次IO就能完成的,因此,一次会话过程就会有多次IO读写过程,在每次IO过程中都需要缓存读写的数据,直至本次数据会话完成。
相对于阻塞式读的处理过程,非阻塞过程要复杂很多:
一次完整的IO会话过程会被分割成多次的IO过程;
每次IO过程需要缓存部分数据及当前会话的处理状态;
要求解析器(如:Json/Xml/Mime解析器)好能支持流式解析方式,否则就需要读到完整数据后才能交给解析器去处理,当遇到业数据较大时就需要分配较大的连续内存块,必然会造成系统的内存分配压力;
当前大部分后台系统(如数据库、存储系统、缓存系统)所提供的客户端驱动都是阻塞式的,无法直接应用在非阻塞通信应用中,从而限制了非阻塞通信方式的应用范围;
多次IO过程将应用的业务处理逻辑分割的支离破碎,大大增加了业务编写过程的复杂度,降低了开发效率,同时加大了后期的不易维护性。
2、网络协程编程
小调度单元:当前大部分操作系统的小调度单元是线程,即在单核或多核CPU环境中,操作系统是以线程为基本调度单元的,操作系统负责将多个线程任务唤入唤出;
上下文切换:当操作系统需要将某个线程挂起时,会将该线程在CPU寄存器中的栈指针、状态字等保存至该线程的内存栈中;当操作系统需要唤醒某个被挂起的线程时(重新放置在CPU中运行),会将该线程之前被挂起的栈指针重新置入CPU寄存器中,并恢复之前保留的状态字等信息,从而使该线程继续运行;通过这样的挂起与唤醒操作,便完成了不同线程间的上下文切换;
并行与网络并发:并行是指同一『时刻』同时运行的任务数,并行任务数量取决于CPU核心数量;而网络并发是指在某一『时刻』网络连接的数量;类似于二八定律,在客户端与服务端保持TCP长连接时,大部分连接是空闲的,所以服务端只需响应少量活跃的网络连接即可,如果服务端采用多路复用技术,即使使用单核也可以支持100K个网络并发连接。
3、网络过程协程化步骤
每一个网络连接绑定一个套接字句柄,该套接字绑定一个协程;
当对网络套接字进行读或写发生阻塞时,将该套接字添加至IO调度协程的事件引擎中并设置读写事件,然后将该协程挂起;这样所有处于读写等待状态的网络协程都被挂起,且与之关联的网络套接字均由IO调度协程的事件引擎统一监控管理;
当某些网络套接字满足可读或可写条件时,IO调度协程的事件引擎返回这些套接字的状态,IO调度协程找到与这些套接字绑定的协程对象,然后将这些协程追加至协程调度队列中,使其依次运行;
IO事件协程内部本身是由系统事件引擎(如:Linux下的epoll事件引擎)驱动的,其内部IO事件的驱动机制和上面介绍的非阻塞过程相似,当某个套接字句柄『准备就绪』时,IO调度协程便将其所绑定的协程添加进协程调度队列中,待本次IO调度协程返回后,会依次运行协程调度队列里的所有协程。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请在707945861群中学习了解。