nginx应用总结(1)--基础认识和应用配置

时间:2022-04-23
本文章向大家介绍nginx应用总结(1)--基础认识和应用配置,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

在linux系统下使用nginx作为web应用服务,用来提升网站访问速度的经验已五年多了,今天在此对nginx的使用做一简单总结。

一、nginx服务简介 Nginx是一个高性能的HTTP和反向代理服务器,也是一个 IMAP/POP3/SMTP代理服务器。Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。

使用 Nginx 前必须了解的事项: 1)目前官方 Nginx 并不支持 Windows,您只能在包括 Linux、UNIX、BSD 系统下安装和使用; 2)Nginx 本身只是一个 HTTP 和反向代理服务器,它无法像 Apache 一样通过安装各种模块来支持不同的页面脚本,例如 PHP、CGI 等; 3)Nginx 支持简单的负载均衡和容错; 4)支持作为基本 HTTP 服务器的功能,例如日志、压缩、Byte ranges、Chunked responses、SSL、虚拟主机等等,应有尽有。

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方便开发和扩展,也正因此才使得Nginx功能如此强大。Nginx的模块默认编译进nginx中,如果需要增加或删除模块,需要重新编译Nginx,这一点不如Apache的动态加载模块方便。如果有需要动态加载模块,可以使用由淘宝网发起的web服务器Tengine,在nginx的基础上增加了很多高级特性,完全兼容Nginx,已被国内很多网站采用。

Nginx处理连接过程: nginx不会为每个连接派生进程或线程,而是由 worker 进程通过监听共享套接字接受新请求,并且使用高效的循环来处理数千个连接。Nginx 不使用仲裁器或分发器来分发连接,这个工作由操作系统内核机制完成。监听套接字在启动时就完成初始化,worker 进程通过这些套接字接受、读取请求和输出响应。

Nginx的工作模式很简单,就是采用一个master进程和多个worker工作进程: 其中master进程的作用也是很明确的就是负责管理worker进程,同时监听连接请求,当连接请求到来之后将连接放入worker进程中去处理具体的业务请求,比如说http请求。 Nginx能够处理高并发的原因在于对socket的管理方式是异步非阻塞的,使用select/poll/epoll/kqueue 来实现对大量socket描述符的管理,每个worker进程有一个主线程,而没有其他的线程这样的好处就在于不需要进行线程间的切换,这样就节省了资源。所以总的来说:Nginx能够实现支持高并发的同时运行效率还很低的关键在于整个系统内部只有有限的几个工作进程和一个监听进程,而每个进程内部只有一个主线程,这样就不会引起很多的线程切换,从而降低了系统开销,同时每个线程内部使用异步非阻塞的方式来管理描述符这样就可以管理大量的描述符,当描述符多的时候也只是会占用较多的内存而已,而不会造成占用大量cpu时间。以上说的就是Nginx的进程模型和事件模型,事件模型中处理的情况主要有三种,分别是网络事件,如HTTP请求等,网络事件使用异步非阻塞模式就可以很好的解决;还有信号,定时器,信号和定时器还不是很明白。Nginx处理进程间争夺系统资源的方式:也就是进程间存在的惊群现象。

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任何能完成的其它任务

举例说明一个完整请求如何通过互相协作来实现的: 既然worker进程之间是平等的,每个进程,处理请求的机会也是一样的。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接。那么问题来了,到底最后怎样处理,是由什么决定的呢?首先,每个 worker 进程都是从 master 进程 fork 过来,在 master 进程里面,先建立好需要 listen 的 socket(listenfd)之后,然后再 fork 出多个 worker 进程。所有 worker 进程的 listenfd 会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有 worker 进程会在注册 listenfd 读事件前抢 accept_mutex,抢到互斥锁的那个进程注册 listenfd 读事件,然后在读事件里调用 accept 接受该连接。当一个 worker 进程在 accept 这个连接之后,就开始读取请求、解析请求、处理请求。产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。我们可以看到:一个请求,完全由 worker 进程来处理,而且只在一个 worker 进程中处理。

也许有个疑问,那就是nginx采用多worker 的方式来处理请求,每个 worker 里面只有一个主线程,那能够处理的并发数很有限啊,多少个 worker 就能处理多少个并发,何来高并发呢? 然而,这就是 nginx 的高明之处,nginx 采用了异步非阻塞的方式来处理请求,也就是说,nginx 是可以同时处理成千上万个请求的。

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

二、nginx相对于传统的apache服务的优缺点 nginx相对比apache,实在有太多的优势。可以说,现在Nginx才是Web服务器的首选!! 1)nginx相对于apache的优点: 轻量级,同样起web 服务,比apache 占用更少的内存及资源; 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能; 高度模块化的设计,编写模块相对简单; 社区活跃,各种高性能模块出品迅速; 当然apache相对于nginx也有它自身的优点:rewrite比nginx 的rewrite强大;模块超多,基本想到的都可以找到;少bug,nginx的bug相对较多;超稳定;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)nginx处理动态请求是鸡肋,一般动态请求要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更好。

三、在 Linux 下安装 Nginx 为了确保能在Nginx中使用正则表达式进行更灵活的配置,安装之前需要确定系统是否安装有PCRE(Perl Compatible Regular Expressions)包。 您可以到ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/下载最新的PCR 源码包,使用下面命令下载编译和安装 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 参数和控制 程序运行参数 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: 第一是通过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 都会非常及时的处理状态的变化,以保证不会影响到用户的访问。

Nginx的location语法规则:location [=|~|~*|^~] /uri/ { … } =  开头表示精确匹配 ^~  开头表示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整个程序包只有500多K,但麻雀虽小、五脏俱全。 Nginx官方提供的各种功能模块应有尽有,结合这些模块可以完整各种各样的配置要求,例如:压缩、防盗链、集群、FastCGI、流媒体服务器、Memcached 支持、URL 重写等等,更关键的是Nginx拥有Apache和其他HTTP服务器无法比拟的高性能。甚至可以在不改变原有网站的架构上,通过在前端引入Nginx做负载均衡来提升网站的访问速度。

-------------------------------------------------------下面对Nginx的一些特殊设置做一说明-------------------------------------------------------

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

