非阻塞IO服务器模型

简介: 我们来考虑一个情形,你跟千千万万个玩家是魔兽世界的超级粉丝,每周末准时组团打boss。每当周末游戏服务器就亚历山大,因为起码几十万用户同时在线。如果用我们的多线程阻塞服务器作为游戏服务器是否可行呢?先分析游戏服务器有哪些特点:①  网络游戏并非像网页一样,打开一旦下载完就可以关闭连接结束。

我们来考虑一个情形,你跟千千万万个玩家是魔兽世界的超级粉丝,每周末准时组团打boss。每当周末游戏服务器就亚历山大,因为起码几十万用户同时在线。如果用我们的多线程阻塞服务器作为游戏服务器是否可行呢?先分析游戏服务器有哪些特点:

①  网络游戏并非像网页一样,打开一旦下载完就可以关闭连接结束。网游必须是有一个持久有状态的连接,每一个客户端都需要跟服务器存在一个持久的连接,以便快速及时发送消息。而随着并发用户数量的增加,多线程阻塞服务器不可能为每一个客户端分配一个线程。

②  跟一般的应用服务器不同,CS结构的网络游戏一般把复杂的逻辑处理放到了客户端,而在游戏服务器端只处理比较简单的逻辑,甚至只是传递消息。像这样简单的逻辑我们竟然给每一个请求分配一条线程,这是不是严重脱离实际了?

③  网游讲求的是响应快,消息交换及时,并且能进行双向通信,那必然需要频繁请求跟响应,假如我们已经采用了长久连接,但服务器并不是每次都有新数据,并不需要发送给客户端,那我们还占了一条线程,是不是太浪费了?

从以上几点分析,像网游这样的场合,我们传统的多线程服务器显然已经力不从心。线程池能在一定程度上缓解频繁的IO调用带来的资源占用,但池有一定的大小限制,在面对成千上万的客户端请求大并发情况下,却始终不是最佳方案。有没有可能用一个或少量的线程就可以维护很多持久连接呢?下面介绍一种新的服务器模型——非阻塞服务器模型。

非阻塞服务器模型最重要的一个特点是,在调用某个接口后立即返回,而不会阻塞等待。如图2-6-2-1中所展示,当多个客户端向服务器请求时,服务器端会保存一个socket连接列表,然后有一个专门的线程对这个列表进行轮询。如果发现某个socket有数据可读,就调用该socket的相应的读操作;反之,发现socket有数据可写的话,就调用该socket的相应的写操作;如果发现某个socket已经中断,就调用socket关闭操作。为了有更好地性能,还可以结合线程池,一旦检测到有需要处理(读数据、写数据、关闭)的socket就启动另外一条线程负责处理。

图2-6-2-1 非阻塞服务器模型

 

这样看来,不管多少个socket连接都可以被一条线程管理起来,一条线程负责遍历这些socket列表,处理再交给线程池,很好地利用了阻塞的时间,处理能力得到提升。但这种模型涉及到遍历所有的socket列表,同时需要处理数据的拼接,空闲时也占用较多CPU资源,仍然不适于大并发场景。再稍做改进——事件驱动模型。它的核心是事件驱动,线程遍历的并非socket列表,取而代之的是检测事件,对检测出来的事件进行逐一响应。极大提高了检测效率,自然处理能力也更强。



==========广告时间==========

鄙人的新书《Tomcat内核设计剖析》已经在京东预售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。

=========================

目录
相关文章
|
2月前
|
网络协议 安全 测试技术
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
41 2
|
3月前
|
Linux
Linux 下的五种 IO 模型详细介绍
根据上述定义,我们的前4种模型——阻塞式I/O模型、非阻塞式I/O模型、I/O复用模型和信号驱动式I/O模型都是同步I/O模型,因为其中真正的I/O操作(recvfrom )将阻塞进程。异步请求:A调用B,B的处理是异步的,B在接到请求后先告诉A我已经接到请求了,然后异步去处理,处理完之后通过回调等方式再通知A。和上面的阻塞IO模型相比,非阻塞IO模型在内核数据没准备好,需要进程阻塞的时候,就返回一个错误,以使得进程不被阻塞。阻塞请求:A调用B,A一直等着B的返回,别的事情什么也不干。
35 0
Linux 下的五种 IO 模型详细介绍
|
3月前
|
网络协议 C++ 数据格式
websocket协议介绍与基于reactor模型的websocket服务器实现
websocket协议介绍与基于reactor模型的websocket服务器实现
56 0
|
1月前
|
Java 关系型数据库 MySQL
Flink1.18.1和CDC2.4.1 本地没问题 提交任务到服务器 报错java.lang.NoClassDefFoundError: Could not initialize class io.debezium.connector.mysql.MySqlConnectorConfig
【2月更文挑战第33天】Flink1.18.1和CDC2.4.1 本地没问题 提交任务到服务器 报错java.lang.NoClassDefFoundError: Could not initialize class io.debezium.connector.mysql.MySqlConnectorConfig
50 2
|
1月前
|
分布式计算 JavaScript Java
非阻塞IO:提高应用程序的效率与性能
非阻塞IO:提高应用程序的效率与性能
|
2月前
|
网络协议 Java Linux
用Java来实现BIO和NIO模型的HTTP服务器(二) NIO的实现
用Java来实现BIO和NIO模型的HTTP服务器(二) NIO的实现
|
3月前
|
弹性计算 运维 安全
带你读《弹性计算技术指导及场景应用》——1. 所以!云服务器也可以玩转大模型?(1)
带你读《弹性计算技术指导及场景应用》——1. 所以!云服务器也可以玩转大模型?(1)
|
3月前
|
弹性计算 数据安全/隐私保护
带你读《弹性计算技术指导及场景应用》——1. 所以!云服务器也可以玩转大模型?(2)
带你读《弹性计算技术指导及场景应用》——1. 所以!云服务器也可以玩转大模型?(2)
|
3月前
|
网络协议 Linux API
基于Linux socket聊天室-多线程服务器模型(01)
基于Linux socket聊天室-多线程服务器模型(01)
46 0