理解FastCGI应用的性能

阅读更多

理解FastCGI应用的性能

Mark R. Brown
Open Market, Inc.

1996年6月10号

Copyright © 1996 Open Market, Inc. 245 First Street, Cambridge, MA 02142 U.S.A.
Tel: 617-621-9500 Fax: 617-621-1703 URL: http://www.openmarket.com/
$Id: fcgi-perf.htm,v 1.4 2002/02/25 00:42:59 robs Exp $

  • 1. 介绍
  • 2. 性能要素
  • 3. 缓存技术
  • 4. 数据库访问
  • 5. 性能测试
    • 5.1 应用概况
    • 5.2 应用设计
    • 5.3 测试条件
    • 5.4 测试结果和讨论
  • 6. 多线程API
  • 7. 总结

1. 介绍

FastCGI有多块?如何对FastCGI应用的性能及使用Web服务器API实现的同样应用的性能进行比较?

当然,答案是它依赖于应用。更完整的答案是FastCGI经常以很大的差距胜出,极少输很多。

关于计算机系统性能的论文可能满是复杂的图表,显示这个如何随那个而变化。难得制作关注于为什么 一个系统比另一个快的图表。宣传材料提供的信息更少。来自某大型Web服务器厂商的广告说,它的服务器“执行Web应用比所有其他服务器快5倍”,但是广告提供的数字“5”来源的线索很少。

本文打算传述对影响Web服务应用性能的主要因素的理解,并要展示FastCGI和服务器API间的架构差异常常给FastCGI应用带来“不公平”的性 能优势。我们运行一个测试,显示FastCGI应用运行比相应的Web服务器API应用快3倍。条件不同,该系数可能大些或小些。我们向你展示要估算 (measure)你所面对的情形,你需要权衡些什么,胜于只说“我们快3倍”并继续前行。

本文不打算证明对于每个应用,FastCGI都比Web服务器API好。Web服务器API允许轻量级协议扩展,例如Open Market的安全链接(SecureLink)扩展,被加入Web服务器,也允许其他的服务器定制形式。但是,囿于高复杂性、低安全性和有限的伸缩性的 缺点,API不适合主流应用,例如私有内容或对商业(corporate)数据库的访问。FastCGI在大多数Web应用上胜出。

2. 性能要素

既然本文是关于性能的,我们需要清楚“性能”是什么。

量度如同Web这样的请求-响应系统性能的标准方法是,测量限定响应时间内的请求吞吐量峰值。例如,Web服务器应用可能在2秒内每秒执行20次请求,而响应20%的请求。

测量Web上的响应时间很难,因为链接到因特网的客户端通信具有大量不同的带宽。如果客户端读取服务器的响应很慢,则客户端和服务器上的响应时间将增长,而且服务器对此无能为力。出于制作可重复的量度的目的,客户端到服务器的通信链接应当具有高带宽。

[脚注: 当设计将通过慢速(例如14.1或28.8kb/s的猫)通道访问的Web服务器应用时,要注意同时存在的线路的瓶颈。一些服务器故意限制同时存在的线路 为100或200。如果你的应用向典型地每秒能读取2kb的客户端发送50kb数据,那么一个请求完成要用25秒。如果你的服务器被限制为100条同时存 在的线路,则吞吐量被限制为只有每秒4个请求。]

当负载很轻时响应时间很少构成问题,但是当系统在某些限制的资源上接近瓶颈时,响应时间快速上升。系统用尽的三类典型资源是网络I/O、磁盘I/O和处理 器时间。如果短响应时间是目标,则这些资源的每个都保持在或者低于50%是个好主意。例如,如果你的磁盘子系统每秒能够提供200次I/O,则设法让系统 运行在每秒100次I/O以避免磁盘子系统减缓响应时间。通过细心地管理可能成功地让运行更接近界限,但是小心地管理困难而且代价昂贵,以致很少有系统做 到。

如果Web服务器应用是Web服务器机器本地的,则其内部设计不会影响网络I/O。应用设计能显著地影响磁盘I/O和处理器时间的使用情况。

3. 缓存技术

当所需的所有信息都在其内存中可用时,罕有Web服务器应用不能快速运行。而且如果处于那些条件下应用不能快速运行,可行的解决方案明显是:调整应用耗费 处理器(processor-hungry)的部分,安装更快的处理器,或是改变应用的功能规格说明书(functional specification),这样它不需要做那么多操作。

