让我们来考虑一个场景,你和百万玩家的魔兽世界的忠实粉丝。时间之旅打每到周末boss。
每当周末比赛server在亚历山大,因为至少在同一时间数十万用户在线。
假设我们的多-threaded果酱server作为游戏server这是可行的?本场比赛首先分析server有什么特点:
① 网络游戏并不是像网页一样。打开一旦下载完就能够关闭连接结束。
网游必须是有一个持久有状态的连接,每个client都须要跟server存在一个持久的连接。以便高速及时发送消息。而随着并发用户数量的添加,多线程堵塞server不可能为每个client分配一个线程。
② 跟一般的应用server不同,CS结构的网络游戏一般把复杂的逻辑处理放到了client。而在游戏server端仅仅处理比較简单的逻辑,甚至仅仅是传递消息。像这样简单的逻辑我们居然给每个请求分配一条线程。这是不是严重脱离实际了?
③ 网游讲求的是响应快,消息交换及时,而且能进行双向通信。那必定须要频繁请求跟响应,假如我们已经採用了长久连接。但server并非每次都有新数据,并不须要发送给client,那我们还占了一条线程,是不是太浪费了?
从以上几点分析。像网游这种场合,我们传统的多线程server显然已经力不从心。线程池能在一定程度上缓解频繁的IO调用带来的资源占用,但池有一定的限制大小。在面对成千上万的client请求大并发情况下。却始终不是最佳方案。有没有可能用一个或少量的线程就能够维护非常多持久连接呢?以下介绍一种新的server模型——非堵塞server模型。
非堵塞server模型最重要的一个特点是,在调用某个接口后马上返回,而不会堵塞等待。如图2-6-2-1中所展示,当多个client向server请求时。server端会保存一个socket连接列表,然后有一个专门的线程对这个列表进行轮询。
假设发现某个socket有数据可读。就调用该socket的对应的读操作。反之,发现socket有数据可写的话,就调用该socket的对应的写操作;假设发现某个socket已经中断,就调用socket关闭操作。为了有更好地性能。还能够结合线程池,一旦检測到有须要处理(读数据、写数据、关闭)的socket就启动另外一条线程负责处理。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3lhbmd6aGl6aG91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
图2-6-2-1 非堵塞server模型
这样看来,无论多少个socket连接都能够被一条线程管理起来。一条线程负责遍历这些socket列表,处理再交给线程池,非常好地利用了堵塞的时间,处理能力得到提升。
但这样的模型涉及到遍历全部的socket列表,同一时候须要处理数据的拼接。空暇时也占用较多CPU资源,仍然不适于大并发场景。再稍做改进——事件驱动模型。它的核心是事件驱动,线程遍历的并不是socket列表。取而代之的是检測事件。对检測出来的事件进行逐一响应。极大提高了检測效率。自然处理能力也更强。
喜欢研究java的同学能够交个朋友,以下是本人的微信号:
版权声明:本文博主原创文章,博客,未经同意不得转载。