比如访问https://www.wangshibo.com/HouseGroup/index.html,跳转到https://www.wangshibo.com/index.php?r=houseGroup/index
rewrite ^/(.*)/index.html https://www.wangshibo.com/index.php?r=$1/index;

if ($request_uri  ~* "/(jkhwpc|jkhw|jkhwadmin).php") {
    rewrite ^/(.*)$ http://www.jikehaiwai.com/$1 last;
    }

if ($request_uri  ~* "/(qjspc|qjsmob|qjsadmin).php") {
    rewrite ^/(.*)$ http://www.qianjins.com/$1 last;
   }

-----------可以参考下面nginx的rewrite伪静态设置---------
rewrite ^(.*)/equip(d+).html$ $1/index.php?m=content&c=index&a=lists&catid=$2 last; 

# nginx rewrite  rule 
rewrite ^(.*)/archiver/((fid|tid)-[w-]+.html)$ $1/archiver/index.php?$2 last; 
rewrite ^(.*)/forum-([0-9]+)-([0-9]+).html$ $1/forumdisplay.php?fid=$2&page=$3 last; 
rewrite ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+).html$ $1/viewthread.php?tid=$2&extra=page%3D$4&page=$3 last; 
rewrite ^(.*)/profile-(username|uid)-(.+).html$ $1/viewpro.php?$2=$3 last; 
rewrite ^(.*)/space-(username|uid)-(.+).html$ $1/space.php?$2=$3 last; 
rewrite ^(.*)/tag-(.+).html$ $1/tag.php?name=$2 last; 

rewrite ^/(.*).(asp|aspx|asa|asax|dll|jsp|cgi|fcgi|pl)(.*)$ /404.php last;
rewrite ^/(.*)/(admin|cache|editor|file|include|lang|module|skin|template)/(.*).php(.*)$ /404.php last;
rewrite ^/(.*)-htm-(.*)$ /$1.php?$2 last;
rewrite ^/(.*)/show-([0-9]+)([-])?([0-9]+)?.html$ /$1/show.php?itemid=$2&page=$4 last;
rewrite ^/(.*)/list-([0-9]+)([-])?([0-9]+)?.html$ /$1/list.php?catid=$2&page=$4 last;
rewrite ^/(.*)/show/([0-9]+)/([0-9]+)?([/])?$ /$1/show.php?itemid=$2&page=$3 last;
rewrite ^/(.*)/list/([0-9]+)/([0-9]+)?([/])?$ /$1/list.php?catid=$2&page=$3 last;
rewrite ^/(.*)/([A-za-z0-9_-]+)-c([0-9]+)-([0-9]+).html$ /$1/list.php?catid=$3&page=$4 last;
rewrite ^/(.*)/([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+).html$ /$1/index.php?moduleid=$2&catid=$3&itemid=$4&page=$5 last;
rewrite ^(.*)/([a-z]+)/(.*).shtml$ $1/$2/index.php?rewrite=$3 last;
rewrite ^/(com)/([a-z0-9_-]+)/([a-z]+)/(.*).html$ /index.php?homepage=$2&file=$3&rewrite=$4 last;
rewrite ^/(com)/([a-z0-9_-]+)/([a-z]+)([/])?$ /index.php?homepage=$2&file=$3 last;
rewrite ^/(com)/([a-z0-9_-]+)([/])?$ /index.php?homepage=$2 last;

--------------------------------------------------------------------------------

1.rewrite跳转规则,有以下四种flag标记: last     基本上都用这个Flag,表示rewrite。 break     中止Rewirte,不在继续匹配。就是说本条规则匹配完成后,终止匹配,不再匹配后面的规则。 redirect     返回临时重定向的HTTP状态302;浏览器地址会显示跳转后的URL地址。 permanent     返回永久重定向的HTTP状态301;浏览器地址会显示跳转后的URL地址。 1)下面是可以用来判断的表达式: -f和!-f用来判断是否存在文件 -d和!-d用来判断是否存在目录 -e和!-e用来判断是否存在文件或目录 -x和!-x用来判断文件是否可执行

先来看几个小例子说明

例如下面这段设定nginx将某个目录下面的文件重定向到另一个目录,$2对应第二个括号(.*)中对应的字符串:
location /download/ {
        rewrite ^(/download/.*)/m/(.*)..*$ $1/nginx-rewrite/$2.gz break;
}
-----------------------------------------------------------------------------------
例如当用户输入 www.a.com.cn 自动跳转到www.a.com 这个域名:
rewrite ^/(.*)$ http://www.a.com/$1 permanent;
-----------------------------------------------------------------------------------
例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:
if ($http_user_agent ~ MSIE) {
        rewrite ^(.*)$ /nginx-ie/$1 break;
}
-----------------------------------------------------------------------------------
例如当用户访问testxqsjapi.xqshijie.com域名时跳转到本机的9501端口
upstream lb-9501 {
   server 127.0.0.1:9501;
}
server {
    listen  80;
    server_name testxqsjapi.xqshijie.com;
    root  /var/www/vhosts/testxqsjapi.xqshijie.com/;
 
    location / {
            proxy_pass http://lb-9501;
        }
}
----------------------------------------------------------------------------------
例如下面一例:nginx rewrite 实现二级域名跳转
当访问http://abc.wangshibo.com跳转到http://www.wangshibo.com/wangshibo/abc/
方法一:这种方法浏览器地址会变www.wangshibo.com/wangshibo/abc
server {
        listen 80;
        server_name www.wangshibo.com;
        location / {
                root /data/wangshibo;
                index index.html;
        }
}
 
server {
        listen 80;
        server_name *.wangshibo.com;
        if ( $http_host ~* "^(.*).wangshibo.com$") {
                set $domain $1;
                rewrite ^(.*) http://www.wangshibo.com/wangshibo/$domain/ break;
        }
}

方法二:当访问http://abc.wangshibo.com跳转到http://www.wangshibo.com/wangshibo/abc/
server {
        listen 80;
        server_name *.wangshibo.com;
        root /usr/local/www;
        #这是里可以加多个目录,如果不加目录,会无法访问到abc.wangshibo.com/目录下的文件,如图片目录/images
        location ~ ^/(wangshibo|images|styles)/
        {
                proxy_redirect        off;
                proxy_set_header    Host   www.wangshibo.com;
                proxy_pass      http://192.168.1.2:8080;
        }
        location / {
                set $domain default;
                if ( $http_host ~* "^(.*).wangshibo.com$") {
                        set $domain $1;
                }
                rewrite ^/(.*)    /wangshibo/$domain/$1 last;
        }
        access_log off;
}