让信息在内存中可用的方法是通过缓存技术。缓存是内存中的数据结构,含有从信息在磁盘上的持久原产地(home)读取的数据。当应用需要信息时,它查阅缓 存,如果有则使用。否则从磁盘读取信息并放置一份拷贝在缓存中。如果缓存满了,应用在加入新数据前丢弃一些旧的。当应用需要更改缓存的信息时,它更改缓存 的条目和磁盘上的信息。那样,如果应用崩溃了,不会丢失信息;应用只是在重启后的片刻运行的慢一些,因为当空时缓存不会提升性能。

缓存技术能减少磁盘I/O和处理器时间,因为从磁盘读取信息比从缓存中读占用更多处理器时间。因为专注于两个潜在的瓶颈,缓存技术是高性能Web服务器应 用设计的焦点。CGI应用不能执行内存缓存技术(in-memory caching),因为它们只处理一个请求就退出了。Web服务器API许诺解决该问题。但是那种解决方案效果如何?

现今最广泛部署的Web服务器API基于线程池服务器模型。Web服务器由一个父进程和一池子进程组成。进程不共享内存。传入的请求被随机地赋给一个空闲 的子(进程)。子(进程)在接受新请求前运行请求至完成。典型的服务器有32个子进程,大型服务器有100或200个。

内存缓存技术在这种服务器模型中效果很差,因为进程不共享内存,而且传入的请求是被随机地赋给进程。例如,要在内存中维持频繁使用的文件,服务器必须为每 个子(进程)都维持一个文件拷贝,这样浪费内存。当文件被修改时必须通知所有子(进程),这样很复杂(API不提供该功能)。

FastCGI被设计允许有效的内存缓存技术。请求被从任何子进程路由到一个FastCGI应用服务器。FastCGI应用进程维持一个内存缓存。

某些情形中单个FastCGI应用服务器不会提供足够的性能。FastCGI提供两种解决方案:会话亲和性(session affinity,也叫sticky session)和多线程技术.

你用会话亲和性运行一池应用进程,Web服务器基于请求中含有的任何信息将请求路由到专用进程。例如,服务器能依据被请求的内容区域进行路由,或者依据用 户。用户可能被应用特定的会话标识符标识,或是Open Market安全链接标签(Secure Link ticket)中含有的用户ID,或是基本认证(Basic Authentication)用户名,或其他什么东西。每个进程维持它自己的缓存,会话亲和性确保每个传入的请求有权访问缓存,那会极大地加速处理。

你用多线程技术运行一个应用进程,它被设计为同时处理多个请求。处理并发请求的线程共享进程内存,所以它们都有权访问相同的缓存。多线程编程是复杂的——并发使程序难于测试和调试——但是用FastCGI你能编写单线程 多线程应用。

4. 数据库访问

很多Web服务器应用执行数据库访问。现有的数据库含有很多有价值的信息;Web服务器应用允许公司广泛地访问这些信息。

访问数据库管理系统,即使在单台机器内部,也是通过面向连接的协议。应用“进入”数据库,创建连接,然后执行一个或多个访问。创建数据库连接的代价常常是通过既定连接访问数据的若干倍。

对于首要的(first)的近似,数据库连接只是另一类要被应用在内存中缓存的状态(state),所以上面缓存技术的论述适用于(apply to)缓存数据库连接。

但是数据库连接在某方面比较特殊:它们通常是数据库许可的主要依据。你按照数据库系统能支持的并发连结数向数据库厂商付费。100连接的许可花费比5个连 接的多很多。由此可知,每个Web服务器子进程缓存一个数据库连接不仅浪费系统硬件资源,也可能超出你的预算。

5. 性能测试

我们设计了一个测试应用来阐明性能问题。该应用表示一类提供私人内容的应用。测试应用比任何真实应用要简单很多,但是仍然阐明了主要性能问题。我们利用FastCGI和当前Web服务器的API都实现了该应用,并且测量了每个的性能。

5.1 应用概况

应用基于一个用户数据库和一组内容文件。当用户请求内容文件时,应用执行用来自用户数据库的信息在文件中执行替换。然后应用返回修改的内容给用户。

每个请求完成下面的:

  1. 身份验证检查:用户id用于检索和校验密码。
  2. 属性检索:用户id用于检索用户的所有属性值。
  3. 文件检索和过滤:请求标识一内容文件。该文件被读取而且出现的变量名被替换成用户的相应属性值。改过的HTML返还用户。

当然,这是个执行缓存以简化这些步骤中的任何一个的公平比赛。

