实战Nginx_取代Apache的高性能Web服务器

nginx的配置文件详解

worker_processes  24;

#指定工作衍生进程数,(一般等于CPU的总核数或者总核数的两倍,例如两个4核CPU,总核数为8)

#指定错误日志的存放路径和错误日志级别:[debug|info|notice|warn|error|crit]

worker_rlimit_nofile  51200#指定文件描述符数量

event{ use epoll}#linux 下默认的I/O网络模型,默认采用的是epoll模型。

worker_connections  65535;#允许的连接数

client_max_body_size 8m#设置客户端能够上传的文件的大小

#开启gzip压缩功能

 gzip  on;
 gzip_min_length  1k;
 gzip_buffers     4 16k;
 gzip_http_version 1.0;
 gzip_comp_level 2;
 gzip_types       text/plain application/x-javascript text/css application/xml;
 gzip_vary on;

#写个判断机制

if ($request_uri ~* ^.*\.svn.*$) {
                return 404;
        }


  if ($request_filename !~ (/index.php/jsapi|/fonts|/javascript) ) {
                rewrite ^/(.*)$ /index.php/user/$1 last;
                break;
        }

#域名重定向链接

 server {
       listen 80;
       server_name ftchinese.com;
       rewrite ^/(.*)   http://www.ftchinese.com/$1 permanent;
    }

#对于每一条日志记录,日志文件都将先打开文件,再写入日志记录,然后马上关闭,为了提高包含变量的日志文件存放路径的性能,需用open_log_file_cache指令设置经常被使用的日志文件描述符缓存。

open_log_file_cache  max=N [inactive=time] [min_uses=N] [valid=time] | off 该指令默认是禁止的

open_log_file_cache off

lnmp环境的配置和优化:

提高PHP(FastCGI),什么是FastCGI呢?

FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获取较高的性能。总所周知,CGI解释器的反复加载是CGI
性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理调度,则可以提供良好的性能、伸缩性、Fail-Over特性等。


FastCGI的工作原理是:
(1)、FastCGI进程管理自身初始化,启动多个CGI解释器进程(多个php-cgi进程)并等待来自Web Server的链接。在本文中,采用PHP-FPM进程管理器启动多个php-cgi FastCGI进程。启动php-cgi FastCGI进程时,可以配置以TCP和UNIX套接字两种方式启动。
(2)、当客户端请求到达Web服务器时,web服务器将请求采用TCP协议或者UNIX套接字方式转发到FastCGI主进程,FastCGI主进程选择并连接到一个CGI解释器(子进程)。web服务器将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。
(3)、FastCGI进程完成处理后将标准输出和错误信息从同一连接返回web服务器。当FastCGI子进程关闭连接时,请求便告知处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器的下一个连接。而在一般的普通CGI模式中,php-cgi在此时已经退出了。
   所以可以想象普通的CGI模式到底有多慢。每一个web请求PHP都必须重新解析php.ini、重新载入全部扩展并重新初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外好处是:持续数据库连接可以工作。


nginx负载均衡的主要模块之HTTP Upstream模块

Upstream模块是nginx负载均衡的主要模块,它提供了一个简单的方法来实现在轮询和客户端IP之间的后端服务器负载均衡,并可以对后端服务器进行健康检查。

ip_hash指令

语法:ip_hash

默认值:None

使用环境:Upstream

当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台服务器上。这样,当来自某个IP的用户在后端web服务器A上登录后,再访问该站点的其他URL,能保证其访问的还是后端web服务器A。如果不采用IP_hash指令,假设来自某个ip的用户在后端web服务器A上登录后,再访问该站点的其他URL,有可能被定向到后端Web服务器B,C...上,由于用户登录后session信息记录在服务器A上的,B,C...上没有,这时就会提示用户未登录。

使用ip_hash指令无法保证后端服务器的负载均衡,可能有些后端服务器接收到的请求多,有些后端服务器接收到的请求少,而且设置后端服务器权重等方法将不起作用。所以,如果后端的动态应用服务器能够做到session共享,还是建议采用后端服务器的session共享方式来代替nginx的ip_hash方式。

