基准测试的统计数据可能有令人难以置信的误导性如果其仅仅靠明显的详细分析。最近Apache的HTTPCore项目发布了一些基准测试的结果,它的标题为:
Jetty HttpCore
Linux BIO 35,342 56,185
Linux NIO 1,873 25,970
Windows BIO 31,641 29,438
Windows NIO 6,045 13,076
纵观这些结果,你可以看到HTTPCore已经尽力想出所有的情形除了windows的阻塞IO。最重要的是,Linux的Jetty的NIO性能优良是落后于HTTPCore的。
难道HTTPCore真的比Jetty快,难道Jetty NIO更慢?对于这个特殊的基准测试,答案很明显是:是的,是的。但是“这个特别的基准测试”的条件非常重要,因为这个基准测试是建立在在对Jetty用于派遣请求那种延迟的巨大惩罚之上。潜伏期通常可以权衡吞吐量,但是对这个基准测试,对介于在每秒56,000的请求到每秒8000的请求的差别在于加入了2ms的延迟。Jetty做频繁的延迟VS吞吐量的权衡,因此被这个基准严厉处罚。
[请注意,我并不是在说 HttpCore 团队做了任何错的事情,而"谎言,该死的谎言" 这个头条只是引用马克吐温的名言开个玩笑而已,他的名言是有关数字具有能阐明几乎任何事物的力量. 我的原则是批评只针对我们自己擅长的领域. 这篇博文旨在评论结果,而不是对 HttpCore 团队评头品足].
一般而言服务器的吞吐量都将会被至少是如下因素的其中之一所限制:
整个网络的容量可能会限制其最大的吞吐量. 如果每个响应大小有10kb,而整个网络的容量是 10MB/s, 那么每秒1024个请求将是那个基准饱和. HttpCore 基准测试使用了本地网络 2048B 的消息, 而本地网络基本上没有最大吞吐量这一说. 因此为了给基准测试建模,我就假定了一个有GB流量的网络, 如果没有其它因素限制的话,这个网络潜在就可能会有524288 个请求每秒的吞吐量.
可以被处理的请求数量可能受到可用CPU能力的限制。如果每一个请求需要2ms的CPU时间来进行处理,那么每一个CPU每分钟就只能处理500哥请求。对于HttpCore基准测试而言,他们有一台4个CPU的机器,并且具备简单且高效的请求处理过程,每个请求只需0.018ms, 这导致潜在的最大吞吐量为 4*1000/0.018 = 222,222 个请求每秒, 如果不受其他因素印象的话.
一般 HTTP 的每个连接都会有一个未处理的请求(除非当管道被使用了的时候(很少有这种情况)), 如此服务器的最大吞吐量可能会受到每个连接的最大吞吐量数量的限制. 一个HTTP连接的最大吞吐量主要是由每个请求来回行程时间所决定的, 例如,如果每个请求来回花了10ms,那么一个连接每分钟就只能处理100个请求. HttpCore基准测试在25个连接上每个请求来回行程花费0.45ms, 这就致使潜在的最大吞吐量为 25*1000/0.45ms = 56180 个请求每秒.
通过上面的分析我们可以看出,HttpCore受连接数和每个连接的来回时间限制,其最大的吞 吐量限定在每秒56180。更重要的是,该限定在数量上对连接数和延迟敏感。下图显示了HttpCore基准三种限制条件下,其吞吐量与连接数以及附加请 求延迟(网络或服务器端)之间的关系。
CPU’s 4 CPU time per request (ms) 0.018 Network latency (ms) 0.427 Max requests/s by CPU 222222 Request size 2048 Network bandwidth (MB) 1024 Max requests/s by bandwidth 524288
可以看出网络带宽限制(每秒524288)不是影响因子(译者注:图中纵轴最大值为240000,远小于524288,因此文中认为网络带宽限制不是影响因子)。CPU限制(每秒222222)只有在连接数超过125时才会产生影响。从图中可以看出,在HttpCore基准使用的25个连接条件下,任何附加的延迟都会造成剧烈的吞吐量下降,从每秒约60000下降的每秒不足2000.
虽然Jetty和HttpCore在这个基准下都位于红色曲线(25连接数下)中,但是HttpCore显然位于曲线的左端,Jetty因为几毫秒的延迟而位于曲线的右端。因此Jetty由于使用附加延迟(出于下面会介绍的一些好的原因)而受到这一标准的狠狠惩罚。因为这一标准正好位于红色曲线最陡峭的一部分之中(尽管在125连接数下更为明显,但我认为一些其他的限制因素会阻止HttpCore达到每秒222222的吞吐量)。
HttpCore基准的配置并不符合大多数关心吞吐量的HTTP服务器的实际情况。特别是:
本地网络存在少于一毫秒的来回延迟,而真实的网络应用延迟即使不是100秒至少也会存在10秒。
现代的浏览器会对同一主机开6个连接,因此25连接数实际仅仅代表了4个并发(连接)的用户。一个负载的HTTP服务器并发连接期望即使不是1000秒,至少也是100秒。
真实的连接大多数是懒惰的,在发送完一个响应后,几乎很难在小于1毫秒内完成另一个请求。
Java网络服务器通常用于动态网页,而动态网页的制作时间大于0.018毫秒。如果我们将CPU响应每个请求的时间提高到0.15毫秒,则CPU限制(吞吐量)将降低到每秒26667。
根据以上更加实际的假设条件更新的图表如下:
![]()
CPU’s 4 CPU time per request (ms) 0.150 Network latency (ms) 20.000 Max requests/s by CPU 26667 Request size 2048 Network bandwidth (MB) 100 Max requests/s by bandwidth 51200
通过使用这些更为实际的假设,从图中可以看出吞吐量对于附加延迟基本不敏感。在超过500连接的情况下,吞吐量被可用CPU数快速限制,而与处理每个请求的附加延迟无关。甚至在125连接情况下,附加延迟也只是少量的减少了吞吐量。这表明对于增加延迟造成的损失极小或者说没有损失,因此服务器可以考虑使用附加延迟如果其觉得有必要的话(下面会介绍)。
我建议您去下载用于绘制这些图表的程序并基于这些假设进行实验,您可以自己体会在一些(如果不是大多数)情况下,吞吐量对延迟没有那么明显的敏感。只有在HttpCore使用的那些特定假设下,延迟才是一个敏感因子。
我已经证明在现实世界中(并发和网络延迟并存),对处理每个请求的附加延迟不会对吞吐量带来明显的影响。那么为什么Jetty对每个请求还会使用比HttpCore更长的延迟呢?
根据该标准配置的HttpCore NIO服务器每个CPU使用单一线程,每个CPU将所有连接中的一部分锁定为一个选择集进行处理。每个进程读取一个请求,进行响应,然后回到选择集查找下一个连接并进行下一个请求的读取。这种方法很有效,但是只有在所有请求处理中无阻塞情况才可以。如果在处理某个请求的过程中由于某种原因(比如对一个慢客户端进行响应写入,等待数据库,等待同步锁等等)发生阻塞,处于同一选择集中的其他所有请求都将被阻塞,吞吐量就会大大降低。对于一个4核CPU机器,其只需要连接四个慢客户端或者进行四个长时间数据库查询就会阻塞整个服务器并阻止其他请求进行处理。HttpCore基准中使用简单的非阻塞请求执行程序和非慢客户端、网络和数据库来避免这种情况(阻塞)的发生。
在大多数现实HTTP部署服务器中,允许一个请求因为线程资源不足而阻塞其他请求是不可接受的。因此,大多数HTTP服务器使用线程池运转,并将每一个请求的处理派遣到不同的处理NIO选择集的线程中。 因为每个请求都是在专用的线程中进行处理,所以即使它阻塞也不会影响到其他的请求或者降低整个服务器的吞吐量。
当一个请求被派遣到线程池时,它往往会在作业队列中等待几毫秒以确定哪个线程对其进行处理。在大多数现实情形中,这一增加的延迟影响极小或没有,益处却非常大。但是在HttpCore基准(测试)中,这一延迟却被狠狠批判,因为延迟拖慢了响应速度,从而拖慢了发送下一请求的负载发生器。吞吐量的降低是因为客户端发送了更少的请求,而不是因为服务器处理不了他们。
同时本基准(测试)中将HttpCore的简化HTTP组件和Jetty的富服务器环境进行对比。Jetty需要花费额外的CPU/延迟去建立这一服务器环境,从而提供给应用开发者许多基础便利性。Jetty也可以配置为简单HTTP处理器,从而占用更少的CPU并使用更短的延迟。
HttpCore基准实质上比较的是苹果和橘子(译者注:两码事儿)。该基准建立的目的更多的是用来测量HttpCore对HTTP解析/生成能力的原始速度,并不算是一个真实的负载测试。Jetty配置作为拥有大量空闲连接的通用应用服务器和HTTP服务器使用是最优的。鉴于这种差距,我个人认为Jetty在某些情形中拥有相同的,甚至有时更好的表现,这是非常了不起的。这表明Jetty自己的HTTP解析/产生(能力)是出众的,如果将Jetty从其线程池和服务器容器中剥离再进行比较将是非常有意思的。
如果有人想要弄清楚哪种服务器对他们来讲更快(并且不同的属性集不能指引他们进行选择),他们需要建立自己的负载产生器基准,并且该负载产生器的通信(负载)曲线能够尽可能近地接近他们的真实应用。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务