再接着看下面的实例说明

#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。  
#这里是直接转发给后端应用服务器了,也可以是一个静态首页  
# 第一个必选规则  
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/  
}  

2)实例说明 1)访问A站跳转(重定向)到B站 server {     listen 80;     server_name www.wangshibo.com ; rewrite ^(.*) http://www.huanqiu.com$1 permanent;

    root /var/www/html;     index index.html index.php index.htm;     access_log /usr/local/nginx/logs/image.log; }

访问wangshibo.com跳转到www.wangshibo.com
server {
        listen       80;

        server_name  www.wangshibo.com wangshibo.com;
        index index.jsp index.html index.php index.htm;
        root /var/www/html;
        access_log /usr/local/nginx/logs/image.log;

        if ($host = "wangshibo.com") {
             rewrite ^/(.*)$ http://www.wangshibo.com permanent;
    }

}

2)多域名绑定一个目录,并且全部301跳转到其中一个域名(注意:多域名都要解析到本机ip上) server {      listen 80;    server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com;      if ($host != 'www.wangshibo.com') {      rewrite ^/(.*)$ http://www.wangshibo.com/$1 permanent;      }      root /var/www/html;      index index.html index.php index.htm;      access_log /usr/local/nginx/logs/image.log; }

上面说明访问http://web01.wangshibo.com、http://hehe.wangshibo.com、http://wangshibo.com的时候都会自动跳转到 http://www.wangshibo.com,并且浏览器地址会显示跳转后的URL地址。

如果是上面多域名访问后都重定向跳转到http://hehe.wangshibo.com,则配置修改如下: server {     listen 80; server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com;     if ($host != 'hehe.wangshibo.com') {     rewrite ^/(.*)$ http://hehe.wangshibo.com/$1 permanent;     }     root /var/www/html;     index index.html index.php index.htm;     access_log /usr/local/nginx/logs/image.log; }

如下配置:多域名中的某个域名访问时发生跳转,其他域名访问时不跳转 server {    listen 80;    server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com;    if ($host = 'hehe.wangshibo.com') {        rewrite ^/(.*)$ http://www.huanqiu.com/$1 permanent;    }    root /var/www/html;    index index.html index.php index.htm;    access_log /usr/local/nginx/logs/image.log; }

3)将多级目录下的文件转成一个文件,增强seo效果 比如将/wang-123-456-789.html指向wang/123/456/wangshow_789.html [root@test-huanqiu ~]# cat /usr/local/nginx/conf/vhosts/test.conf server {      listen 80;      server_name www.wangshibo.com; rewrite ^/wang-([0-9]+)-([0-9]+)-([0-9]+).html$ http://www.wangshibo.com/wang/$1/$2/wangshow_$3.html last;      root /var/www/html;      index index.html index.php index.htm;      access_log /usr/local/nginx/logs/image.log;

}

这样访问http://www.wangshibo.com/wang-123-456-789.html就会跳转到http://www.wangshibo.com/wang/123/456/wangshow_789.html

4)访问的目标文件和目录资源不存在的时候重定向跳转 如下配置,当访问http://www.wangshibo.com/后面的访问资源(文件或目录)不存在时,统统跳转到http://www.wangshibo.com/sorry.html页面 server {     listen 80;     server_name www.wangshibo.com;     if (!-e $request_filename) { rewrite ^/ http://www.wangshibo.com/sorry.html ;     }     root /var/www/html;     index index.html index.php index.htm;     access_log /usr/local/nginx/logs/image.log; }

5)将站点根目录下某个目录指向二级目录 例如将/huanqiupc/指向/ops/huanqiu/,配置如下: server {     listen 80;     server_name www.wangshibo.com;     rewrite ^/([0-9a-z]+)pc/(.*)$ http://www.wangshibo.com/ops/$1/$2 last;     root /var/www/html;     index index.html index.php index.htm;     access_log /usr/local/nginx/logs/image.log; }

这样,访问http://www.wangshibo.com/huanqiupc的时候就会跳转到http://www.wangshibo.com/ops/huanqiu/ 注意:上面的配置中的last修改为permanent或redirect都可以

以上的配置也适用于:(前提是这些目录要真是存在于站点目录/var/www/html/中,并且权限要正确) 将/wangshibopc/指向/ops/wangshibo/ 将/guohuihuipc/指向/ops/guohuihui/ 将/hahapc/指向/ops/haha/ ......

6)其他的rewrite跳转规则的例子:

server {
    listen 80;
    server_name www.wangshibo.com;
    root /var/www/html; 
    index index.html index.htm;

    rewrite ^/site/resource/(.*)$ https://www.wangshibo.com/resource/$1 last;
    rewrite ^/active/Ymf.html$ https://www.wangshibo.com/project/detail.html?project_id=1 last;
    rewrite ^/active/Ysyg.html$ https://www.wangshibo.com/project/detail.html?project_id=7 last;

    if ($host ~* "^wangshibo.com$") {
       rewrite ^/(.*)$ https://www.wangshibo.com/ permanent;
    }

    location / { 
      rewrite /abc http://www.huanqiu.com break;    #本机站点目录下并不需要真实存在abc这个目录,对虚拟目录的访问都重写到http://www.huanqiu.com
    }                                               #即访问http://www.wangshibo.com/abc,跳转到http://www.huanqiu.com

    location /text { 
      rewrite / http://china.huanqiu.com break;     #本机站点目录下需要真实存在text目录,对其的访问都重写到http://china.huanqiu.com
    }                                               #即访问http://www.wangshibo.com/text,跳转到http://china.huanqiu.com

    }

下面一例:访问http://www.wangshibo.com/g/4HG45SkZ 实际访问地址跳转为 http://110.10.88.99:8081/qun/share/view?code=4HG45SkZ

