本文主要介绍Linux系统安装HTTP服务器——Nginx、并在不改变原有网站结构的条件下用Nginx来提升网站的访问速度。
Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了。Igor 将源代码以类BSD许可证的形式发布。尽管还是测试版,但是,Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。
根据最新一期(08年6月份)的NetCraft调查报告显示,已经有超过两百万的主机使用了Nginx,这个数字超过了另外一个轻量级的HTTP服务器lighttpd, 排名第四,并且发展迅速。下面是这份报告的前几名的报表:
| 产品 | 网站数 | 
| Apache | 84,309,103 | 
| IIS | 60,987,087 | 
| Google GFE | 10,465,178 | 
| Unknown | 4,903,174 | 
| nginx | 2,125,160 | 
| Oversee | 1,953,848 | 
| lighttpd | 1,532,952 | 
关于这期调查报告的更详细信息请看下面链接:
http://survey.netcraft.com/Reports/200806/
下图是最近几个月使用Nginx和lighttpd的网站数比较
	 
使用Nginx前必须了解的事项
1. 目前官方Nginx并不支持Windows,你只能在包括Linux、UNIX、BSD系统下安装和使用;
2. Nginx本身只是一个HTTP和反向代理服务器,它无法像Apache一样通过安装各种模块来支持不同的页面脚本,例如PHP、CGI等;
3. Nginx支持简单的负载均衡和容错
4. 支持作为基本HTTP服务器的功能,例如日志、压缩、Byte ranges、Chunked responses、SSL、虚拟主机等等,应有尽有。
在Linux下安装Nginx
为了确保能在Nginx中使用正则表达式进行更灵活的配置,安装之前需要确定系统是否安装有PCRE(Perl Compatible Regular Expressions)包。你可以到 ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ 下载最新的PCRE源码包,使用下面命令下载编译和安装PCRE包:
# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.7.tar.gz # tar zxvf pcre-7.7.tar.gz # cd pcre-7.7 # ./configure # make # make install
接下来安装Nginx,Nginx一般有两个版本,分别是稳定版和开发版,你可以根据你的目的来选择这两个版本的其中一个,下面把Nginx安装到/opt/nginx目录下的详细步骤:
# wget http://sysoev.ru/nginx/nginx-0.6.31.tar.gz # tar zxvf nginx-0.6.31.tar.gz # cd nginx-0.6.31 # ./configure --with-http_stub_status_module –prefix=/opt/nginx # make # make install
其中参数--with-http_stub_status_module 是为了启用nginx的NginxStatus功能,用来监控Nginx的当前状态。
安装成功后/opt/nginx目录下有四个子目录分别是:conf、html、logs、sbin。其中Nginx的配置文件存放于conf/nginx.conf,Nginx只有一个程序文件位于sbin目录下的nginx文件。确保系统的80端口没被其他程序占用,运行 sbin/nginx 命令来启动Nginx,打开浏览器访问此机器的IP,如果浏览器出现Welcome to nginx! 则表示Nginx已经安装并运行成功。
常用的Nginx参数和控制
1.程序运行参数
Nginx安装后只有一个程序文件,本身并不提供各种管理程序,它是使用参数和系统信号机制对Nginx进程本身进行控制的。Nginx的参数包括有如下几个:
-c <path_to_config> 使用指定的配置文件而不是conf目录下的nginx.conf。
-t 测试配置文件是否正确,在运行时需要重新加载配置的时候,此命令非常重要,用来所修改的配置文件没有语法错误。
-v 显示nginx版本号。
-V 显示nginx的版本号以及编译环境信息以及编译时的参数。
例如我们要测试某个配置文件是否书写正确,我们可以使用以下命令
sbin/nginx –t –c conf/nginx2.conf
2.通过信号对Nginx进行控制
Nginx支持下表中的信号:
| 信号名 | 作用描述 | 
| TERM, INT | 快速关闭程序,中止当前正在处理的请求 | 
| QUIT | 处理完当前请求后,关闭程序 | 
| HUP | 重新加载配置,并开启新的工作进程,关闭就的进程,此操作不会中断请求 | 
| USR1 | 重新打开日志文件,用于切换日志,例如每天生成一个新的日志文件 | 
| USR2 | 平滑升级可执行程序 | 
| WINCH | 从容关闭工作进程 | 
有两种方式来通过这些信号去控制Nginx,第一是通过logs目录下的nginx.pid查看当前运行的Nginx的进程ID,通过 kill –XXX <pid> 来控制Nginx,其中XXX就是上表中列出的信号名。如果你的系统中只有一个Nginx进程,那你也可以通过killall命令来完成,例如运行killall –s HUP nginx 来让Nginx重新加载配置。
配置Nginx
先来看一个实际的配置文件:
user  nobody;#工作进程的属主 
worker_processes  4;#工作进程数,一般与CPU核数等同 
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    use epoll;#Linux下性能最好的event模式 
    worker_connections  2048;#每个工作进程允许最大的同时连接数 
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] $request '
    #                  '"$status" $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log  off;
    access_log  logs/access.log;#日志文件名 
    sendfile        on;
    #tcp_nopush     on;
    tcp_nodelay     on;
    keepalive_timeout  65;
    include gzip.conf;
            
    #集群中的所有后台服务器的配置信息 
    upstream tomcats {
        server 192.168.0.11:8080 weight=10; 
        server 192.168.0.11:8081 weight=10;
        server 192.168.0.12:8080 weight=10;
        server 192.168.0.12:8081 weight=10;
        server 192.168.0.13:8080 weight=10; 
        server 192.168.0.13:8081 weight=10;
    }
    server {
        listen       80;#HTTP的端口 
        server_name  localhost;
        charset utf-8;
        #access_log  logs/host.access.log  main;
        location ~ ^/NginxStatus/ {
            stub_status on; #Nginx状态监控配置 
            access_log off;
        }
        location ~ ^/(WEB-INF)/ {
            deny all;
        }
        location ~* \.(htm|html|asp|php|gif|jpg|jpeg|png|bmp|ico|rar|css|js|zip|java|jar|txt|flv|swf|mid|doc|ppt|xls|pdf|txt|mp3|wma)$ {
            root /opt/webapp;
            expires 24h;
        }
        location / {
            proxy_pass http://tomcats;#反向代理 
            include proxy.conf;
        }
        error_page 404 /html/404.html;
        # redirect server error pages to the static page /50x.html
        #
        error_page 502 503 /html/502.html;
        error_page 500 504 /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
Nginx监控
上面是一个实际网站的配置实例,其中灰色文字为配置说明。上述配置中,首先我们定义了一个location ~ ^/NginxStatus/,这样通过http://localhost/NginxStatus/就可以监控到Nginx的运行信息,显示的内容如下:
Active connections: 70 server accepts handled requests 14553819 14553819 19239266 Reading: 0 Writing: 3 Waiting: 67 NginxStatus显示的内容意思如下: active connections – 当前Nginx正处理的活动连接数 server accepts handled requests --总共处理了 14553819 个连接, 成功创建 14553819 次握手 (证明中间没有失败的), 总共处理了 19239266 个请求 (平均每次握手处理了 1.3个数据请求) reading -- nginx 读取到客户端的Header信息数 writing -- nginx 返回给客户端的Header信息数 waiting -- 开启 keep-alive 的情况下,这个值等于 active - (reading + writing),意思就是Nginx说已经处理完正在等候下一次请求指令的驻留连接
静态文件处理
通过正则表达式,我们可让Nginx识别出各种静态文件,例如images路径下的所有请求可以写为:
    location ~ ^/images/ {
        root /opt/webapp/images;
    }
而下面的配置则定义了以几种文件类型的请求处理方式。
location ~ \.(htm|html|gif|jpg|jpeg|png|bmp|ico|css|js|txt)$ {
    root /opt/webapp;
    expires 24h;
}
对于例如图片、静态HTML文件、js脚本文件和css样式文件等,我们希望Nginx直接处理并返回给浏览器,这样可以大大的加快网页浏览时的速度。因此对于这类文件我们需要通过root指令来指定文件的存放路径,同时因为这类文件并不常修改,通过expires指令来控制其在浏览器的缓存,以减少不必要的请求。expires指令可以控制HTTP应答中的“Expires”和“Cache-Control”的头标(起到控制页面缓存的作用)。你可以使用例如以下的格式来书写Expires
expires 1 January, 1970, 00:00:01 GMT; expires 60s; expires 30m; expires 24h; expires 1d; expires max; expires off;
动态页面请求处理
Nginx本身并不支持现在流行的JSP、ASP、PHP、PERL等动态页面,但是它可以通过反向代理将请求发送到后端的服务器,例如Tomcat、Apache、IIS等来完成动态页面的请求处理。前面的配置示例中,我们首先定义了由Nginx直接处理的一些静态文件请求后,其他所有的请求通过proxy_pass指令传送给后端的服务器(在上述例子中是Tomcat)。最简单的proxy_pass用法如下:
location / {
    proxy_pass        http://localhost:8080;
    proxy_set_header  X-Real-IP  $remote_addr;
}
这里我们没有使用到集群,而是将请求直接送到运行在8080端口的Tomcat服务上来完成类似JSP和Servlet的请求处理。
当页面的访问量非常大的时候,往往需要多个应用服务器来共同承担动态页面的执行操作,这时我们就需要使用集群的架构。Nginx通过upstream指令来定义一个服务器的集群,最前面那个完整的例子中我们定义了一个名为tomcats的集群,这个集群中包括了三台服务器共6个Tomcat服务。而proxy_pass指令的写法变成了:
location / {
    proxy_pass        http://tomcats;
    proxy_set_header  X-Real-IP  $remote_addr;
}
在Nginx的集群配置中,Nginx使用最简单的平均分配规则给集群中的每个节点分配请求。一旦某个节点失效时,或者重新起效时,Nginx都会非常及时的处理状态的变化,以保证不会影响到用户的访问。
总结
尽管整个程序包只有五百多K,但麻雀虽小、五脏俱全。Nginx官方提供的各种功能模块应有尽有,结合这些模块可以完整各种各样的配置要求,例如:压缩、防盗链、集群、FastCGI、流媒体服务器、Memcached支持、URL重写等等,更关键的是Nginx拥有Apache和其他HTTP服务器无法比拟的高性能。你甚至可以在不改变原有网站的架构上,通过在前端引入Nginx来提升网站的访问速度。
本文只是简单介绍了Nginx的安装以及常见的基本的配置和使用,更多关于Nginx的信息请阅读文章后面的参考资源。在这里要非常感谢我的朋友——陈磊(chanix@msn.com),他一直在做着 Nginx的中文WIKI(http://wiki.codemongers.com/NginxChs),同时也是他介绍给我这么好的一款软件。
如果你的网站是运行在Linux下,如果你并没有使用一些非常复杂的而且确定Nginx无法完成的功能,那你应该试试Nginx。
参考资源
· Nginx英文站点:http://www.nginx.net
· Nginx中文WIKI:http://wiki.codemongers.com/NginxChs
· Nginx英文WIKI:http://wiki.codemongers.com/Main
· 另外一个轻量级HTTP服务器lighttpd: http://www.lighttpd.net/
· 最新版本Nginx下载地址:http://sysoev.ru/nginx/nginx-0.6.31.tar.gz
· PCRE下载地址:ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
