论Web服务器的运行速度,谁与Nginx争锋!

译文
运维 服务器运维
本文介绍了如何在笔记本电脑上,通过Nginx处理每秒10000个请求的繁重任务。

在上一篇《Nginx风头正劲,Apache和IIS Web服务器遇到对手》文章中,我们介绍了在Web服务器系统管理员有了更多的选择;主要的替代服务器之一:开源Nginx Web服务器正在迅速发展起来。本文介绍了如何在笔记本电脑上,通过Nginx处理每秒10000个请求的繁重任务。

说得好听点,我是个不大专业的系统管理员。我年轻时从事技术支持,后来在一个运行几个UNIX系统的Windows部门担任管理员工作,这些系统大多放置在装有空调的清洁机房里,由上了年纪的员工负责维护。直到我开始管理企业级存储设备,才慢慢领教了bash外壳程序的强大功能,我那个拼凑起来的家庭网络慢慢由支持几台个人电脑的Windows 2003域变成了GNU/Linux服务器和OS X台式机及笔记本电脑组成的混合环境。

与大多数人一样,我***也决定把自己的网站放到互联网上,于是我使用Apache HTTP服务器来托管该网站。原因何在?因为我眼前就有一套Ubuntu服务器设备,而Apache服务器是我听到次数最多的Web服务器。既然Apache对大型网站来说都足够好,它对我这个小小的静态个人网站来说理应足够好,不是吗?

但没想到,Apache对我来说不太好用。下面介绍了具体原因——我用了一个周末的时间扔掉原先安装的Apache服务器,换成了Nginx的Web服务器:其守护程序占用资源少,运行速度快。

#p# 老朽系统