upstream  g_server {
        keepalive 64;
        server 110.10.88.99:8081 max_fails=2 fail_timeout=5 weight=100;
        }

    server {
        listen       80;
        server_name  www.wangshibo.com;

        rewrite ^/bcloud.(swf|html|js)(.*)$ http://hehe.wangshibo.com/bcloud.$1$2 last;

        root  /home/web/www;
        location ~ .apk$ {
        max_ranges 0;
          }

        location ^~ /g {
            proxy_redirect off;
            proxy_set_header Host $host;
#           proxy_set_header Host $host:$remote_port;
#           proxy_set_header REMOTE_PORT $remote_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            client_max_body_size 1G;
            client_body_buffer_size 256k;
            proxy_connect_timeout 30;
            proxy_send_timeout 30;
            proxy_read_timeout 600;
            proxy_buffer_size 16k;
            proxy_buffers 4 32k;
            proxy_temp_file_write_size 64k;
            proxy_pass  http://g_server;
            #rewrite "/g/(.*$)"   www.wangshibo.com/qun/share/view?code=$1  break;
            rewrite "/g/(.*$)"   /qun/share/view?code=$1  break;
        }
    }

另外注意: $1表示第一个变量,即前面rewrite后第一个()内设置的变量 $2表示第二个变量,即前面rewrite后第二个()内设置的变量

再看一例: 访问http://www.wangshibo.com/thumb/transcode 实际访问地址为 http://120.170.190.99:28080/transcode/thumb/transcode

upstream  thumb {
        keepalive 64;
        server 120.170.190.99:28080 max_fails=2 fail_timeout=5 weight=100;
    }

server {
        listen       80;
        server_name  www.wangshibo.com ;

        root   /home/web/www;

  location ^~ /thumb {
            proxy_pass  http://thumb;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;
            client_max_body_size 1G;
            client_body_buffer_size 256k;
            proxy_connect_timeout 30;
            proxy_send_timeout 30;
            proxy_read_timeout 60;
            proxy_buffer_size 16k;
            proxy_buffers 4 32k;
            proxy_temp_file_write_size 64k;
            rewrite  "^/(.*)$"  /transcode/$1 break;
        }
}

----------------------------再看一个访问nginx跳转后的url不变的例子--------------------------------------

需要特别注意的是:
proxy_pass 反向代理,可以实现只改变跳转后的内容,而跳转后的原url保持不变!
rewrite 重写跳转后会进行重定向,很难实现跳转后的原url不变的需求。

看看之前踩过的坑;
要求访问http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,内容跳转到http://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken,但是跳转后的url保持不变!
这是根据path路径进行反向代理的配置,即要求访问http://wx2.xqshijie.com/apiwx2/$1 跳转到http://m.xqshijie.com/$1,跳转后的url不变!

配置如下:
[root@fangfull_web1 vhosts]# cat wx2.xqshijie.com.conf
server {
        listen       80;

        server_name  wx2.xqshijie.com;
        root  /Data/app/xqsj_wx2/dist;
        index index.html;
  
        #if ($http_x_forwarded_for !~ ^(124.65.197.154|103.10.86.28|103.10.86.8)) {
        #   rewrite ^.*$  /maintence.php last;
        #}

        location /apiwx2/ {
        proxy_pass https://m.xqshijie.com/;
        }

        access_log  /var/log/betawx2.log  main;

        location / {
            try_files $uri $uri/ @router;
            index  index.html;
        }
        #rewrite ^(.+)$ /index.html last;
        location @router {
            rewrite ^.*$ /index.html last;
        }
    } 

根据上面配置后,就可以实现访问http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,实际显示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的内容,但是跳转后的原来的url不变!


如果采用rewrite重写规则,即将:
        location /apiwx2/ {
        proxy_pass https://m.xqshijie.com/;
        }
改为
        location /apiwx2/ {
        rewrite ^/apiwx2(.*)$ https://m.xqshijie.com.$1 last;
        }
那么,访问http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,实际显示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的内容,但是跳转后的url已经变了!


上面碰到过的坑:
由于访问http://m.xqshijie.com就会自动跳转到https://m.xqshijie.com,所以如果将上面的配置改为(即将https://m.xqshijie.com改为http://m.xqshijie.com):
        location /apiwx2/ {
        proxy_pass http://m.xqshijie.com/;
        }
这样,访问http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,实际显示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的内容,但是跳转后的原来的url已经变了!
原因是因为这里经过了两次跳转,即rewrite->http->https,所以跳转后的url变了。
解决办法:就是直接rewrite跳转到https,即proxy_pass https://m.xqshijie.com/;

----------------------------下面的跳转规则表示--------------------------------------- 访问http://www.wangshibo.com/wangshibo/ops就会跳转到http://www.wangshibo.com/ops/wangshibo 访问http://www.wangshibo.com/wangshibo/beijing就会跳转到http://www.wangshibo.com/beijing/wangshibo ...... 即由"wangshibo/变量"-->"变量/wangshibo"

server {
   listen 80;
   server_name www.wangshibo.com;
   rewrite ^/wangshibo/(.*)$  http://www.wangshibo.com/$1/wangshibo last;
   root /var/www/html;
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}

访问http://www.wangshibo.com/ops/web 跳转到 http://www.wangshibo.com/web/ops/web/

server {
   listen 80;
   server_name www.wangshibo.com;
   rewrite ^/ops/(.*)$  http://www.wangshibo.com/$1/ops/$1 break;
   root /var/www/html;
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}

访问http://www.wangshibo.com/wang/123 实际访问地址跳转为 http://www.hehe.com/qun/share/view?code=123

server {
   listen 80;
   server_name www.wangshibo.com;
   rewrite ^/wang/(.*)$  http://www.hehe.com/qun/share/view?code=$1 last;
   root /var/www/html;
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}

其他配置实例

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

多目录转成参数
abc.domian.com/sort/2 => abc.domian.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;
}


目录自动加"/",前提是访问目录存在
配置如下:
if (-d $request_filename){
   rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}


三级域名跳转
配置如下:
if ($http_host ~* “^(.*).i.beijing.com$”) {
rewrite ^(.*) http://www.wangshibo.com$1/;
break;
}


针对站点根目录下的某个子目录作镜向
配置如下:就会把http://www.huanqiu.com的内容(即首页)镜像到/var/www/html下的ops目录下了
server {
   listen 80;
   server_name www.wangshibo.com;
   root /var/www/html;
   location ^~ /ops {
   rewrite ^.+ http://www.huanqiu.com/ last;
   break;
   }
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}