如果后端服务器有时要从nginx负载均衡(已使用ip_hash)中摘除一段时间,你必须将其标记为“down”,而不是直接从配置文件中删除或者注释掉该后端服务器的信息。
upstream backend{
ip_hash;
server  backend1.example.com;
server  backend2.example.com;
server  backend3.example.com down;#当原来为4台服务器时,3标记为down后,nginx仍然会按4台服务器进行哈希。如果直接注释掉,nginx会按照3台服务器进行重新哈希,原来哈希到server1 上的ip地址可能被哈希到server2上边,原来的session就会失效。

server  backend4.example.com
}


server指令

server
语法:servername[parameters]
默认值:none
使用环境:upstream
该指令用于指定后端服务器的名称和参数。服务器的名称可以是一个域名、一个ip地址、端口号或UNIX Socket。

在后端服务器名称之后,可以跟以下参数:
a、weight=NUMBER---设置服务器的权重,权重数值越高,被分配到的客户端请求数越多。如果没有权重,则为默认值权重1
b、max_fails=NUMBER---在参数fail_timeout指定的时间内对后端服务器请求失败的次数,如果检测到后端服务器无法连接或者发生服务器错误(404除外),则标记为失败。如果没有设置,则默认值为1,设为数值0将关闭这项检查。

c、fail_timeout=TIME---在经历参数max_fails设置的失败次数后,暂停的时间
d、down---标记服务器为永久离线状态,用于ip_hash指令
e、backup---仅仅在非backup服务器全部宕机或者繁忙的时候才启用。

upstream backend{
server backend1.example.com  weight=5;
server 127.0.0.1:8080   max_fails=3  fail_timeout=30s;
server unix:/tmp/backend3;
}


upstream 指令
语法:upstream name{...}
默认值:none
使用环境:http
该指令用于设置一组可以在proxy_pass和fastcgi_pass指令中使用的代理服务器,默认的负载均衡方式为轮询。示例如下:

upstream backend{
server backend1.example.com  weight=5;
server 127.0.0.1:8080   max_fails=3  fail_timeout=30s;
server unix:/tmp/backend3;
}


upstream相关变量

log_format  timing  '$remote_addr - $remote_user [$time_local]  $request '
       ' upstream_response_time $upstream_response_time'
       'msec $msec request_time $request_time';

log_format  up_head  '$remote_addr - $remote_user [$time_local]  $request '
       ' upstream_http_content_type  $upstream_http_content_type' ;   


upstream模块拥有以下的变量:

$upstream_addr
处理请求的upstream服务器地址

$upstream_status
upstream服务器的应答状态

$upstream_response_time
upstream服务器响应时间(毫秒),多个响应以逗号和冒号分割

$upstream_http_$HEADER
任意的HTTP协议头信息。如:$upstream_http_host


nginx负载均衡服务器的双机高可用

第一种方式:

(1)、www.youedomain.com域名解析到虚拟IP 61.1.1.2上。
(2)、正常情况下,主机61.1.1.4绑定虚拟IP61.1.1.2
/sbin/ifconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
/sbin/route add -host 61.1.1.2 dev eth0:1
/sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
(3)、用户访问www.youedomain.com(虚拟ip61.1.1.2)实际访问的是主机61.1.1.4.而备机61.1.1.5则处于空闲状态
(4)、如果主机61.1.1.4发送故障,备机61.1.1.5将在几秒钟之内接管虚拟ip61.1.1.2,与自己绑定,并发送ARPing包给IDC的公网网关刷新MAC地址。
/sbin/ifconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
/sbin/route add -host 61.1.1.2 dev eth0:1
/sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
(5)、这时,用户访问www.youedomain.com(虚拟ip地址为61.1.1.2)实际*问的是备机61.1.1.5,从而实现故障转移与高可用,避免了单点故障。
注意:此种方式还可以利用基于VRRP路由协议的Keepalived软件来实现。

第二种方式:
(1)、www.yourdomain.com域名通过DNS轮询解析到虚拟IP61.1.1.3和61.1.1.3上
(2)、正常情况下,server1 61.1.1.4绑定虚拟ip61.1.1.2,server261.1.1.5绑定虚拟IP地址61.1.1.3.
(3)、在server1上执行如下命令:
/sbin/ifconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
/sbin/route add -host 61.1.1.2 dev eth0:1
/sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1

(4)、在server2上执行以下命令:
/sbin/ifconfig eth0:1 61.1.1.3 broadcast 61.1.1.255 netmask 255.255.255.0 up
/sbin/route add -host 61.1.1.3 dev eth0:1
/sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1

