注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

mie

 
 
 

日志

 
 

Windows完成端口模型(IOCP)的服务器程序性能优化(设想)  

2011-07-14 13:39:36|  分类: 网络开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
       Windows完成端口模型(IOCP)的服务器程序性能优化的几点设想。

       计算机理论,可以说就是生产者和消费者的资源调度优化理论。程序的优化,就是以最少的消费换取最大的生产。在计算机的世界里,我们的设计原则是,“生产得多的可以多消费,但尽量少消费”。所以,一般情况下,对于“while(1);”这样的死循环代码,我们表示最崇高的敬意,它会导致CPU空转(资源极度消耗,40-50%的CPU使用率)。
       很多时候,我们走进了别人设计的误区中。比如,链表,没有人规定链表就必须是链状的,然而,我们却往往因为思维定式,认为链表必然就是链状。于是,链表的查找等操作就必须从头部遍历。然而,如果把链表设计成闭合的环路,那么,很多操作就变得更加简单。例如,内存置换算法中的最近未使用调度算法,就可以借此优化。

(1)单线程模式
       在完成端口模型中,微软建议,线程数是CPU的核数×2。于是,大部分人都这么写。接下来,我们不得不重组被完成端口打乱了的TCP数据流,其中,不排除重组失败(如果算法设计得不太好的话)。
       为什么不能一个线程接收?一个线程真的会影响性能?我们假设一个线程,在一秒内,这个线程固定地得到了100毫秒的CPU时间片,其中,线程拿出80%的CPU时间用来进行IO操作,也就是0.8×(10的八次幂)纳秒。假设,5纳秒(ns)可以写内存1个字节。那么,数据传输的速度可以达到0.2 × 0.8×(10的八次幂)字节,约16MB/s,要使这样的吞吐量满负荷运载,需要16×8=150Mb的网卡。
      可以看到,单线程足可满足我们的大部分的需求。而我们省去了大量的数据包重组的时间,同时可以简化数据报文的结构。

      当然,也可以多线程。我们可以创建多个完成端口,将不同的客户端的socket加入到不同的完成端口,而每个完成端口的IO处理线程只有一个。这样,即可抽象出常规的服务器模型。

(2)多进程模式
        和上面差不多。不过,将多线程换成多进程。

(3)客户端断开连接的处理
        以往,我的做法是,加锁。
        对于如何提高新增用户连接的响应速度方面,我之前简单测试过,每秒新增几千个客户端,是不难做到的,主要是找到速度的瓶颈。现在,我们来假想一种极端情况(TCP连接)。随着用户量的大增,客户端拥有30万的并发数,服务器不堪负载了,乃至于一个客户端断开和服务器的连接,服务器都得处理很久。
        我们通常遇到几种客户端断开连接的情况。(a)服务器主动关闭连接;(b)客户端主动关闭连接;(c)客户端异常关闭连接(进程崩溃等);(d)客户端的系统崩溃,用户拔掉网线,客户端断网等。(a)(b)(c)三种情况,服务器都是可以得到通知的,而对于(d),由于TCP协议栈(驱动层)没有给服务器发送断开TCP连接的“四次握手”数据报文,所以,情况比较复杂。对于这种情况,如果不作特殊处理,默认情况下,我们只能等待服务器的TCP协议栈发送主动保持连接的数据报文,从而侦测到连接丢失。
        无论是哪种情况,现在,连接已经中断,服务器程序得知通知了,该如何处理?锁定客户端列表,然后查找到指定的节点,然后回收客户端资源(中断或者取消数据库查询等请求、回收内存、向数据库记录一些信息等),最后删除客户端节点。然后,解锁。
        这种处理很合乎常理。但是,很低效!

       (a)由于锁定了客户端列表,所以,新增的客户端无法加入到列表,导致其他线程等待。
       (b)逐个查找,30万个客户端节点,查找到什么时候呢?!(可以使用Hash算法优化)
       (c)回收资源时,比如,取消数据库查询,那么,必须得等待其他线程响应,如果其他线程正阻塞处理某个操作,那么,就有一定的延迟。

关于(a),尽量减少锁的使用。任何锁都是可以被替代的
关于(b),Hash算法,或者借鉴内存管理方面的页表和二级页表的思路。
关于(c),设置标记,放到另外一个队列中处理,利用“PostMessage”代替“SendMessage”。


By:zhanyonhu

  评论这张
 
阅读(1586)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016