域名镜像(其实就是域名跳转)
server {
   listen 80;
   server_name www.wangshibo.com;
   root /var/www/html;
   rewrite ^/(.*) http://www.huanqiu.com/$1 last;
   index index.html index.php index.htm;
   access_log /usr/local/nginx/logs/image.log;
}

其他:
rewrite ^/(space|network)-(.+).html$ /$1.php?rewrite=$2 last;
rewrite ^/(space|network).html$ /$1.php last;
rewrite ^/([0-9]+)$ /space.php?uid=$1 last;

rewrite ^(.*)/archiver/((fid|tid)-[w-]+.html)$ $1/archiver/index.php?$2 last;
rewrite ^(.*)/forum-([0-9]+)-([0-9]+).html$ $1/forumdisplay.php?fid=$2&page=$3 last;
rewrite ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+).html$ $1/viewthread.php?tid=$2&extra=page%3D$4&page=$3 last;
rewrite ^(.*)/profile-(username|uid)-(.+).html$ $1/viewpro.php?$2=$3 last;
rewrite ^(.*)/space-(username|uid)-(.+).html$ $1/space.php?$2=$3 last;
rewrite ^(.*)/tag-(.+).html$ $1/tag.php?name=$2 last;

目录对换:/1234/xxx ----->xxx?id=1234 配置如下: [root@test-huanqiu ~]# vim /usr/local/nginx/conf/vhosts/test.conf server {     listen 80;     server_name www.wangshibo.com;     root /var/www/html; rewrite ^/(d+)/(.+)/ /$2?id=$1 last;     index index.html index.php index.htm;     access_log /usr/local/nginx/logs/image.log; }

[root@test-huanqiu ~]# cat /var/www/html/ops/index.html nginx的目录对换的跳转测试

如上配置后,那么: 访问http://www.wangshibo.com/?id=567567567567567 的结果就是http://www.wangshibo.com/的结果 访问http://www.wangshibo.com/ops/?id=wangshibo 的结果就是http://www.wangshibo.com/ops的结果 访问http://www.wangshibo.com/wang/?id=123111 的结果就是http://www.wangshibo.com/wang的结果 .......

2.反向代理(proxy_pass) 简单测试nginx反向代理和负载均衡功能的操作记录(1)-----http代理 简单测试nginx反向代理和负载均衡功能的操作记录(2)-----https代理

3.缓存设置 nginx反向代理+缓存开启+url重写+负载均衡(带健康探测)的部署记录 nginx缓存配置的操作记录梳理

4.防盗链。关于Nginx防盗链具体设置,可参考:Nginx中防盗链(下载防盗链和图片防盗链)的操作记录 location ~* .(gif|jpg|swf)$ { valid_referers none blocked start.igrow.cn sta.igrow.cn; if ($invalid_referer) { rewrite ^/ http://$host/logo.png; } }

下面设置文件反盗链并设置过期时间: location ~*^.+.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {     valid_referers none blocked *.wangshibo.com*.wangshibo.net localhost 218.197.67.14;     if ($invalid_referer) {        rewrite ^/ http://img.wangshibo.net/leech.gif;        return 412;        break;       }    access_log off;    root /opt/lampp/htdocs/web;    expires 3d;    break; }

这里的return 412 是自定义的http状态码,默认为403,方便找出正确的盗链的请求 “rewrite ^/ http://img.wangshibo.net/leech.gif;”显示一张防盗链图片 “access_log off;”不记录访问日志,减轻压力 “expires 3d”所有文件3天的浏览器缓存

5.根据文件类型设置过期时间 1)expires起到控制页面缓存的作用,合理的配置expires可以减少很多服务器的请求; 2)对于站点中不经常修改的静态内容(如图片,JS,CSS),可以在服务器中设置expires过期时间,控制浏览器缓存,达到有效减小带宽流量,降低服务器压力的目的。 3)Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。 要配置expires,可以在http段中或者server段中或者location段中加入; 如下:控制图片等过期时间为30天,如果图片文件不怎么更新,过期可以设大一点;如果频繁更新,则可以设置得小一点,具体视情况而定 location ~ .(gif|jpg|jpeg|png|bmp|swf|ico)$ {     root /var/www/img/;     expires 30d; }

location ~ .*.(js|css)$ {    expires 10d; }

location ~* .(js|css|jpg|jpeg|gif|png|swf)$ {    if (-f $request_filename) {    expires 1h;    break;    } }

location ~ .(wma|wmv|asf|mp3|mmf|zip|rar|swf|flv)$ {    root /var/www/upload/;    expires max; }

expires 指令可以控制 HTTP 应答中的“ Expires ”和“ Cache-Control ”的头标(起到控制页面缓存的作用) 语法:expires [time|epoch|max|off] 默认值:off expires指令控制HTTP应答中的“Expires”和“Cache-Control”Header头部信息,启动控制页面缓存的作用 time:可以使用正数或负数。“Expires”头标的值将通过当前系统时间加上设定time值来设定。 time值还控制"Cache-Control"的值: 负数表示no-cache 正数或零表示max-age=time epoch:指定“Expires”的值为 1 January,1970,00:00:01 GMT max:指定“Expires”的值为31 December2037 23:59:59GMT,"Cache-Control"的值为10年。(即设置过期时间最最长) -1:指定“Expires”的值为当前服务器时间-1s,即永远过期。 off:不修改“Expires”和"Cache-Control"的值

expires使用了特定的时间,并且要求服务器和客户端的是中严格同步。 而Cache-Control是用max-age指令指定组件被缓存多久。 对于不支持http1.1的浏览器,还是需要expires来控制。所以最好能指定两个响应头。但HTTP规范规定max-age指令将重写expires头。

如何检测nginx中设置的expires网页过期时间是否生效? 方法: 打开webkaka的网站速度诊断工具(http://pagespeed.webkaka.com/),输入你的网页地址,检测后,立即可以看到设置是否生效了。如下图所示:

上图可以看到,被检测网页的js文件过期时间为1天(12h)。

6.禁止访问某个文件或目录 1)禁止访问以txt或doc结尾的文件 location ~* .(txt|doc)${ root /data/www/wwwroot/linuxtone/test; deny all; }

2)nginx禁止访问所有.开头的隐藏文件设置 location ~* /.* { deny all; }