(5)、用户访问www.yourdomain.com(虚拟ip地址为61.1.1.2和61.1.1.3)实际上是根据DNS轮询访问两天负载均衡服务器,两台服务器均处于活的状态。
(6)、如果server1发生故障,server2将在几秒钟之内接管server1的虚拟ip61.1.1.2,与自己绑定,并发送ARPing包给IDC的公网网关刷新MAC地址,server2同时绑定61.1.1.2和61.1.1.3两个虚拟ip
(7)、在server2上执行如下命令:
/sbin/ifconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
/sbin/route add -host 61.1.1.2 dev eth0:1
/sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1


nginx的Rewrite规则与实例

rewrite主要的功能就是实现url的重写,nginx的rewrite规则采用PCRE,Perl兼容正则表达式的语法进行规则匹配,如果您需要nginx的rewrite功能,在编译nginx之前,必须编译安装pcre库。

rewrite的应用:通过rewrite规则,可以实现规范的URL、根据变量来做URL转向及选择配置。例如:
一些使用MVC框架的程序只有一个入口,可以通过rewrite来实现。一些动态URL地址需要伪装成静态HTML。便于搜索引擎抓取,也需要rewrite来处理。一些用于目录结构、域名变化的旧URL,也必须跳转到新的URL上,也可以通过rewrite来处理。

rewrite指令的最后一项参数为flag标记,支持的flag标记主要有以下几种:  
  a、  last :相当于Apache里德(L)标记,表示完成rewrite;  
  b、 break;本条规则匹配完成后,终止匹配,不再匹配后面的规则  
  c、  redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址  
  d、 permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址  
  e、  last和break用来实现URL重写,浏览器地址栏URL地址不变

nginx rewrite规则相关指令有if、rewrite、set 、return、break等,其中rewrite是最关键的指令。

break指令
语法:break
默认值:none
使用环境:server,location,if
该指令的作用是完成当前的规则集,不再处理rewrite指令
示例如下:
if ($slow) {
limit_rate 10k;
break
}

if指令
语法:if(condition){...}
默认值:none
使用环境:server,location
该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。if指令不支持嵌套,不支持多个条件&&和||处理。

以下信息可以被指定为条件:
(1)变量名:错误的值包括:空字符串"",或者任何以0开始的字符串;
(2)变量比较可以使用"="(表示等于)和"!="(表示不等于)运算符;
(3)正则表达式模式匹配可以使用"~*"和"~"符号;

(4)“~”符号表示区分大小写字母的匹配;
(5)"~*"符号表示不区分大小写字母的匹配(例如firefox与FireFox是匹配的);
(6)“!~”和“!~*”符号的作用刚好和"~"、"!~*"相反,表示不匹配;
(7)"-f"和"!-f"用来判断文件是否存在;
(8)"-d"和"!-d"用来判断目录是否存在;
(9)"-e"和"!-e"用来判断文件或目录是否存在;
(10)"-x"和"!-x"用来判断文件是否可执行。

部分正则表达式可以在圆括号"()"内,其值可以通过后面的变量$1至$9访问,示例:


if ($http_user_agent ~MSIE) {
   rewrite ^(.*)$ /mise/$1 break;
}

return指令
语法:return code
默认值:none
使用环境:server,location,if
该指令用于结束规则的执行并返回状态码给客户端。状态码可以这些值:204,400,402~406,408,410,411,413,416及500~504。此外,非标准状态码444将以不发送任何Header头的方式结束连接。

注意:某些代理服务器在DNS查询超时时会返回400或者500的错误.

rewrite指令
语法:rewrite regex replacement flag
默认值:none
使用环境:server,location,if
该指令根据表达式来重定向URI,或者修改字符串。指令根据配置文件中的顺序来执行。
注意:重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,代码如下:
if ($host ~* www\.(.*)) {
set $host_without_www $1;
rewrite ^(.*)$ http://$host_without_www$1 permanent;#$1contains '/foo',not 'www.mydomain.com/foo'
}

如果替换串以http://开头,将会采用301或302跳转进行URL重定向

在以上的标记中,last和break用来实现URI重写,浏览器地址栏的URL地址不变,但在服务器访问的路径发生了变化。redirect和permanent用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址。
last和break标记的实现功能类似,但二者之间有细微的差别,使用alias指令时必须用last标记,使用proxy_pass指令时要使用break标记。last标记在本条rewrite规则执行完毕后,会对其所在的server[......]标签重新发起请求,而break标记则在本条规则匹配完成后,终止匹配,不再匹配后面的规则。如下:必须使用break标记,使用last会导致死循环:

