此文章配合 nginx配置文件解答    共同分享,了解。

 一、nginx服务简介
Nginx是一个高性能的HTTP和反向代理服务器

使用 Nginx 前必须了解的事项:

1)Nginx 本身只是一个 HTTP 和反向代理服务器

2)Nginx 支持简单的负载均衡和容错

3)支持作为基本 HTTP 服务器的功能

Nginx工作原理:

Nginx由内核和一系列模块组成,内核提供web服务的基本功能,Nginx的各种功能和操作都由模块来实现。Nginx的模块从结构上分为核心模块、基础模块和第三方模块。

1)核心模块: HTTP模块、EVENT模块和MAIL模块
2)基础模块: HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块
3)第三方模块: HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块及用户自己开发的模块

如果需要增加或删除模块,需要重新编译Nginx,

如果有需要动态加载模块,可以使用由淘宝网发起的web服务器Tengine,在nginx的基础上增加了很多高级特性,完全兼容Nginx,已被国内很多网站采用。

Nginx处理连接过程:

Nginx的工作模式很简单,就是采用一个master进程和多个worker工作进程:

master:
当 nginx 在启动后,会有一个 master 进程和多个 worker 进程。master进程主要用来管理worker进程,master 要做的就是:接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动重新启动新的 worker 进程。

主要完成如下工作:
1)读取并验证配置信息;
2)创建、绑定及关闭套接字;
3)启动、终止 worker 进程及维护 worker 进程的个数;
4)无须中止服务而重新配置工作;
5)控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;
6)重新打开日志文件;
7)编译嵌入式perl脚本

worker:
对于基本的网络事件,则是放在 worker 进程中来处理了。多个 worker 进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个 worker 进程中处理,一个 worker 进程,不可能处理其它进程的请求(一对一)。然而 nginx 没有专门地仲裁或连接分布的 worker,这项工作是由操作系统内核机制完成的。在启动时,创建一组初始的监听套接字,HTTP 请求和响应之时,worker 连续接收、读取和写入套接字。
worker 进程主要完成的任务包括:
1)接收、传入并处理来自客户端的连接;
2)提供反向代理及过滤功能;
3)nginx任何能完成的其它任务

异步非阻塞
异步的概念是和同步相对的,也就是不同事件之间不是同时发生的。非阻塞的概念是和阻塞对应的,阻塞是事件按顺序执行,每一事件都要等待上一事件的完成,而非阻塞是如果事件没有准备好,这个事件可以直接返回,过一段时间再进行处理询问,这期间可以做其他事情。

二、nginx相对于传统的apache服务的优缺点

apache有自带php解析功能(apache环境部署好后,不需要再启动php服务,apache自动解析php文件,机器上只要有php命令即可;但是nginx不行,nginx必须结合php服务才能解析php文件,两则服务都要启动)

存在就是理由,一般来说,需要性能的web 服务,用nginx 。
如果不需要性能只求稳定,那就用apache。
后者的各种功能模块实现得比前者,例如ssl 的模块就比前者好,可配置项多。
这里要注意一点,epoll(freebsd 上是 kqueue )网络IO 模型是nginx 处理性能高的根本理由,但并不是所有的情况下都是epoll 大获全胜的,如果本身提供静态服务的就只有寥寥几个文件,apache 的select 模型或许比epoll 更高性能。当然,这只是根据网络IO 模型的原理作的一个假设,真正的应用还是需要实测了再说的。