Apache安装起来很容易。我差点儿要写成“太”容易了;但是如果你光有一身胆量,只晓得“Apache是托管运行网站的某种软件”,就想动手安装Apache,那么恐怕面临需要摸索学习的一个过程。不过,我在网上只搜索了一两个小时以寻求帮助,钻研Apache的配置文件,就建好了网站,它还是放在互联网上的!几个月后,Ars刊登了一篇文章,介绍如何获得免费的SSL/TLS证书(http://arstechnica.com/security/news/2009/12/how-to-get-set-with-a-secure-sertificate-for-free.ar)。我立马想试一下——倒不是由于我真的很需要该证书,而是就想看看证书是如何工作的。此文刊登后没过一天,我就为自己的域获得了一份2级通配符SSL/TLS证书,我的Web服务器就有了https。

系统就这样顺利运行了好几年;但是当我开始进一步折腾Web服务器时,这一点开始显露无遗:我安装的系统尽管运行顺畅,但可以做得更好。尤其是,为Web服务器添加了Tectonicus后,我发现系统并非处于***运行状态。Tectonicus是一款沙盘游戏《Minecraft》地图渲染工具,可以生成数以百万讲的小图片,并且使用类似谷歌地图(Google Maps)的界面,将众多小图片拼接起来。即使在我的本地网络上,Apache也很难以相当快的速度来显示地图。该Web服务器的硬件配置是双核AMD E-350、2GB内存和Vertex 2固态硬盘,理应会立即显示网站的静态图像。但是htop工具显示,只要一显示Tectonicus地图,Apache进程就疯狂地占用处理器资源;屏幕慢慢填满小图片时,两个处理器核心的使用率都达到了100%。

此外,我开始在同一套服务器设备上运行一个小型维基。这使用Dokuwiki(http://www.dokuwiki.org/dokuwiki),该维基服务器可以使用皮肤,非常像MediaWiki,但是将数据存储在平面文件中,并不需要数据库。Dokuwiki需要PHP,这种广泛使用的脚本语言用在全球数量众多的Web服务器上,所以这意味着我需要将某种PHP软件包安装到我目前的环境中。

可以选择的道路有好多条。由于我轻而易举地将Apache安装到Ubuntu上——只需输入“sudo aptitude install apache2”,就得到了所谓的Apache MPM Prefork版本。这是最常安装的Apache版本,其工作方式如下:创建许多独立的Apache进程,以处理Web请求。它不是使用多个线程,而是把任务划分给多个子Apahce进程。想好好了解进程与线程的区别,请参阅关于该话题的这篇Ask Ars特写文章(http://arstechnica.com/business/news/2011/04/ask-ars-what-is-a-cpu-thread.ars)。prefork是默认的Apache安装,因为Apache是一款可以扩展的Web服务器,它可以进行定制,只要添加模块,就能执行各种实用的操作;而人们可能想要安装的一些模块以多进程方式运行时无法顺畅运行。

用进程来处理每项任务的缺点是,Apache的prefork模式比较占用内存,在负载状态下更是如此。Apache的另一种预编译版本Apache MPM worker可以作为替代方案来安装。worker有别于prefork的地方在于,worker的进程是多线程的,因而它们能够以较少的系统资源来满足更多请求的需要。这就相当于以较少的内存和处理器资源更快地提供网页。不过,由于一些Apache模块在多线程Apache环境下运行时未必能顺畅地运行,你得特意选择该版本,使用软件包管理器安装到Ubuntu以及其他GNU/Linux发行版上。

稍微搜索一下,就发现Apache worker对于使得Tectonicus更快地显示无数小图片大有帮助,但是更换后会引起PHP方面出现一些问题。内置的Apache PHP模块“mod_php”属于以多线程方式运行可能有问题的那些模式。我面临这个难题:丢弃并更换不少软件,才能从mod_php改为独立的PHP。

不过,Ars论坛成员Blacken00100的一个帖子(http://arstechnica.com/civis/viewtopic.php?p=22241073#p22241073)完全给了我新的方向。Apache结合独立式PHP也许远不如像Nginx这些占用资源少的事件驱动型Web服务器结合独立式PHP来得好。我的想法开始转变。我想,只要我做好一些基本工作,也许可以一路过来,看看能不能安装被广泛认为是当今世界上运行速度最快的Web服务器:Nginx。

后起之秀

Nginx是一款占用资源少的Web服务器,以超快的运行速度超快而出名。它与Apache根本不一样:Apache是进程和线程驱动型的应用软件,而Nginx是事件驱动型的应用软件。这种设计上的差异所带来的实际影响是,少量的Nginx“worker”进程就能处理一大堆的请求,进程之间不用等待对方,也不用同步;它们只要“闭上眼睛”,就能尽快地一口一口地吃掉大象(喻指繁重任务)。

相比之下,Apache处理大量请求的方式是,生成更多的进程来处理请求,这种做法通常耗用大量的内存。Apache看到大象后,边吃边想大象有多大,有时Apache望着面前的沉重任务会有点发愁。另一方面,Nginx完全开始吞吃。

Chris Lea在为什么使用Nginx?网页(http://wiki.nginx.org/WhyUseIt)上简明扼要地概括了两者的区别:“Apache好比是微软Word,它有100万个选项,但是你只需要其中6个。Nginx就处理那6项任务,但处理其中5项任务时速度比Apache快50倍。”

Nginx在提供静态文件时——比如Tectonicus地图图片图像,表现尤为出色。对比较大的网站来说,它常常被用作前端Web服务器,以便迅速地提供没有变化的网页内容,同时将针对动态内容的请求转交给其他地方运行的更复杂的Apache Web服务器。不过,我感兴趣的是它纯粹作为一台快速运行的Web服务器。

与本文中提到的其他Web服务器一样,只要用简单的“sudo aptitude install Nginx”,很快就能从Ubuntu软件包存储库获得Nginx。我停掉Apache后,很快安装好了Nginx。遵照Blacken的建议,我还改而安装了php5-fpm,这是一款经过大量改动的PHP软件包,内置了FastCGI功能。Blacken之所以建议选用php5-fpm,而不是比较旧、比较有名的php5-cgi套件,是因为fpm能够根据服务器负载的需要来开启或关闭新的PHP进程,因而这是智能化程度高得多、功能强得大的软件包;它所消耗的资源比较少,同时在负载状态下可以透明地扩展、保持速度。

如果你的要求很简单,就像我这样,那么用php5-fpm安装可实际运行的PHP很容易。主配置文件(/etc/php5/fpm/php-fpm.conf under Ubuntu 11.10)根本不需要改动,池配置文件(/etc/php5/fpm/pool.d/www.conf)只需要稍微调整一下。池配置文件定义了php5-fpm将如何接受来自Web服务器的CGI请求。默认情况下,php5-fpm监听TCP端口9000,检查来自Web服务器的请求,但我对此作了更改,改而使用Unix套接字文件,因为让CGI请求通过本地TCP端口进来稍稍带来了一点延迟。除非你的网站在生成大量网页,否则这可能不会有什么影响;但是我想用采取“正确”的做法。另外,池配置文件让你可以指定池进程以哪个用户和用户组来运行——将这设成与Web服务器所使用的用户和用户组一模一样是个好主意。

最重要的是,池配置文件让你可以指定如果php-fpm配置成“动态”模式下,可以生成的PHP进程的最小数量和***数量。这让你开始时可以只用一两个活动进程来满足PHP请求,但你可以指令php-fpm:根据需要,生成更多的进程。唯一的实际限制是所能抽出来的内存和处理器数量。至于我这个小型网站,我将php-fpm设成一开始只有一个进程,最多可以生成10个进程。***,池配置文件让你可以指定传统的PHP配置数值,比如***内存使用量、***上传文件大小、Sendmail二进制文件的位置,等等。

#p# 配置Nginx

保存了配置文件、通过init脚本启动该守护程序后,我有了一个完全实用的PHP环境;我准备好了把注意力转向这款Web服务器。如何针对Nginx改动现有的Apache配置——这种配置包括实用的SSL/TLS支持?

结果发现,这其实相当容易,因为Nginx配置起来根本不像Apache那么复杂。对于小型网站来说,这再好不过了!如果Nginx通过软件包管理器安装在Ubuntu下,就使用类似Apache的目录结构。凡是用户可以配置的东西,都放在/etc/Nginx下;Nginx.conf文件用于存放所有的全局设置,conf.d目录用于存放需要在运行中配置里面解析和添加的额外配置文件,sites-available和sites-enabled目录用于定义实际网站及其特定配置。
 
/etc/Nginx的内容对Apache用户来说有点似曾相识。

值得注意的是Nginx不能用来配置——它不支持.htaccess文件。你想在特定子目录上完成的任何配置必须在配置文件或其中一个网站定义文件中进行。如果你在考虑改用Nginx,你的网站又高度依赖.htaccess方面的技巧,用于定义访问或用于添加重写规则或其他任何规则,就需要重新评估一下,看看你所作的各种任务是否可以改而在配置文件中再现。这还意味着,专门依赖.htaccess文件的一些Web应用程序在Nginx环境下可能无法顺畅地运行(或根本无法运行)。

尽管如此,我的网站还是很适应Nginx,主配置文件几乎不需要什么编辑。主配置文件中最重要的设置就是“worker_processes”设置,它定义了有多少个Nginx进程运行。由于一个worker进程就能同时处理数千个请求,一个可靠的经验法则就是,每个处理器核心使用一个worker进程。以我为例,我将该设置设成了2。主配置文件还让你可以指定Nginx进程将作为哪个用户来运行;由于我通过软件包管理器来安装Nginx,这预先配置成www-data用户,就跟Apache一样。

配置的其余部分在sites-available目录中进行。就像Apache那样,若使用Nginx,你在sites-available目录中创建网站定义,然后为它们创建符号链接,指向sites-enabled目录;Nginx在启动时会解析网站定义。不过,不像在Apache中非SSL和SSL各有一个不同的文件,sites-available包含的“默认”文件在里面同时定义了HTTP虚拟主机和HTTPS虚拟主机。

Nginx继承了Apache的虚拟主机概念,提供了足够多的配置选项,以满足大多数网站的要求。你可以定义虚拟主机名称、存放了所提供文件的Web根目录,然后执行任何特定的位置权限和指令。重写也在同一个文件中处理,而不是像Apache那样可能在多处执行。这会导致网站定义文件比Apache网站的来得复杂,但是配置实现了集中化。

安装SSL也有点不一样,因为Nginx不像Apache那样支持不同的链证书(chain certificate)。如果你网站的证书需要中级证书包(intermediate certificate bundle),就得把你网站的证书连入到证书包,然后才可以使用它。此外,提供带SSL/TLS的文件时,Nginx默认情况下在加密连接上使用极其安全但速度也极慢的DHE-RSA-AES256-SHA密码。如果你需要为网页提供非常可靠的加密,这很好;但是如果需要网页迅速提供,就不太好,因为它另外添加的Diffie-Hellman加密是计算密集型操作。如果你要提供加密网页,禁用DSE-RSA-AES256-SHA密码、让Nginx重新使用普通的AES256-SHA也许是个好主意。该网页(http://matt.io/technobabble/hivemind_devops_alert:_nginx_does_not_suck_at_ssl/ur)上介绍了这么做的方法,以及关于该问题的另外一些信息。

为了让Nginx正确地将PHP文件传送到安装的独立式php-fpm,只要在需要使用PHP的每一个虚拟主机下安装一个处理器(handler),就像这样:

location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php5-fpm.soc;}

这告诉Nginx:位于Web根目录下任何地方的、以.php为后缀的任何文件都应该通过/var/run/php5-fpm处的套接字与FastCGI一起传送,这个地方表明了php5-fpm进程在哪里监听出现的任务。

一个重要的提示是,Nginx与FastCGI和PHP结合使用时,存在一个众所周知的潜在安全漏洞,这个漏洞会让恶意访客得以通过PHP处理器来发送非PHP文件。这个漏洞抓住了PHP的这个特点:试图尽量帮助处理Web服务器交由它处理的任务。可以告诉PHP执行实际上并非以PHP为后缀的文件,只要为它提供以PHP为后缀的不正确文件名。可以设置php.ini中的一个选项,阻止这种情况发生,但是数量众多的流行的PHP应用程序实际上依赖这种帮忙过头的行为,所以比较容易从服务器端来处理。这就是“try_files $uri =404;”这一行的用途——它指令Nginx先试图提供它所获得的准确的统一资源标识符(URI);如果该URI并不明确存在,就报告404错误,而不是将URI传送到PHP。

网上的绝大多数Nginx + PHP教程没有提到配置方面的这个陷阱,尽管它已存在了近两年(我在这里提及,是因为它是个很容易避免的问题!)。

我对配置文件要做的其余工作涉及重写,这一切与清除Dokuwiki URL、让它们更容易阅读有关。从Apache极其丰富的重写语言转为Nginx的重写语言基本上不需要猜来测去;如果你的网站依赖大量重写,你可能不想使用Nginx。它的重写引擎其功能完全不如Apache的来得强大。 
 

这套存放在.htaccess的重写规则针对我那个托管运行的维基,用来清理URL、处理安全登录……
 

 
……Nginx中的大多数对应的重写规则

#p# 运行顺畅

好了,大功告成了。那么,Nginx运行起来到底有多好?

它运行起来确实很好。暂时不说PHP这部分,我想换成Nginx的主要原因是提供平面文件的速度。在我完全主观性的测试中,Nginx在这方面完胜Apache。Tectonicus地图以前需要数秒才能完全填满屏幕,现在立即就能填满;而且只要鼠标有什么操作,它会立即响应。拖动和缩放也很流畅、快速,不像同一个地图在Apache环境下会出现滞后、漏过,好像它架设在南极州的靠仓鼠提供动力的服务器上,而不是架设在另一头连至千兆以太网连接的局域网设备上。我满意极了。
 

 
两个Nginx worker进程和单个的PHP-FPM池进程,只用了大约14MB的物理内存。

就基于PHP的维基而言,改善幅度有点不大明显;但是无疑不比之前来得糟糕。维基上有几个图像密集型的网页,通过Apache来装入可能要花3至5秒;同样的网页装入到Nginx上所需时间大致相当。不过,Nginx+php-fpm环境占用的内存资源比我之前所用的庞大Apache prefork配置环境少得多;在处理十几个网页装入请求时,处理器的占用率也低得多。
这次更换只花了我周六的大半天时间,开始出现了几个错误,后来在网上搜索了一番,时间主要花在了试图搞定重写规则、让维基满意上。我从这次经验中学到了很多东西,尤其是Nginx的表现确实名副其实——它是一台运行速度超快的Web服务器。 

原文链接:http://arstechnica.com/business/news/2011/11/a-faster-web-server-ripping-out-apache-for-nginx.ars

责任编辑:张玉 来源: 51CTO
相关推荐

2013-11-20 13:24:16

2011-06-30 09:08:12

2010-04-12 10:01:43

Windows 7运行速度

2019-06-12 14:55:12

CentOSUbuntuWeb服务器

2018-07-20 10:12:27

租用服务器速度测试

2014-09-17 10:59:59

APP

2011-06-16 18:15:59

iCloud谷歌微软

2011-01-12 11:22:24

微软认证

2010-03-30 18:26:07

Nginx Web服务

2017-12-27 10:18:09

ApacheNginx服务器

2020-04-15 20:57:57

NginxWeb服务器

2018-08-02 16:17:34

Python 开发编程语言

2011-11-28 14:30:12

NginxApache

2011-10-14 09:16:48

NGINXApacheWeb服务器

2011-09-08 10:42:38

Web服务器Nginx

2021-11-24 08:00:00

服务器Web系统

2020-03-06 15:11:21

进程线程Web

2018-02-05 10:36:01

APP服务器WEB

2009-08-28 11:25:59

2009-01-16 14:37:57

TomcatWeb服务器应用服务器
点赞
收藏

51CTO技术栈公众号