location /cms/{
  proxy_pass http://test.yourdomain.com;
  rewrite "^/cms/(.*)\.html$" /cms/index.html break;
}

因此,一般在根location中(即location /{...})或直接在server标签中编写rewrite规则,推荐使用last标记,在非根location中(例如:location /cms/{...}),
则使用break标记。如:
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;

location /download {
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
return 403;
}

如果被替换的URI中含有参数(即类似/app/test.php?if=5之类的URI),默认情况下参数会被自动附加到替换串上,你可以通过在替换串的末尾加上?标记来解决这一问题。
rewrite ^/users/(.*)$  /show?user=$1? last;

下面我们来比较一下,不加?标记和加上?标记的URL跳转区别:
rewrite ^/test(.*)$ http://www.yourdomain.com/home  permanent;
访问http://www.yourdomain.com/home/test?id=5 经过301跳转后的URL地址为:http://www.yourdomain.com/home?id=5
rewrite ^/test(.*)$ http://www.yourdomain.com/home? permanent;
访问http://www.yourdomain.com/home/test?id=5经过301跳转后的URL地址为http://www.yourdomain.com/home
注意:对于({和})来说,他们既能用在重定向的正则表达式里,也能用在配置文件里分割代码块,为了避免冲突,正则表达式里如果带花括号,应该用双引号(会在单引号)包围。如下:
/photos/123456
重定向到:
/path/photos/12/1234/123456.png
可以用以下方法(注意双引号):
rewrite "/photos/([0-9]{2})([0-9]{2})([0-9]{2})"
/path/to/photos/$1/$1$2/$1$2$3.png;

set指令
语法:set variable value
默认值:none
使用环境:server,location,if
该指令用于定义一个变量,并给变量赋值。变量的值可以是文本、变量及文本变量的联合。
示例:
set $varname 'hello';

uninitialized_variable_warn 指令
语法:uninitialized_variable_warn on|off
默认值:uninitialized_variable_warn on
使用环境:http,server,location,if
该指令用于开启或关闭记录关于未初始化变量的警告信息,默认值为开启。

nginx的rewrite规则编写示例:
文件和目录不存在时,重定向到某个PHP文件上。适用于WordPress 等MVC结构的开源博客系统:

#-e filename 如果 filename存在,则为真
if (!-e $request_filename){
    rewrite ^/(.*)$  /index.php  last;
}

多目录转成参数 abc.domain.com/sort/2 =>abc.domain.com/index.php?act=sort&name=abc&id=2:

if ($host ~* (.*)\.domain\.com) {
    set $sub_name $1;
    rewrite ^/sort\/(\d+)\/?$  /index.php?act=sort&cid=$sub_name&id=$1 last;
}

目录对换 /123456/xxxx ->/xxxx?id=123456:
rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;

如果客户端使用IE浏览器,则重定向到/nginx-ie目录下:
if ($http_user_agent ~ MSIE) {
   rewrite ^(.*)$ /nginx-ie/$1 break;
}

禁止访问多个目录:
location ~^/(cron|templates)/{
    deny all;
    break;
}

禁止访问以/data开头的文件:
location ~^/data { 
    deny all;
}

设置某些类型文件的浏览器缓存时间:
location ~ .*\.(gif|jpg|jpeg|pnf|bmp|swf)$ 
{
    expires 30d;
 }
location ~ .*\.(js|css)?$ 
{
    expires 1h;     
}
将多级目录下的文件转换成一个文件/job-1234-456-789.html指向job/123/456/789.html:
rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;


禁止访问以.sh 、 .flv 、 .mp4为文件名后缀的URL地址:
location ~ .*\.(sh|flv|mp4)?$  {return 403;}

由以上示例可以看出,Apache的rewrite规则改为nginx的rewrite规则,其实很简单:Apache的rewriterule指令转换成nginx的rewrite指令,Apache的[L]标记换成nginx的last标记,中间的内容不变。
如果Apache的rewrite规则改为nginx的rewrite规则后,使用nginx -t命令检查发现nginx.conf配置文件有语法错误(主要是大括号引起的),那么可以尝试给条件加上引号。如下为错误:
rewrite ^/([0-9]{5}).html$ /x.jsp?id=$1  last;
加上引号就正确了:
rewrite "^/([0-9]{5}).html$"  /x.jsp?id=$1  last;