3)nginx禁止访问目录 location ^~ /path { deny all; }

4)禁止访问扩展名为bat的文件 location ~* /.bat { deny all; }

5)禁止访问configs目录,以及其下所有子目录或文件 location ^~ /configs/ { deny all; } 注意上述configs后面的斜杠不能少,否则所有以configs开头的目录或文件都将禁止访问。

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

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

8)禁止访问以.sh,.flv,.mp3为文件后缀名的文件 location ~ .*.(sh|flv|mp3)$ { return 403; }

9)或者以=符号形式 location = /config/ { return 404; } location =/config.ini{ return 404; }

10)禁止htaccess location ~/.ht { deny all; }

return指令 语法:returncode ; 使用环境:server,location,if; 该指令用于结束规则的执行并返回状态码给客户端。

例如:访问的URL以".sh"或".bash"结尾,则返回403状态码 location ~ .*.(sh|bash)?$ { return 403; }

7.禁止IP访问 只允许域名访问 当别人通过ip或者未知域名访问你的网站的时候,你希望禁止显示任何有效内容,可以给他返回500. 目前国内很多机房都要求网站主关闭空主机头,防止未备案的域名指向过来造成麻烦。 为了避免网站遭受恶意IP攻击,需要禁止IP访问,只能使用域名访问站点!

listen行加上default(或default_server)参数,表示这个是默认虚拟主机。 所以,禁止ip访问,只能使用域名访问的正确配置是: server {      listen 80 default_server;      server_name _;      return 500; }

server {     listen 80;     server_name web01.wangshibo.cn;     root /var/www/html;     index index.html index.php index.htm;     access_log /usr/local/nginx/logs/image.log; }

注意: 如果在上面的server_name配置中指定域名的同时,也指明了ip访问,比如server_name 103.110.186.17 web01.wangshibo.cn 那么尽管上面已经做了返回500设置,也禁止不了ip访问!也就是说,只要server_name一行指明了ip访问,那么就禁止不了了

以上设置,可以将ip访问禁用,这样的话,使用ip访问的流量就会丢失。 如果想把这部分流量收集起来,导入到自己的网站,只要做以下跳转设置就可以: server {     listen 80 default;     rewrite ^(.*) http://www.wangshibo.com permanent; }

server {     listen 80;     server_name web01.wangshibo.cn;     root /var/www/html;     index index.html index.php index.htm;     access_log /usr/local/nginx/logs/image.log; }

下面列出其他的一些细节导致的不同效果: 1)将ip和域名访问统统禁止,返回403(或者配置return 500)错误页 server { listen 80 default_server; server_name _; return 403;

root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; }

2)下面的配置: 指明了只能使用域名,即http://web01.wangshibo.cn访问配置中的站点(/var/www/html) 不能使用ip,即http://103.110.186.17访问配置中的站点。但是可以使用ip方式访问nginx默认的根目录下的内容(比如/usr/local/nginx/html) server { listen 80 ; server_name web01.wangshibo.cn;

root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; }

下面的配置,指明了使用域名或ip都可以访问配置中的站点。(使用ip访问只限于只有一个vhost虚拟主机配置的情况,如果是多个,那么指明ip访问就会混淆) server { listen 80 ; server_name 103.110.186.17 web01.wangshibo.cn;

root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; }

3)下面两个的配置后,都能使用域名或ip访问配置中的站点。 server { listen 80 default; server_name web01.wangshibo.cn;

root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; }

server { listen 80 default; server_name 103.110.186.17 web01.wangshibo.cn;                        

root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; }

8.流量限制 对于提供下载的网站,肯定是要进行流量控制的,例如BBS、视频服务,还是其它专门提供下载的网站。在nginx中我们完全可以做到限流,由Nginx模块中的Core模块提供了limit_rate、limit_rate_after命令,我们只需要调用命令实现流量限制就行。 实现流量限制由两个指令limit_rate和limit_rate_after共同完成: limit_rate 语法: limit_rate rate; 默认值: limit_rate 0; 作用域: http, server, location, location中的if字段 命令概述:限制向客户端传送响应的速率限制。参数 rate 的单位是字节/秒,设置为 0 将关闭限速。 nginx 按连接限速,需要明白的一点是该限制只是针对一个连接的设定,所以如果某个客户端同时开启了两个连接,那么客户端的整体速率是这条指令设置值的2倍。

limit_rate_after 语法: limit_rate_after size; 默认值: limit_rate_after 0; 作用域:http, server, location,location中的if字段 设置不限速传输的响应大小。当传输量大于此值时,超出部分将限速传送。

示例说明: server {        listen 80;        server_name ops.wangshibo.com;        location /ops/{             root /home/www/html;             limit_rate_after 5m;             limit_rate 20k;       } }

测试: [root@test-huanqiu ~]# wget http://ops.wangshibo.com/ops/seven.mp4

修改配置之前,速率没有限制:

修改配置之后,可见由于传输量大于5m,超出部分的传输速率已经被限制在20k/s:

可以发现配置之后,刚开始的时候传输速度很高,因为,传输量大于设定值的部分才会受到限制。这就说明,我们两个命令都发挥了作用!

9.并发连接数限制 这个配置是基于ngx_http_limit_zone_module模块的,要简单完成并发限制,我们要涉及到limit_conn_zone和limit_conn 这两个指令: limit_conn_zone 语法:limit_conn_zone zone_name $variable the_size 默认值:no 作用域:http 本指令定义了一个数据区,里面记录会话状态信息。 variable 定义判断会话的变量;the_size 定义记录区的总容量。

limit_conn 语法:limit_conn zone_name the_size 默认值:no 作用域:http, server, location 指定一个会话最大的并发连接数。 当超过指定的最发并发连接数时,服务器将返回 "Service unavailable" (503)。