2)作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。在高连接并发的情况下,Nginx是Apache服务器不错的替代品: Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一. 能够支持高达 50,000 个并发连接数的响应, 感谢Nginx为我们选择了 epoll and kqueue 作为开发模型.
Nginx作为负载均衡服务器: Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理 服务器对外进行服务. Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多.
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器), Last.fm 描述了成功并且美妙的使用经验.
Nginx 是一个安装非常的简单 , 配置文件非常简洁(还能够支持perl语法), Bugs 非常少的服务器: Nginx 启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动. 你还能够不间断服务的情况下进行软件版本的升级 .
3)Nginx 配置简洁,Apach复杂;Nginx静态处理性能比Apache高3倍以上;Apache对PHP支持比较简单,Nginx需要配合其他后端用;Apache的组件比Nginx多;
4)最核心的区别在于apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程
5)nginx处理静态文件好,耗费内存少.但apache目前也有它的优势,有很多丰富的特性.所以还需要搭配着来.当然如果能确定nginx就适合需求,那么使用nginx会是更经济的方式.
6)从个人过往的使用情况来看,nginx的负载能力比apache高很多。最新的服务器也改用nginx了。而且nginx改完配置能-t测试一下配置有没有问题,apache重启的时候发现配置出错了,会很崩溃,改的时候都会非常小心翼翼现在看有好多集群站,前端nginx抗并发,后端apache集群,配合的也不错。
7)一般动态请求要apache去做,nginx只适合静态和反向。
8)从个人经验来看,nginx是很不错的前端服务器,负载性能很好,linux服务器上运营nginx,用webbench模拟10000個个静态文件请求毫不吃力。apache对php等语言的支持很好,此外apache有強大的支持网路,反正时间相对nginx更久,bug少,但是apache有先天不支持多核心处理负载鸡肋的缺点,所以建议使用nginx做前端,后端用apache。大型网站建议用nginx自代的集群功能!
9)Nginx优于apache的主要两点还体现在:Nginx本身就是一个反向代理服务器;Nginx支持7层负载均衡;其他的当然,Nginx可能会比apache支持更高的并发;Aapche因为其成熟的技术和开发社区,总体来说也有非常不错的性能,很多大公司而言还比较青睐apache。
10)你对web server的需求决定你的选择。大部分情况下nginx都优于apache,比如说静态文件处理、PHP-CGI的支持、反向代理功能、前端Cache、维持连接等等。在Apache+PHP(prefork)模式下,如果PHP处理慢或者前端压力很大的情况下,很容易出现Apache进程数飙升,从而拒绝服务的现象。
11)对于nginx,我喜欢它配置文件写的很简洁,正则配置让很多事情变得简单运行效率高,占用资源少,代理功能强大,很适合做前端响应服务器
12)Apache在处理动态有优势,Nginx并发性比较好,CPU内存占用低,如果rewrite频繁,那还是Apache更好。

常用的 Nginx 参数和控制

Nginx 安装后只有一个程序文件,本身并不提供各种管理程序,它是使用参数和系统信号机制对 Nginx 进程本身进行控制的。 Nginx 的参数包括有如下几个:
-c <path_to_config>:使用指定的配置文件而不是 conf 目录下的 nginx.conf 。
-t:测试配置文件是否正确,在运行时需要重新加载配置的时候,此命令非常重要,用来检测所修改的配置文件是否有语法错误。
-v:显示 nginx 版本号。
-V:显示 nginx 的版本号以及编译环境信息以及编译时的参数。
例如我们要测试某个配置文件是否书写正确,我们可以使用以下命令
sbin/nginx – t – c conf/nginx2.conf

当一台服务器中启用多个实例的nginx时(即开启不同端口的nginx),那么启动nginx的时候就要根据各自的nginx配置文件进行启动了,

/data/nginx/sbin/nginx  -c /data/nginx/conf/nginx.conf
/data/nginx1.9/sbin/nginx -c /data/nginx1.9/conf/nginx.conf
/opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf

有两种方式来通过这些信号去控制Nginx:
第一是通过logs目录下的nginx.pid查看当前运行的Nginx的进程ID,通过 kill – XXX <pid> 来控制 Nginx,其中 XXX 就是上表中列出的信号名。
如果系统中只有一个Nginx进程,那也可以通过 killall 命令来完成,例如运行 killall – s HUP nginx 来让 Nginx 重新加载配置。

配置 Nginx
先来看一个实际的配置文件:

user  www;# 工作进程的属主
 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 都会非常及时的处理状态的变化,以保证不会影响到用户的访问。

^~  开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。
~  开头表示区分大小写的正则匹配
~*  开头表示不区分大小写的正则匹配
!~和!~* 分别为区分大小写不匹配及不区分大小写不匹配 的正则
/  通用匹配,任何请求都会匹配到。

多个location配置的情况下匹配顺序为(参考资料而来,还未实际验证,试试就知道了,不必拘泥,仅供参考):
首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

示例说明:
有如下匹配规则:
location = / {
#规则A
}
location = /login {
#规则B
}
location ^~ /static/ {
#规则C
}
location ~ \.(gif|jpg|png|js|css)$ {
#规则D
}
location ~* \.png$ {
#规则E
}
location !~ \.xhtml$ {
#规则F
}
location !~* \.xhtml$ {
#规则G
}
location / {
#规则H
}

产生的效果如下:
访问根目录/, 比如http://localhost/ 将匹配规则A
访问http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H
访问http://localhost/static/a.html 将匹配规则C
访问http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用, 而 http://localhost/static/c.png 则优先匹配到 规则C
访问http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写。
访问http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。
访问http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。

所以实际使用中,至少有三个匹配规则定义,如下:
直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
这里是直接转发给后端应用服务器了,也可以是一个静态首页
第一个必选规则
location = / {
proxy_pass http://tomcat:8080/index
}