每个用户的数据库记录(包括密码和属性值)大约100字节长。每个内容文件是3,000字节长。数据库和内容文件都存储在置于服务器平台上的磁盘中。

典型的用户以每次访问间间隔近似实际情况的思考时间(30-60秒)进行10次文件访问,然后消失一段很长的时间。

5.2 应用设计

FastCGI应用保持最近访问的来自数据库的属性值的缓存。当缓存缺失时,应用从数据库读取。因为只需要很少数量的FastCGI应用进程,所以每个进程启动时打开一个数据库连接并保持其为打开状态。

FastCGI应用被配置为多应用进程。 为了在数据库读取和文件读取期间得到并发应用处理,这是值得的。利用FastCGI的用户id为键的会话亲和性,请求被路由到这些应用进程。这种方式下,首次后的所有用户请求都命中应用的缓存。

API应用不保持缓存;API应用没法在其进程间共享缓存,所以缓存命中率太低而不能负担缓存技术的代价。API应用在每个请求上打开和关闭数据库连接;在请求间保持数据库连接打开会导致同时打开不现实的大量的数据库连接,而且每个连接利用率非常低。

5.3 测试条件

测试负载由10个HTTP客户进程产生。各进程代表相互分离的用户集。一个进程为一用户产生一个请求,然后是一不同用户的一个请求,等等,直到第一个用户产生另一个请求时。

简化起见,10个客户进程运行在同Web服务器相同的机器上。这避免了网络瓶颈会模糊测试结果的可能性。如同应用概况中规定的那样,数据库系统也运行在该机器上。

在此测试条件下,响应时间不是问题。我们只测量吞吐量。

这些测试中的API Web服务器是Netscape 1.1。

5.4 测试结果和讨论

这是测试结果:

    FastCGI  12.0 毫秒/请求 = 83 请求/秒
    API      36.6 毫秒/请求 = 27 请求/秒

倘若FastCGI应用较API应用享有重大的架构优势,那么FastCGI应用运行快很多就不奇怪了。要更深入地理解这些结构,我们再测量两种情形:

  • 带持久连接的API。如果你能避免额外的许可费用,你的API应用的运行会快多少?
        API      16.0 毫秒/请求 = 61 请求/秒
    
    答案是:仍然不能和FastCGI应用一样快。
  • 停用缓存的FastCGI。FastCGI应用从其缓存中受益多少?
        FastCGI  20.1 毫秒/请求 = 50 请求/秒
    
    答案是:极其大量的助益,即使数据库访问是相当简单的。

这两个额外的试验显示,如果API和FastCGI应用以完全相同的方式实现——缓存数据库连接但不缓存用户简介数据——API应用稍微快一些。这是预料中的,因为FastCGI应用必须负担进程间通信的代价,而API应用中不存在。

实际上这两种应用不会以相同的方式实现。FastCGI的架构优势导致更高的性能——本测试中是3倍。使用远程数据库或代价更高的数据库访问,该系数会更高。使用需要更多处理的内容文件,该系数会变小。

6. 多线程API

现在,带多线程内部结构(以及配套的API)的Web服务器开始变得更普通了。这些服务器没有第3章中描述的全部缺点。这是否意味着FastCGI的性能优势将要消失?

一个粗略的分析同意(这种观点)。单进程、多线程服务器中的基于API的应用能以FastCGI应用的方式保持缓存和数据库连接。基于API的应用不用负担进程间通信的代价,所以基于API的应用将比FastCGI应用稍微快一些。

更深入的分析否认(这种观点)。多线程编程是复杂的,因为并发使得程序更加难于测试和调试。 在对Web服务器API进行多线程编程的情形中,多线程技术的常规问题由于不同的应用间以及应用和Web服务器间不够独立而被混合了。使用 FastCGI,你能以单线程风格编写程序,得到进程隔离的所有可靠性和可维护性,并且仍然得到非常高的性能。如果真的需要多线程技术,你能编写多线程 FastCGI并且仍然从其他应用及服务器中分离出你的多线程应用。简而言之,排除相对CGI来说对FastCGI的选择,多线程技术使得Web服务器 API不适用于几乎所有的应用。在那个争论中性能赢家明显是FastCGI。

7. 总结

FastCGI到底有多快?答案是:确实非常快。不是因为它具有一些通过操作系统专门加速的(specially-greased)途径,而是因为其设计 很好地适应了多数应用的需要。我们邀请你用FastCGI作为你的Web服务器应用的快速、开放的基础。

你可能感兴趣的:(网络应用,应用服务器,Web,多线程,数据结构)