示例说明: http {        limit_conn_zone $binary_remote_addr zone=one:10m;        .......        .......        server {              listen 80;              server_name ops.wangshibo.com;              location /ops/ {              limit_conn one 1;              } 示例解释: 1)定义一个叫“one”的记录区,总容量为 10M,以变量$binary_remote_addr作为会话的判断基准(即一个地址一个会话)。 限制/ops/目录下,一个会话只能进行一个连接;简单来说,就是限制/ops/目录下,一个IP只能发起一个连接,多过一个,一律报错503。 2)这里使用的是$binary_remote_addr而不是 $remote_addr。$remote_addr的长度为7至15 bytes,会话信息的长度为32或64bytes;而 $binary_remote_addr的长度为4bytes,会话信息的长度为32bytes;$binary_remote_addr是限制同一客户端ip地址;当 zone 的大小为 1M 的时候,大约可以记录 32000 个会话信息(一个会话占用 32 bytes)。

下面分享一个限制流量和并发送的配置: 现象描述: 中间一段时间,网站访问有点慢,初步怀疑是机房交换机问题(之前出现过网站访问很慢,热插拔网卡/重启网卡就好了) 最后查看,发现机房流量很大!主要是论坛流量大,主站流量很小,应该是论坛人数访问一多,就把带宽占满了。

解决办法: 在论坛服务器上修改: 1)首先限制并发数 [root@server_web ~]# vim /etc/sysconfig/iptables ..... -A INPUT -p tcp --dport 80 -m limit --limit 6/s -j ACCEPT [root@server_web ~]# /etc/init.d/iptables restart

上面将每个用户限制在每秒6个请求,但效果不明显。

2)设置nginx的流量请求 [root@server_web ~]# vim /usr/local/nginx/conf/nginx.conf http{      limit_conn_zone $binary_remote_addr zone=perip:10m;     # limit_req_zone $binary_remote_addr zone=one2:10m rate=5r/s;     # limit_req zone=one2 burst=5;     ..........     .......... }

[root@server_web ~]# vim /usr/local/nginx/conf/vhost/forum.conf       server {             listen 80;             server_name forum.wangshibo.com;             root /var/www/html;                 limit_conn perip 10;   //这里调用上面的perip,需要写在server里面;即每个ip最多有10个并发连接                 limit_rate 10k;    //限制每个连接的带宽,可以单独写这条,与连接数无关;            } }

[root@server_web ~]# /usr/local/nginx/sbin/nginx -s reload

10.nginx的访问控制及DDOS预防 1)访问控制配置 基于各种原因,Ningx有时要进行访问控制。 比如说,一般网站的后台都不能让外部访问,所以要添加 IP 限制,通常只允许公司的IP访问。 访问控制就是指只有符合条件的IP才能访问到这个网站的某个区域。 涉及模块:ngx_http_access_module 模块概述:允许限制某些 IP 地址的客户端访问。 对应指令: allow 语法: allow address | CIDR | unix: | all; 默认值: — 作用域: http, server, location, limit_except 允许某个 IP 或者某个 IP 段访问。如果指定 unix,那将允许 socket 的访问。注意:unix 在 1.5.1 中新加入的功能,如果你的版本比这个低,请不要使用这个方法。

deny 语法: deny address | CIDR | unix: | all; 默认值: — 作用域: http, server, location, limit_except 禁止某个 IP 或者一个 IP 段访问。如果指定 unix,那将禁止 socket 的访问。注意:unix 在 1.5.1 中新加入的功能,如果你的版本比这个低,请不要使用这个方法。

示例说明: server {       listen 80;      server_name forum.wangshibo.com;      root /var/www/html;      location / {        deny 192.168.1.1;        allow 192.168.1.0/24;        allow 10.1.1.0/16;        allow 103.10.67.56;        deny all;        } } 规则按照顺序依次检测,直到匹配到第一条规则。 在这个例子里,只有 10.1.1.0/16 、192.168.1.0/24和103.10.67.56允许访问,但 192.168.1.1 除外。

如下实例: 1)先是多域名绑定一个目录后的301跳转至同一个域名 2)针对网站访问做来源ip白名单设置,并加上密码。(即用户认证配置) [root@test-huanqiu vhosts]# cat test.conf

server {
     listen 80;
     server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com;
     if ($host != 'www.wangshibo.com') {
     rewrite ^/(.*)$ http://www.wangshibo.com/$1 permanent;
     }
     root /var/www/html;
     index index.html index.php index.htm;
     access_log /usr/local/nginx/logs/image.log;

     allow  192.168.1.0/24; 
     allow  124.65.197.154; 
     deny  all;
     auth_basic "C1G_ADMID";
     auth_basic_user_file /usr/local/nginx/htpasswd;
}

[root@test-huanqiu vhosts]# htpasswd -c /usr/local/nginx/htpasswd wangshibo New password: Re-type new password: Adding password for user wangshibo 访问站点http://www.wangshibo.com,效果如下:

ngx_http_access_module 配置允许的地址能访问,禁止的地址被拒绝。这只是很简单的访问控制,而在规则很多的情况下,使用 ngx_http_geo_module 模块变量更合适。 这个模块大家下来可以了解 : ngx_http_geo_module

------------------------------------------------------------------------------------------------------- 上面也用到了nginx的用户认证的配置,其中: auth_basic 认证时的提示信息 auth_basic_user_file 认证时存放用户名和密码的文件

# htpasswd -c /usr/local/nginx/htpasswd wangshibo       //第一次设置认证的用户 # htpasswd /usr/local/nginx/htpasswd guohuihui           //追加认证的用户,后面再次追加认证用户时,不要加-c参数,否则就会覆盖之前添加的用户!

下面顺便看几个认证部分的配置:

location /admin/ { 
auth_basic "Admin Auth."; 
auth_basic_user_file /usr/local/nginx/htpasswd; 
} 


location /wangshibo/ { 
proxy_pass http://www.guohuihui.com/heng/; 
auth_basic "Test Auth."; 
auth_basic_user_file /usr/local/nginx/htpasswd; 
} 

location ^~ /auth/ { 
location ~ .*.(php|php5)?$ { 
fastcgi_pass 127.0.0.1:9000; 
fastcgi_index index.php; 
include fcgi.conf; 
} 
auth_basic "Authorized users only"; 
auth_basic_user_file /usr/local/nginx/htpasswd;
} 