apache 与nginx的rewrite规则在URL跳转时有细微的区别:
Apache rewrite的规则,如下:
RewriteRule ^/html/tagindex/([a-zA-Z])/.*$/$1/ [R=301,L]
nginx 的规则:
rewrite ^/html/tagindex/([a-zA-Z]+)/.$ http://$host/$1  permanent;
Apache与nginx的rewrite规则在变量名称方面也有区别。

介绍:Apache和nginx rewrite规则的一些功能相同或者类似的指令、标记对应关系
Apache的RewriteCond指令对应nginx的if指令

Apache的RewriteRule指令对应nginx的rewrite指令;

Apache的[R]标记对应nginx的redirect标记

Apache的[P]标记对应nginx的last标记

Apache的[R,L]标记对应nginx的redirect标记;

Apache的[P,L]标记对应nginx的last标记;

Apache的[PT,L]标记对应nginx的last标记;

nginx的web缓存服务

nginx的web缓存服务器主要有proxy_cache相关指令集和fastCGI相关指令集构成,前者用于反向代理时,对后端内容源服务器进行缓存,后者主要用于对fastCGI的动态程序进行缓存。


proxy_cache相关指令集

1、proxy_cache指令
语法:proxy_cache zone_name;
默认值:None
使用环境:http,server,location
该指令用于设置哪个缓存区将被使用,zone_name值为proxy_cache_path指令创建的缓存区的名称。

2、proxy_cache_path
语法:proxy_cache_path path[level=number] keys_zone=zone_name:zone_size[inactive=time] [max_size=size]

默认值:None 
使用环境:http
该指令用于设置缓存文件的存放路径:示例如下:
proxy_cache_path  /data0/proxy_cache_dir  levels=1:2  keys_zone=cache_one: 500m inactive=1d max_size=30g;
注意:该指令只能在http标签内配置,levels指定该缓存空间有两层目录,第一层目录为1个字母,第二层为2个字母,保存的文件名会类似/data0/proxy_cache/c28/brwvfege3454565555555-er4t54t5g5665c;keys_zone参数用来为这个缓存区起名,500m指内存缓存空间大小500MB;
inactive的1d指如果缓存数据在1天内没有被访问,将被删除;max_size的30g是指磁盘缓存空间为30G。

3、proxy_cache_methods指令
语法:proxy_cache_methods[GET HEAD POST]
默认值:proxy_cache_methods GET HEAD;
使用环境:http,server,location
该指令用于设置缓存那些http方法,默认缓存http get/head方法。不缓存http post 方法;

4、proxy_cache_min_uses指令
语法:proxy_cache_min_uses the_number;
默认值:proxy_cache_min_uses 1;
使用环境:http、server、location
该指令用于设置缓存的最小使用次数,默认为1

5、proxy_cache_valid指令
语法:proxy_cache_valid reply_code[reply_code...]time;
默认自:None
使用环境:http、server、location

该指令用于对不同返回状态码的URL设置不同的缓存时间,例如:
proxy_cache_valid 200 302 10m; #设置200,302状态的URL缓存10分钟
proxy_cache_valid 404 1m;#设置404的缓存时间为1分钟

proxy_cache_valid  5m;#如果不指定状态码,直接指定缓存时间,则只有200 301 302 状态的URL缓存5分钟。


proxy_cache_valid  200 302 10m;
proxy_cache_valid  301  1h;
proxy_cache_valid  any 1m;#对没有单独设置的状态码,全部设置缓存时间为1分钟。

6、proxy_cache_key指令
语法:proxy_cache_key  line;
默认值:None
使用环境:http,server,location
该指令用于设置web缓存的key值,nginx根据key值md5哈希存储缓存。一般根据$host(域名)、$request_uri(请求路径)等变量组合成proxy_cache_key。
如:proxy_cache_key   "$host:$server_port$uri$is_args$args";


注意:通过ngx_cache_purge模块编译安装到nginx中,用来清除指定URL的缓存。










本文转自 妙曼  51CTO博客,原文链接:http://blog.51cto.com/yanruohan/1950751,如需转载请自行联系原作者
上一篇:数据库查询优化器论文列表


下一篇:Android利用广播监听按下HOME和RECENT_APPS键