第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}

第三个规则就是通用规则,用来转发动态请求到后端应用服务器
非静态文件请求就默认是动态请求,自己根据实际把握
毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
proxy_pass http://tomcat:8080/
}

 Nginx官方提供的各种功能模块应有尽有,结合这些模块可以完整各种各样的配置要求,例如:压缩、防盗链、集群、FastCGI、流媒体服务器、Memcached 支持、URL 重写等等,更关键的是Nginx拥有Apache和其他HTTP服务器无法比拟的高性能。甚至可以在不改变原有网站的架构上,通过在前端引入Nginx做负载均衡来提升网站的访问速度。

****************************************************************************************************************************************

proxy_pass的基本用法

一,在nginx中配置proxy_pass时的加不加/的问题
要注意proxy_pass后的url最后的/
当加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走
如果没有/,则会把匹配的路径部分也给代理走
例:
    location ^~ /static_js/
    {
    proxy_cache js_cache;
    proxy_set_header Host js.test.com;
    proxy_pass http://js.test.com/;
    }

如上面的配置,如果请求的url是http://servername/static_js/test.html 会被代理成http://js.test.com/test.html
而如果这么配置
例:
    location ^~ /static_js/
    {
    proxy_cache js_cache;
    proxy_set_header Host js.test.com;
    proxy_pass http://js.test.com;
    } 
如上面的配置,如果请求的url是http://servername/static_js/test.html
则会被代理到http://js.test.com/static_js/test.htm
二,关于proxy_pass配置的uri问题

你不想nginx对你的URI请求有任何形式的修改,那么,proxy_pass的配置中就不应该有任何URI部分。

举个例子,nginx服务器IP为10.0.0.20,它的配置不含URI:
location /firstcond/ {
        proxy_pass http://10.0.0.30:90;
}
那么,
原:http://10.0.0.20/first/second/test.html
转:http://10.0.0.30:90/first/second/test.html

如果配置成含URI:
location /firstcond/ {
proxy_pass http://10.0.0.30:90/myuri;
}
那么,
原: http://10.0.0.20/first/second/test.html
转:http://10.0.0.30:90/myuri/test.html
简单地说,配置了URI之后,跳转行为可能会令你感到莫名其妙。

********************************************************************************************************************************

nginx的全局变量

remote_addr              客户端ip,如:192.168.4.2
binary_remote_addr    客户端ip(二进制)
remote_port               客户端port,如:50472
remote_user               已经经过Auth Basic Module验证的用户名
host                           请求主机头字段,否则为服务器名称,如:dwz.stamhe.com
request                      用户请求信息,如:GET /?_a=index&_m=show&count=10 HTTP/1.1
request_filename         当前请求的文件的路径名,由root或alias和URI request组合而成,如:/webserver/htdocs/dwz/index.php
status                        请求的响应状态码,如:200
body_bytes_sent         响应时送出的body字节数数量。即使连接中断,这个数据也是精确的,如:40
content_length            请求头中的Content-length字段
content_type               请求头中的Content-Type字段
http_referer                 引用地址
http_user_agent           客户端agent信息,如:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11
args                            如:_a=index&_m=show&count=10
document_uri               与$uri相同,如:/index.php
document_root             针对当前请求的根路径设置值,如:/webserver/htdocs/dwz
hostname                     如:centos53.localdomain
http_cookie                  客户端cookie信息
cookie_COOKIE             cookie   COOKIE变量的值
is_args                         如果有$args参数,这个变量等于”?”,否则等于”",空值,如?
limit_rate                      这个变量可以限制连接速率,0表示不限速
query_string                 与$args相同,如:_a=index&_m=show&count=10
realpath_root                如:/webserver/htdocs/dwz
request_body                记录POST过来的数据信息
request_body_file          客户端请求主体信息的临时文件名
request_method            客户端请求的动作,通常为GET或POST,如:GET
request_uri                   包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。不能修改。如:/index.php_a=index&_m=show&count=10
scheme                         HTTP方法(如http,https),如:http
uri                                如:/index.php
request_completion        如果请求结束,设置为OK. 当请求未结束或如果该请求不是请求链串的最后一个时,为空(Empty),如:OK
server_protocol              请求使用的协议,通常是HTTP/1.0或HTTP/1.1,如:HTTP/1.1
server_addr                   服务器地址,在完成一次系统调用后可以确定这个值,如:192.168.4.129
server_name                  服务器名称,如:dwz.stamhe.com
server_port                   请求到达服务器的端口号,如:80