2)DDOS预防配置 DDOS的特点是分布式,针对带宽和服务攻击,也就是四层流量攻击和七层应用攻击,相应的防御瓶颈四层在带宽,七层的多在架构的吞吐量。 对于七层的应用攻击,还是可以做一些配置来防御的,使用nginx的http_limit_conn和http_limit_req模块通过限制连接数和请求数能相对有效的防御。 其中: ngx_http_limit_conn_module    可以限制单个 IP 的连接数 ngx_http_limit_req_module      可以限制单个 IP 每秒请求数 配置方法: (1)限制每秒请求数,即ip访问频率限制  涉及模块:ngx_http_limit_req_module 通过漏桶原理来限制单位时间内的请求数,一旦单位时间内请求数超过限制,就会返回 503 错误。 配置范例: http {        limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s; ...        server { ...       location ~ .php$ {           limit_req zone=one burst=5 nodelay;           }       } }

配置说明(上一部分解释过的就不再解释): 定义一个名为one的limit_req_zone用来存储session,大小是10M内存, 以$binary_remote_addr 为key,限制平均每秒的请求为20个, 1M能存储16000个状态,rete的值必须为整数, rate=20r/s表示限制频率为每秒20个请求;如果限制两秒钟一个请求,可以设置成30r/m。 限制每ip每秒不超过20个请求,漏桶数burst为5 brust的意思就是,如果第1秒、2,3,4秒请求为19个, 第5秒的请求为25个是被允许的。 但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。 nodelay,如果不设置该选项,严格使用平均速率限制请求数, 第1秒25个请求时,5个请求放到第2秒执行, 设置nodelay,25个请求将在第1秒执行。

(2)限制IP连接数(上面已经说明,这里直接写配置) http {        limit_conn_zone $binary_remote_addr zone=addr:10m;               //上面讲过 ...       server { ...       location /ops/ {       limit_conn addr 1;          }      } }

总的来说:如何设置能限制某个IP某一时间段的访问次数是一个让人头疼的问题,特别面对恶意的ddos攻击的时候。其中CC攻击(Challenge Collapsar)是DDOS(分布式拒绝服务)的一种,也是一种常见的网站攻击方法,攻击者通过代理服务器或者肉鸡向向受害主机不停地发大量数据包, 造成对方服务器资源耗尽,一直到宕机崩溃。 cc攻击一般就是使用有限的ip数对服务器频繁发送数据来达到攻击的目的。

nginx可以通过Http LimitReq Modul和Http LimitZone Module配置来限制ip在同一时间段的访问次数来防cc攻击。 1)Http LimitReq Modul用来限制连单位时间内连接数的模块,使用limit_req_zone和limit_req指令配合使用来达到限制。一旦并发连接超过指定数量,就会返回503错误。 2)Http LimitConn Modul用来限制单个ip的并发连接数,使用limit_zone和limit_conn指令

配置示例: Http LimitReq Modul限制某一段时间内同一ip访问数 http{ ......       limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s; ......      server{ ...      location { ......        limit_req zone=allips burst=5 nodelay; ......     } ......    } ...... }

Http LimitZone Module 限制并发连接数实例 limit_zone只能定义在http作用域,limit_conn可以定义在http server location作用域 http{ ...     limit_conn_zone one $binary_remote_addr 10m; ......     server{ ......     location { ......       limit_conn one 20;       limit_rate 500k; ......      } ......      } ...... }

(3)限速白名单设置(可参考:nginx利用geo模块做限速白名单以及geo实现全局负载均衡的操作记录) http_limit_conn和 http_limit_req模块限制了单IP单位时间内的连接和请求数,但是如果Nginx前面有lvs或者haproxy之类的负载均衡或者反向代理,nginx 获取的都是来自负载均衡的连接或请求,这时不应该限制负载均衡的连接和请求,就需要 geo 和 map 模块设置白名单: geo $whiteiplist {      default 1;      10.11.15.1610; } map $whiteiplist$limit {      1 $binary_remote_addr;      0 ""; } limit_req_zone $limit zone=one:10m rate=10r/s; limit_conn_zone $limit zone=addr:10m;

geo 模块定义了一个默认值是 1 的变量 whiteiplist,当在 ip 在白名单中,变量 whiteiplist 的值为 0,反之为1. 对上面设置的逻辑关系解释: 如果在白名单中--> whiteiplist=0 --> $limit="" --> 不会存储到 10m 的会话状态(one 或者 addr)中 --> 不受限制; 反之,不在白名单中 --> whiteiplist=1 --> $limit=二进制远程地址 -->存储进 10m 的会话状态中 --> 受到限制。

(4)动手测试DDOS预防配置 下面来测一下上面说到的配置是否起到了作用。 安装nginx+php环境 写一个测试的PHP文件,修改nginx配置文件,使其能正常访问。 在/home/shiyanlou目录下写一个test.php,内容如下: [root@server_web1 ~]# vim /home/shiyanlou/test.php <?php phpinfo (); ?>

nginx 配置文件修改:

最后展示:

image.png

使ab命令进行测试,比较修改nginx配置文件前后(连接数和请求数分开测试)的测试结果。

修改之前:

测试结果为:

对nginx配置做修改(添加http和php配置如下的红线内容),重启,然后再进行测试

image.png

测试结果为:

11.访问白名单 参考:nginx访问白名单设置以及根据$remote_addr分发

12.nginx的上传下载设置 参考:nginx限制上传大小和超时时间设置说明/php限制上传大小

13.nginx目录浏览及其验证功能 参考:nginx下目录浏览及其验证功能配置记录

14.Nginx下禁止指定目录运行php脚本文件

非常简单,直接通过location条件匹配定位后进行权限禁止。

在server配置段中增加下面的的配置:

1)如果是单个目录
location ~* ^/uploads/.*.(php|php5)$ {  
    deny all; 
}  

2)如果是多个目录
location ~* ^/(attachments|uploads)/.*.(php|php5)$ { 
   deny all; 
}  

注意:这段配置文件一定要放在下面配置的前面才可以生效。
location ~ .php$ { 
fastcgi_pass 127.0.0.1:9000; 
fastcgi_index index.php; 
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
include fastcgi_params; 
} 

配置完后记得重启Nginx生效。

------------------------------------------------------------------------------
如果是Apache下禁止指定目录运行PHP脚本,在虚拟主机配置文件中增加php_flag engine off指令即可,配置如下
"/website/uploads">  
  Options FollowSymLinks  
  AllowOverride None  
  Order allow,deny  
  Allow from all   
  php_flag engine off