服务器性能指标

服务器性能指标

 

服务器的性能指标

 

作为一个网络服务器程序,性能永远是第一位的指标。性能

可以这样定义:

在给定的硬件条件和时间里,

能够处理的任务量。

能够最大限度

地利用硬件性能的服务器设计才是良好的设计。

 

设计良好的服务器还应该考虑

平均服务,

对于每一个客户端,

服务器应该给予每个客户端平均的服务,

不能让

某一个客户端长时间得不到服务而发生“饥饿”的状况。

 

可伸缩性,

也就是说,

随着硬件能力的提高,服务器的性能能够随之呈线性增长。

 

实现高性能的途径

 

一个实际的服务器的计算是很复杂的,往往是混合了

IO

计算和

CPU

计算。

IO

算指计算任务中以

IO

为主的计算模型,比如文件服务器、邮件服务器等,混合

了大量的网络

IO

和文件

IO

CPU

计算指计算任务中没有或很少有

IO

,比如加密

/

解密,编码

/

解码,数学计算等等。

 

CPU

计算中,单线程和多线程模型效果

是相当的。

Win32

多线程的性能》

中说“在一个单处理器的计算机中,

基于

 CPU 

的任务的并发执行速度不可能比串行执行速度快,但是我们可以看到,在

 

Windows NT 

下线程创建和切换的额外开销非常小;对于非常短的计算,并发执

行仅仅比串行执行慢

 10%

而随着计算长度的增加,

这两个时间就非常接近了。

” 

可见,对于纯粹的

CPU

计算来说,如果只有一个

CPU

,多线程模型是不合适的。

考虑一个执行密集的

CPU

计算的服务,

如果有几十个这样的线程并发执行,

过于

频繁地任务切换导致了不必要的性能损失。

 

在编程实现上,单线程模型计算模

型对于服务器程序设计是很不方便的。

因此,

对于

CPU

计算采用线程池工作模型

是比较恰当的。

QueueUserWorkItem

函数非常适合于将一个

CPU

计算放入线程池。

线程池实现将会努力减少这种不必要的线程切换,而且控制并发线程的数目为

CPU

的数目。

 

我们真正需要关心的是

IO

计算,一般的网络服务器程序往往伴随

着大量的

IO

计算。提高性能的途径在于要避免等待

IO 

的结束,造成

CPU

空闲,

要尽量利用硬件能力,让一个或多个

IO

设备与

CPU

并发执行。前面介绍的异步

IO

APC

IO

完成端口都可以达到这个目的。

 

对于网络服务器来说,如果客户

端并发请求数目比较少的话,

用简单的多线程模型就可以应付了。

如果一个线程

因为等待

IO

操作完成而被挂起,操作系统将会调度另外一个就绪的线程投入运

行,从而形成并发执行。经典的网络服务器逻辑大多采用多线程

/

多进程方式,

在一个客户端发起到服务器的连接时,

服务器将会创建一个线程,

让这个新的线

程来处理后续事务。这种以一个专门的线程

/

进程来代表一个客户端对象的编程

方法非常直观,易于理解。

 

对于大型网络服务器程序来说,这种方式存在着局

限性。

首先,

创建线程

/

进程和销毁线程

/

进程的代价非常高昂,

尤其是在服务器

采用

TCP“短连接”方式或

UDP

方式通讯的情况下,

例如,

HTTP

协议中,

客户端

发起一个连接后,

发送一个请求,

服务器回应了这个请求后,

连接也就被关闭了。

如果采用经典方式设计

HTTP

服务器,

那么过于频繁地创建线程

/

销毁线程对性能

造成的影响是很恶劣的。

 

其次,即使一个协议中采取

TCP“长连接”,客户端

连上服务器后就一直保持此连接,

经典的设计方式也是有弊病的。

如果客户端并

发请求量很高,

同一时刻有很多客户端等待服务器响应的情况下,

将会有过多的

线程并发执行,

频繁的线程切换将用掉一部分计算能力。

实际上,

如果并发线程

数目过多的话,往往会过早地耗尽物理内存,绝大部分时间耗费在线程切换上,

因为线程切换的同时也将引起内存调页。最终导致服务器性能急剧下降,

 

对于

一个需要应付同时有大量客户端并发请求的网络服务器来说,

线程池是唯一的解

决方案。

线程池不光能够避免频繁地创建线程和销毁线程,

而且能够用数目很少

 

 

的线程就可以处理大量客户端并发请求。

 

值得注意的是,对于一个压力不大的

网络服务器程序设计,

我们并不推荐以上任何技巧。

在简单的设计就能够完成任

务的情况下,把事情弄得很复杂是很不明智,很愚蠢的行为。

 

你可能感兴趣的:(编程)