在linux系统下使用nginx做为web应用服务,用来提高网站访问速度的经验已五年多了,今天在此对nginx的使用作一简单总结。php
1、nginx服务简介
Nginx是一个高性能的HTTP和反向代理服务器,也是一个 IMAP/POP3/SMTP代理服务器。Nginx 已经由于它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。css
使用 Nginx 前必须了解的事项:
1)目前官方 Nginx 并不支持 Windows,您只能在包括 Linux、UNIX、BSD 系统下安装和使用;
2)Nginx 自己只是一个 HTTP 和反向代理服务器,它没法像 Apache 同样经过安装各类模块来支持不一样的页面脚本,例如 PHP、CGI 等;
3)Nginx 支持简单的负载均衡和容错;
4)支持做为基本 HTTP 服务器的功能,例如日志、压缩、Byte ranges、Chunked responses、SSL、虚拟主机等等,应有尽有。html
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 进程经过这些套接字接受、读取请求和输出响应。java
Nginx的工做模式很简单,就是采用一个master进程和多个worker工做进程:
其中master进程的做用也是很明确的就是负责管理worker进程,同时监听链接请求,当链接请求到来以后将链接放入worker进程中去处理具体的业务请求,好比说http请求。 Nginx可以处理高并发的缘由在于对socket的管理方式是异步非阻塞的,使用select/poll/epoll/kqueue 来实现对大量socket描述符的管理,每一个worker进程有一个主线程,而没有其余的线程这样的好处就在于不须要进行线程间的切换,这样就节省了资源。因此总的来讲:Nginx可以实现支持高并发的同时运行效率还很低的关键在于整个系统内部只有有限的几个工做进程和一个监听进程,而每一个进程内部只有一个主线程,这样就不会引发不少的线程切换,从而下降了系统开销,同时每一个线程内部使用异步非阻塞的方式来管理描述符这样就能够管理大量的描述符,当描述符多的时候也只是会占用较多的内存而已,而不会形成占用大量cpu时间。以上说的就是Nginx的进程模型和事件模型,事件模型中处理的状况主要有三种,分别是网络事件,如HTTP请求等,网络事件使用异步非阻塞模式就能够很好的解决;还有信号,定时器,信号和定时器还不是很明白。Nginx处理进程间争夺系统资源的方式:也就是进程间存在的惊群现象。node
master:
当 nginx 在启动后,会有一个 master 进程和多个 worker 进程。master进程主要用来管理worker进程,master 要作的就是:接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的运行状态,当 worker 进程退出后(异常状况下),会自动从新启动新的 worker 进程。
主要完成以下工做:
1)读取并验证配置信息;
2)建立、绑定及关闭套接字;
3)启动、终止 worker 进程及维护 worker 进程的个数;
4)无须停止服务而从新配置工做;
5)控制非中断式程序升级,启用新的二进制程序并在须要时回滚至老版本;
6)从新打开日志文件;
7)编译嵌入式perl脚本linux
worker:
对于基本的网络事件,则是放在 worker 进程中来处理了。多个 worker 进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个 worker 进程中处理,一个 worker 进程,不可能处理其它进程的请求(一对一)。然而 nginx 没有专门地仲裁或链接分布的 worker,这项工做是由操做系统内核机制完成的。在启动时,建立一组初始的监听套接字,HTTP 请求和响应之时,worker 连续接收、读取和写入套接字。
worker 进程主要完成的任务包括:
1)接收、传入并处理来自客户端的链接;
2)提供反向代理及过滤功能;
3)nginx任何能完成的其它任务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 进程中处理。web
也许有个疑问,那就是nginx采用多worker 的方式来处理请求,每一个 worker 里面只有一个主线程,那可以处理的并发数颇有限啊,多少个 worker 就能处理多少个并发,何来高并发呢?
然而,这就是 nginx 的高明之处,nginx 采用了异步非阻塞的方式来处理请求,也就是说,nginx 是能够同时处理成千上万个请求的。正则表达式
异步非阻塞
异步的概念是和同步相对的,也就是不一样事件之间不是同时发生的。非阻塞的概念是和阻塞对应的,阻塞是事件按顺序执行,每一事件都要等待上一事件的完成,而非阻塞是若是事件没有准备好,这个事件能够直接返回,过一段时间再进行处理询问,这期间能够作其余事情。
2、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更好。
3、在 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的时候就要根据各自的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 进行控制
Nginx 支持下表中的信号:
有两种方式来经过这些信号去控制Nginx:
第一是经过logs目录下的nginx.pid查看当前运行的Nginx的进程ID,经过 kill – XXX <pid> 来控制 Nginx,其中 XXX 就是上表中列出的信号名。
若是系统中只有一个Nginx进程,那也能够经过 killall 命令来完成,例如运行 killall – s HUP nginx 来让 Nginx 从新加载配置。
配置 Nginx
先来看一个实际的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
好比访问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用来判断文件是否可执行
先来看几个小例子说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
例以下面这段设定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;
}
|
再接着看下面的实例说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#直接匹配网站根,经过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也能够是一个静态首页
# 第一个必选规则
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;
}
================================================================================
访问一个主域名,自动添加www前缀。好比访问http://kevin.com自动跳转http://www.kevin.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
1) 首先要保证不加www和加www的域名都要解析出来。
在DNS里添加kevin.com和www.kevin.com的解析,好比解析到111.110.11.18
@ IN A 111.110.11.18
www IN A 111.110.11.18
解释:
A记录解析kevin.com到111.110.11.18地址上,前面加@或者留空(留空默认就是@)
A记录解析www.kevin.com到111.110.11.18地址上,前面加www
2)nginx配置不加www自动跳转到www的域名访问(80或443都同样),有下面两种方法实现:
方法一:
在conf
/vhost/kevin
.conf文件中配置:
server {
listen 80;
server_name www.kevin.com kevin.com;
index index.jsp index.html index.php index.htm;
root
/var/www/html
;
access_log
/data/nginx/logs/www
.kevin.com-access.log main;
error_log
/data/nginx/logs/www
.kevin.com-error.log;
if
($host =
"kevin.com"
) {
rewrite ^/(.*)$ http:
//www
.kevin.com permanent;
}
}
方法二(官方推荐这一种nginx的301跳转方法)
在conf
/vhost/kevin
.conf文件中配置:
server {
listen 80;
server_name kevin.com;
return
301 http:
//www
.kevin.com$request_uri;
}
server {
listen 80;
server_name www.kevin.com;
index index.jsp index.html index.php index.htm;
root
/var/www/html
;
access_log
/data/nginx/logs/www
.kevin.com-access.log main;
error_log
/data/nginx/logs/www
.kevin.com-error.log;
}
|
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跳转规则的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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不变的例子--------------------------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
须要特别注意的是:
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"
1
2
3
4
5
6
7
8
|
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/
1
2
3
4
5
6
7
8
|
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
1
2
3
4
5
6
7
8
|
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;
}
|
其余配置实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
若是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_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_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;
}
======================================================================
nginx配置只能经过域名禁止ip访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
为何要禁止ip访问页面呢,这样作是为了不其余人把未备案的域名解析到本身的服务器IP,而致使服务器被断网,
能够经过禁止使用ip访问的方法,防止此类事情的发生。
Nginx的默认虚拟主机在用户经过IP访问,或者经过未设置的域名访问(好比有人把他本身的域名指向了你的ip)的时候
生效最关键的一点是,在server的设置里面添加这一行:
listen 80 default;
后面的default参数表示这个是默认虚拟主机。这个设置很是有用。
好比别人经过ip或者未知域名访问你的网站的时候,你但愿禁止显示任何有效内容,能够给他返回500。
网站主关闭空主机头,防止未备案的域名指向过来形成麻烦。就能够这样设置:
server {
listen 80 default;
return
500;
}
也能够把这些流量收集起来,导入到本身的网站,只要作如下跳转设置就能够:
server {
listen 80 default;
rewrite ^(.*) http:
//www
.xxx.com permanent;
}
-----------------特别注意-------------------
按照如上设置后,确实不能经过IP访问服务器了,可是在应该用中出现当server_name后跟多个域名时,
其中一个域名怎么都没法访问:
设置以下:
没更改以前,经过server_name 中的www.xxx.com kevin.com都可访问服务器,加入禁止IP访问的设置后,经过kevin.com没法访问服务器了,www.xxx.com能够访问
用 nginx -t 检测配置文件会提示warning:
最后经过在listen 80 default;后再加server_name _;解决,形式以下:
#禁止IP访问(若是vhosts下面有不少域名的conf配置,那么只须要建立建立一个文件,好比deny.ip.conf,输入下面五行内容,这样就全局禁止了ip访问,只能使用域名访问了!)
server{
listen 80 default;
//
若是是禁止ip的8080端口访问,则将此处的80修改成8080
server_name _;
return
500;
}
或者
server {
listen 80 dufault;
server_name _;
rewrite ^(.*) http:
//www
.xxx.com permanent;
}
这样,经过xxx.com就能访问服务器了,问题解决了。
=====================================================================
也可使用以下设置:即在server段里插入以下内容便可
if
($host !=
'www.kevin.com'
) {
return
403;
}
=====================================================================
|
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
======================Nginx下的限流配置=====================
limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "leaky bucket" #点击前面超连接可查看对应模块官方介绍
limit_req_conn 用来限制同一时间链接数,即并发限制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
|
其中limit_req_conn模块能够根据源IP限制单用户并发访问的链接数或链接到该服务的总并发链接数
什么是漏桶算法?
咱们假设系统是一个漏桶,当请求到达时,就是往漏桶里
"加水"
,而当请求被处理掉,就是水从漏桶的底部漏出。水漏出的速度是固定的,当
"加水"
太快,
桶就会溢出,也就是
"拒绝请求"
。从而使得桶里的水的体积不可能超出桶的容量。主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算
法提供了一种机制,经过它,突发流量能够被整形以便为网络提供一个稳定的流量。
示例一:
http {
limit_conn_log_level error;
limit_conn_status 503;
limit_conn_zone $binary_remote_addr zone=one:10m;
limit_conn_zone $server_name zone=perserver:10m;
limit_req_zone $binary_remote_addr zone=allips:100m rate=10r
/s
;
#其中$binary_remote_addr有时须要根据本身已有的log_format变量配置进行替换
server {
........
limit_conn one 100;
limit_conn perserver 1000;
limit_req zone=allips burst=5 nodelay;
.......
}
}
参数解释:
Zone=one或allips 表示设置了名为
"one"
或
"allips"
的存储区,大小为10兆字节
rate=10r
/s
意思是容许1秒钟不超过10个请求
burst=5 表示最大延迟请求数量不大于5。 若是太过多的请求被限制延迟是不须要的 ,这时须要使用nodelay参数,服务器会马上返回503状态码。
limit_conn one 100表示最大并发链接数100
limit_conn perserver 1000表示该服务提供的总链接数不得超过1000,超过请求的会被拒绝
示例二:
http {
limit_req_zone $binary_remote_addr zone=one:100m rate=10r
/m
;
server {
.......
limit_req zone=one burst=1 nodelay;
......
}
}
解释:
rate=10r
/m
意思是容许1秒钟不超过1个请求,最大延迟请求数量不大于5。
若是请求不须要被延迟,添加nodelay参数,服务器会马上返回503状态码。若是没有该字段会形成大量的tcp链接请求等待。
http{
limit_zone one $binary_remote_addr 10m;
server
{
......
limit_conn one 1;
......
}
}
这里的 one 是声明一个 limit_zone 的名字,$binary_remote_addr是替代 $remore_addr 的变量,10m是会话状态储存的空间。
limit_conn one 1 ,限制客户端并发链接数量为1,allow only one connection per an IP address at a
time
(每次)。
按照字面的理解,lit_req_zone的功能是经过漏桶原理来限制用户的链接频率,(这个模块容许你去限制单个地址指定会话或特殊须要的请求数 )
而 limit_zone 功能是限制一个客户端的并发链接数。(这个模块能够限制单个地址的指定会话或者特殊状况的并发链接数)
一个是限制并发链接一个是限制链接频率,表面上彷佛看不出来有什么区别,那就看看实际的效果吧~~~
在个人测试机上面加上这两个参数下面是个人部分配置文件
http{
limit_zone one $binary_remote_addr 10m;
#limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s;
server
{
......
limit_conn one 1;
#limit_req zone=req_one burst=120;
......
}
}
解释一下 limit_zone one $binary_remote_addr 10m;
这里的 one 是声明一个 limit_zone 的名字,$binary_remote_addr是替代 $remore_addr 的变量,10m是会话状态储存的空间
limit_conn one 1 ,限制客户端并发链接数量为1
============================================================================
limit_zone两种工做状况
a)limit_reqzone=one burst=10 ;
默认状况下是这样配置的,这样每一个请求就会有一个delay时间,
limit_req_zone$binary_remote_addr zone=one:100m rate=10r
/m
;
就是每分钟有10个令牌供用户使用,按照a的配置状况,就会有一个delay,每一个请求时间就是60
/10
,那每一个请求时间就是6s。
b)limit_reqzone=one burst=10 nodelay;
- 添加nodelay配置,这样就是根据你的网络情况访问,一分钟访问够10次后,服务器直接返回503。
- limit_req_zone$binary_remote_addr zone=one:100m rate=10r
/m
;
就是每分钟有10个令牌供用户使用,按照b的配置状况,就会根据网络状况访问url,若是一分钟超过10个令牌,服务器返回503,
等待下一个一分钟领取访问令牌。
rate=10r
/m
的意思是每一个地址每分钟只能请求10次,也就是说根据漏桶原理burst=1 一共有1块令牌,而且每分钟只新增10块
令牌,1块令牌发完后多出来的那些请求就会返回503。
加上nodelay以后超过 burst大小的请求就会直接返回503,若是没有该字段会形成大量的tcp链接请求等待。
例如:
http{
...
#定义一个名为allips的limit_req_zone用来存储session,大小是10M内存,
#以$binary_remote_addr 为key,限制平均每秒的请求为20个,
#1M能存储16000个状态,rete的值必须为整数,
#若是限制两秒钟一个请求,能够设置成30r/m
limit_req_zone $binary_remote_addr zone=allips:10m rate=20r
/s
;
...
server{
...
location {
...
#限制每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秒执行。
limit_req zone=allips burst=5 nodelay;
...
}
...
}
...
}
限制下载速度:
location
/download
{
limit_rate 128k;
}
#若是想设置用户下载文件的前10m大小时不限速,大于10m后再以128kb/s限速能够增长如下配内容,修改nginx.conf文件
location
/download
{
limit_rate_after 10m;
limit_rate 128k;
}
====================================================================
nginx流量限制的使用场景
你们都知道服务器资源有限的,可是客户端来的请求是无限的(不排除恶意攻击), 为了保证大部分的请求可以正常响应,不得不放弃一些客户端来的请求,
因此咱们会采用Nginx的限流操做, 这种操做能够很大程度上缓解服务器的压力, 使其余正常的请求可以获得正常响应。
如何使用Nginx实现基本的限流,好比单个IP限制每秒访问50次。经过Nginx限流模块,咱们能够设置一旦并发链接数超过咱们的设置,将返回503错误给客户端。
这样能够很是有效的防止CC攻击。再配合 iptables防火墙,基本上CC攻击就能够无视了。
配置实例:
#统一在http域中进行配置
#限制请求
limit_req_zone $binary_remote_addr $uri zone=api_read:20m rate=50r
/s
;
#按ip配置一个链接 zone
limit_conn_zone $binary_remote_addr zone=perip_conn:10m;
#按server配置一个链接 zone
limit_conn_zone $server_name zone=perserver_conn:100m;
server {
listen 80;
server_name report.52itstyle.com;
index login.jsp;
location / {
#请求限流排队经过 burst默认是0
limit_req zone=api_read burst=5;
#链接数限制,每一个IP并发请求为2
limit_conn perip_conn 2;
#服务所限制的链接数(即限制了该server并发链接数量)
limit_conn perserver_conn 1000;
#链接限速
limit_rate 100k;
proxy_pass http:
//report
;
}
}
upstream report {
fair;
server 192.168.10.12:8882 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.10.12:8881 weight=1 max_fails=2 fail_timeout=30s;
}
配置503错误
默认状况,超出限制额度,将会报503错误,提示:
503 Service Temporarily Unavailable
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later. Sorry
for
the inconvenience.
Please report this message and include the following information to us.
Thank you very much!
这样显示没毛病,可是不够友好,这里咱们自定义503错误。
error_page 500 502 503 504
/50x
.html;
location =
/50x
.html {
root html;
#自定义50X错误
}
配置说明
limit_conn_zone
是针对每一个IP定义一个存储session状态的容器。这个示例中定义了一个100m的容器,按照32bytes
/session
,能够处理3200000个session。
limit_rate 300k;
对每一个链接限速300k. 注意,这里是对链接限速,而不是对IP限速。若是一个IP容许两个并发链接,那么这个IP就是限速limit_rate×2。
burst=5;
这至关于在检查站req旁边放5个座位。若是某个请求当时超过速度限制被拦了,请他在空座位上坐着,等排队,若是检查站空了,就能够经过。
若是连座位都坐满了,那就抱歉了,请求直接退回,客户端获得一个服务器忙的响应。因此说burst跟request_rate一点关系都没有,设成10000,
就是1万个请求能够等着排队,而检查站仍是1秒钟放行5个请求(龟速)。并且也不能一直排队,因此nginx还设了超时,排队超过必定时间,
也是直接退回,返回服务器忙的响应。
以上配置Nginx须要配置如下模块:
ngx_http_limit_conn_module (static)
ngx_http_limit_req_module (static)
执行命令
"nginx -V"
就能够检查到是否有安装。
===================================================================
电商平台营销时候,常常会碰到的大流量问题,除了作流量分流处理,可能还要作用户黑白名单、信誉分析,进而根据用户ip信誉权重作相应的流量拦截、限制流量。
Nginx自身有的请求限制模块ngx_http_limit_req_module、流量限制模块ngx_stream_limit_conn_module基于令牌桶算法,能够方便的控制令牌速率,自定义
调节限流,实现基本的限流控制。
对于提供下载的网站,确定是要进行流量控制的,例如软件下载站、视频服务等。它也能够减小一些爬虫程序或者DDOS的攻击。
limit_zone指令能够用limit_conn_zone替换
如何Nginx限制同一个ip的链接数,限制并发数目?
限流
1) 添加limit_zone和limit_req_zone
这个变量只能在http区域使用 :
http {
limit_zone one $binary_remote_addr 20m;
limit_req_zone $binary_remote_addr zone=req_one:20m rate=12r
/s
;
......
}
2) 添加limit_conn 和limit_req
这个变量能够在http, server, location使用。若是限制nginx上的全部服务,就添加到http里面;若是限制部分服务,就添加到相应的server或者location里。
http {
limit_zone one $binary_remote_addr 20m;
limit_req_zone $binary_remote_addr zone=req_one:20m rate=12r
/s
;
limit_conn one 10;
limit_req zone=req_one burst=120;
......
}
参数详解(数值按具体须要和服务器承载能力设置):
limit_zone,是针对每一个变量(这里指IP,即$binary_remote_addr)定义一个存储session状态的容器。这个示例中定义了一个20m的容器,按照32bytes
/session
,能够处理640000个session。
limit_req_zone 与limit_zone相似。rate是请求频率. 每秒容许12个请求。
limit_conn one 10 : 表示一个IP能发起10个并发链接数
limit_req: 与limit_req_zone对应。burst表示缓存住的请求数。
配置范例:
http
{
limit_zone one $binary_remote_addr 20m;
limit_req_zone $binary_remote_addr zone=req_one:20m rate=12r
/s
;
limit_conn one 10;
limit_req zone=req_one burst=120;
server {
listen 80;
server_name status.
test
.kevin.com ;
location / {
stub_status on;
access_log off;
}
}
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++
nginx白名单设置
以上配置会对全部的ip都进行限制,有些时候咱们不但愿对搜索引擎的蜘蛛或者某些本身的代理机过来的请求进行限制,
对于特定的白名单ip咱们能够借助geo指令实现。
先在nginx的请求日志进行统计,查看那个ip的访问量比较大,运行:
# cat access.log | grep "03/Jun" |awk '{print $1}'|sort |uniq -c|sort -nrk 1|head -n 10
#列出访问日志里面在6月3号这天前10个访问量最大的ip.
接下来就能够对这些IP进行分析了。看哪些须要进行白名单设置。
http{
geo $limited {
# the variable created is $limited
default 1;
127.0.0.1
/32
0;
10.12.212.63 0;
}
map $limited $limit {
1 $binary_remote_addr;
0
""
;
}
limit_zone one $binary_remote_addr 20m;
limit_req_zone $limit zone=req_one:20m rate=20r
/s
;
limit_conn one 10;
limit_req zone=req_one burst=120;
}
上面两个须要用到map和geo模块,这是nginx自带的模块,有的运维喜欢把他们关闭,本身.
/sbin/nginx
-V 留意一下。
把配置的--whithout-XXX-module 去掉从新编译一下就能够了。 上面这段配置的意思是:
a)geo指令定义了一个白名单limited变量,默认值为1,若是客户端ip在上面的范围内,limited变量,默认值为1,若是客户端ip在上面的范围内,
limited的值为0
b)使用map指令映射搜索引擎客户端的ip为空串,若是不是搜索引擎就显示自己真实的ip,这样搜索引擎ip就不能存到limit_req_zone内存session中,
因此不会限制搜索引擎的ip访问
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
获取客户端的真实IP?
顺带一提,为了获取客户端的真实IP。该模块须要安装read_ip模块,运维应该默认有安装。没有的话也可自行安装:
配置方式至关简单,从新编译Nginx 加上 --with-http_realip_module 参数,如:
# ./configure --prefix=/opt/nginx --with-http_stub_status_module --with-pcre=../pcre-6.6 --with-http_realip_module
# make
# make install
在server中增长:
set_real_ip_from 192.168.1.0
/24
;
set_real_ip_from 192.168.2.1;
real_ip_header [X-Real-IP|X-Forwarded-For];
须要说明的地方就是设置IP源的时候能够设置单个IP,也能够设置IP段,另外是使用X-Real-IP仍是X-Forwarded-For,取决于前面的服务器有哪一个头。
set_real_ip_from 设置的IP端可让运维查看日志,看下你的请求是来自哪些ip段。
从新加载一下服务,差很少就OK了。
再查看日志的话,应该能够看到客户端的真实IP了。
注意:若是未安装该模块的话你的获取到的IP端多是来自前端代理(如squid)的IP,结果就是多个用户被当成单个用户对待,致使应用不能响应。
------自测: 有条件的本身能够用ab或者webben自测一下--------
未安装前压测的话,由于有大量请求,因此access.log会有大量日志,而error.log日志没有变化。
[root@kevin ~]
# webbench -c 30 -t 30 http://test.kevin.com
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http:
//test
.kevin.com
30 clients, running 30 sec.
Speed=193468 pages
/min
, 1254317 bytes
/sec
.
Requests: 96734 susceed, 0 failed.
安装后会发现不少超出的请求会返回503,因此access.log日志变化不快,error.log有大量记录,提示limit_reque缓住了多少请求。
kevin ~ webbench -c 30 -t 30 http:
//test
.kevin.com
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http:
//test
.kevin.com
30 clients, running 30 sec.
Speed=120 pages
/min
, 778 bytes
/sec
.
Requests: 60 susceed, 0 failed.
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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参数,不然就会覆盖以前添加的用户!
下面顺便看几个认证部分的配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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 配置文件修改:
最后展现:
使ab命令进行测试,比较修改nginx配置文件先后(链接数和请求数分开测试)的测试结果。
修改以前:
测试结果为:
对nginx配置作修改(添加http和php配置以下的红线内容),重启,而后再进行测试
测试结果为:
11.访问白名单
参考:nginx访问白名单设置以及根据$remote_addr分发
12.nginx的上传下载设置
参考:nginx限制上传大小和超时时间设置说明/php限制上传大小
13.nginx目录浏览及其验证功能
参考:nginx下目录浏览及其验证功能配置记录
14.Nginx下禁止指定目录运行php脚本文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
很是简单,直接经过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
|
15.Nginx下开启gzip压缩功能,大幅提升页面加载速度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
若是发现如上配置后,访问页面时,
gzip
压缩没有生效。通常缘由就是该页面的相应的gzip_type类型没有加进去。
检查一个页面的
gzip
是否生效:
[root@uatinner-lb01 ~]
# curl -I -H "Accept-Encoding: gzip, deflate" "http://www.kevin.com/blog/plugins/bo-coolings/bo-coolings.css"
HTTP
/1
.1 200 OK
Date: Fri, 14 Sep 2018 09:10:38 GMT
Content-Type: text
/html
Connection: keep-alive
Set-Cookie: __cfduid=da2267d06a7d8364c8d4c9193627d56f91536916238; expires=Sat, 14-Sep-19 09:10:38 GMT; path=/; domain=.slyar.com; HttpOnly
CF-Cache-Status: EXPIRED
Expires: Tue, 19 Mar 2019 09:10:38 GMT
Cache-Control: public, max-age=16070400
Vary: Accept-Encoding
Server: cloudflare
CF-RAY: 45a1b8bb26712132-LAX
Content-Encoding:
gzip
若是发现访问如上的http:
//www
.kevin.com
/blog/plugins/bo-coolings/bo-coolings
.css页面时,
gzip
没有生效。
就注意查看下上面结果中的Content-Type类型的内容(如上是text
/html
)是否加到了nginx.conf文件中
gzip
配置区域里。若是没有,就加上,并reload nginx服务便可!
|
16.Nginx使用非root用户启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
在linux系统里, 监听端口在1024如下的服务必须使用root用户启动, 1024以上端口的应用服务可使用非root用户启动.
好比, nginx默认端口是80, 必须使用root用户启动. 考虑到安全问题, 采用非root用户启动, 好比app用户.
[root@web ~]
# cat /data/nginx/conf/nginx.conf
user app;
而后切换到app用户下启动
[root@web ~]
# su - app
[app@web ~]$
/data/nginx/sbin/nginx
非root用户在检查nginx配置文件或启动nginx的时候,会出现告警信息:
nginx: [warn] the
"app"
directive makes sense only
if
the master process runs with super-user privileges, ignored
in
/data/nginx/conf/nginx
.conf:2
这是由于:
- 在非root帐户下启动时,nignx的master和worker进程的owner都将是这个帐户(这里是app用户),
- 在root帐户下启动时 nignx的master进程是的owner是rootworker的owner在conf已配置用户的状况下,owner是配置的用户,不然将是nobody,
并且也可能致使nginx的一些文件的owner也是nobody
因此出现了上面那个warn告警信息, 能够忽略, 不影响
[app@web ~]$
ps
-ef|
grep
nginx
app 8837 1 0 16:02 ? 00:00:00 nginx: master process
/data/nginx/sbin/nginx
app 8838 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8839 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8840 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8841 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8842 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8843 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8844 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8845 8837 0 16:02 ? 00:00:00 nginx: worker process
app 8846 8837 0 16:02 ? 00:00:00 nginx: cache manager process
|
17. Nginx实现404错误页面跳转的几种方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
|
Nginx做为经常使用网站的web服务器, 出现404错误页面的跳转实现方式主要有如下几种:
第一种状况: Nginx本身的错误页面
Nginx访问一个静态的html 页面,当这个页面没有的时候,Nginx抛出404,那么如何返回给客户端404呢?
看下面的配置,这种状况下不须要修改任何参数,就能实现这个功能。
[root@localhost ~]
# cat /data/nginx/conf/nginx.conf
.........
http {
proxy_intercept_errors on;
//
若是nginx不作代理, 不代理到后面的tomcat服务器, 只是本身的静态页访问, 则这一行加不加均可以实现;
[root@localhost ~]
# cat /data/nginx/conf/test.conf
server {
listen 80;
server_name localhost;
access_log
/data/nginx/logs/access
.log main;
error_log
/data/nginx/logs/error
.log;
location / {
root
/data/web
;
index index.php index.html index.htm;
}
#定义错误页面码,若是出现相应的错误页面码,转发到那里。
error_page 404 403 500 502 503 504
/404
.html;
#承接上面的location。
location =
/404
.html {
#放错误页面的目录路径。
root
/data/web
;
}
}
------------------------------------------------------------------------------------------
须要注意:
若是是跳转到其余url, 则配置改成:
#定义错误页面码,若是出现相应的错误页面码,转发到那里。
error_page 404 403 500 504 http:
//www
.haha.com;
------------------------------------------------------------------------------------------
须要注意:
或是能够设置多种类型的错误页面
# 这里的错误码能够是多个
error_page 500 502 503 504
/50x
.html;
location =
/50x
.html {
root
/data/web
;
}
error_page 404
/404
.html;
location =
/404
.html {
root
/data/web
;
}
而后在定义的
/data/web
目录下编写50x.html和404.html错误页面内容
-----------------------------------------------------------------------------------------
到定义的错误页面存放目录下编辑404错误页面内容:
[root@localhost vhosts]
# ll /data/web/
total 8
-rw-r--r-- 1 root root 50 Dec 19 16:04 404.html
-rw-r--r-- 1 root root 21 Dec 19 15:59 index.html
[root@localhost vhosts]
# cat /data/web/404.html
Sorry, sir, this page does not exist! Excuse me ~
重启nginx服务
[root@localhost vhosts]
# /data/nginx/sbin/nginx -t
nginx: the configuration
file
/data/nginx/conf/nginx
.conf syntax is ok
nginx: configuration
file
/data/nginx/conf/nginx
.conf
test
is successful
[root@localhost vhosts]
# /data/nginx/sbin/nginx -s reload
而后访问nginx的地址, 当访问一个错误页面时, 就会出现定义的404错误页面内容:
"Sorry, sir, this page does not exist! Excuse me ~"
============================================
第二种:反向代理的错误页面 (nginx代理的后端是tomcat页面, 使用proxy_intercept_errors on参数, 该参数能够放在http区域, 也能够访问server或location区域)
若是后台Tomcat处理报错抛出404,想把这个状态叫Nginx反馈给客户端或者重定向到某个链接.
好比在本身的Linux服务器上部署了tomcat的一个项目,使用Nginx进行的代理,访问项目不存在的页面时,出现的是Nginx默认的404页面,
如今要配置本身定义的404页面进行提示
配置以下:
[root@localhost ~]
# cat /data/nginx/conf/vhost/test.conf
upstream tomcat {
ip_hash;
server 127.0.0.1:8080 weight=20 max_fails=2 fail_timeout=30s;
}
server {
listen 80;
server_name www.
test
.com;
access_log
/data/nginx/logs/access
.log main;
error_log
/data/nginx/logs/error
.log;
location / {
# 即把www.test.com的首页设定为index.html (默认状况下tomcat的首页是index.jsp, 这里在tomcat下的webapp/ROOT下加了index.html)
if
($request_uri ~*
'^/$'
) {
rewrite .* http:
//www
.
test
.com
/index
.html redirect;
}
#关键参数(好比加下面这一行的参数配置):这个变量开启后,咱们才能自定义错误页面,当后端返回404,nginx拦截错误定义错误页面
proxy_intercept_errors on;
proxy_pass http:
//tomcat
;
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for;
}
error_page 404
/404
.html;
location =
/404
.html {
root
/mnt/error
;
}
}
配置解释:
if
($request_uri ~*
"^/$"
) 表示url中只有域名,后面不跟任何东西,好比www.
test
.com。
if
($request_uri ~*
"test"
) 表示域名后面那串儿只要包含
test
这个关键词,就可匹配成功。好比www.
test
.com
/pan/beta/test3
上面的配置表示:
当访问http:
//www
.
test
.com 时(即url只有一个完整的域名) 时, 页面跳转到tomcat跟下的index.html (即tomcat的webapp
/ROOT/index
.html, tomcat的默认首页通常是webapp
/ROOT/index
.jsp)
也就是访问http:
//www
.
test
.com, 显示为http:
//www
.
test
.com
/index
.html, 这个index.html是tomcat的webapp
/ROOT/index
.html
当访问http:
//www
.
test
.com/* 时, 跳转到http:
//127
.0.0.1:8080/* , 好比访问 http:
//www
.
test
.com
/index
.jsp, 跳转到http:
//127
.0.0.1:8080
/index
.jsp,
当访问http:
//www
.
test
.com/* 的页面时, 页面不存在, 则显示404错误页面, 错误页面文件为
/mnt/error/404
.html
[root@localhost ~]
# ll /usr/local/tomcat8/webapps/ROOT/index.html
-rw-r--r-- 1 root root 21 Dec 19 16:32
/usr/local/tomcat8/webapps/ROOT/index
.html
[root@localhost ~]
# ll /usr/local/tomcat8/webapps/ROOT/index.jsp
-rw-r--r-- 1 root root 12513 Jun 29 10:44
/usr/local/tomcat8/webapps/ROOT/index
.jsp
[root@localhost ~]
# ll /mnt/error/404.html
-rw-r--r-- 1 root root 31 Dec 19 17:12
/mnt/error/404
.html
[root@localhost ~]
# /data/nginx/sbin/nginx -s reload
-------------------------------------------------------------------------------------------------------------------
这里注意下: 看下面这个状况的错误页面本地跳转配置
[root@localhost ~]
# cat /data/nginx/conf/nginx.conf
..........
http {
proxy_intercept_errors on;
[root@localhost ~]
# cat /data/nginx/conf/vhosts/test.conf
server {
listen 80;
server_name www.
test
.com;
access_log
/data/nginx/logs/access
.log main;
error_log
/data/nginx/logs/error
.log;
location / {
proxy_pass http:
//127
.0.0.1:8080;
proxy_set_header REMOTE-HOST $remote_addr;
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 20m;
}
location
/upload
{
root
/data/web
;
index index.html index.htm;
}
#error_page 404 /404.html;
error_page 500 502 503 504
/404
.html;
error_page 404
/404
.html;
location =
/404
.html {
root
/data/web/error
;
}
}
[root@localhost ~]
# cat /data/web/error/404.html
Sorry, sir, this page does not exist! Excuse me ~
[root@localhost ~]
# /data/nginx/sbin/nginx -s reload
当8080端口的tomcat服务没有开启时, 访问http:
//www
.
test
.com , 则会出现定义在
/data/web/error/404
.html错误页面内容
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
================================================
第三种:反向代理的错误页面 (nginx代理的后端是php解析的页面, 使用fastcgi_intercept_errors on参数, 该参数能够放在http区域, 也能够访问server或location区域)
Nginx解析php代码的错误页面, 若是后端是php解析的,须要加一个变量fastcgi_intercept_errors on进行错误页面提示, 不然php页面则显示为空白页!
在http段中加一个变量 fastcgi_intercept_errors on 就能够了。
[root@localhost ~]
# vim /data/nginx/conf/nginx.conf
.........
http {
fastcgi_intercept_errors on;
接着指定一个错误页面
[root@localhost ~]
# vim /data/nginx/conf/vhosts/test.conf
........
error_page 404
/404
.html;
location =
/404
.html {
root
/mnt/error
;
}
错误页面404.html 放在
/mnt/error
下面
若是指定404错误时跳转到其余的一个错误页面, 配置为
[root@localhost ~]
# vim /data/nginx/conf/vhosts/test.conf
........
error_page 404
/404
.html;
error_page 404 = http:
//www
.
test
.com
/error
.html;
=================================================================
舒适提示:
配置proxy_intercept_errors on时, 配置的错误页面表示的是当服务器返回的状态码为咱们配置的状态码时,才进行的页面跳转。
如:服务器中没有xxxx.
do
接口时,访问了这个接口,配置了proxy_intercept_errors on则也会进行页面跳转
若是服务器中没有开启服务,则配置proxy_intercept_errors on无用,则须要再添加fastcgi_intercept_errors on配置,
这样的话,出现页面错误时也会进行跳转
总结:
=====什么是404页面======
若是碰巧网站出了问题,或者用户试图访问一个并不存在的页面时,此时服务器会返回代码为404的错误信息,此时对应页面就是404页面。
404页面的默认内容和具体的服务器有关。若是后台用的是NGINX服务器,那么404页面的内容则为:404 Not Found
NGINX下如何自定义404页面
1) 更改nginx.conf在http定义区域加入: proxy_intercept_errors或者fastcgi_intercept_errors
2) 更改nginx.conf,在server 区域加入: error_page 404
/404
.html 或者 error_page 404 =http:
//www
.xxx.com
/404
.html
3) 更改后重启nginx,,测试nginx.conf正确性
#502 等错误能够用一样的方法来配置。 配置以下:
error_page 500 502 503 504
/50x
.html;
location =
/50x
.html {
root
/mnt/error
;
}
或是
error_page 500 501 502 503 504 @errpage;
location @errpage {
access_log logs
/access
.log maintry;
proxy_pass url;
}
注意事项:
1) 要添加:fastcgi_intercept_errors on 或者 proxy_intercept_errors
默认: fastcgi_intercept_errors off
添加位置: http, server, location
默认状况下,nginx不支持自定义404错误页面,只有这个指令被设置为on,nginx才支持将404错误重定向
这个指令指定是否传递4xx和5xx错误信息到客户端,或者容许nginx使用error_page处理错误信息。你必须明确的在error_page中指定处理方法使这个参数有效
2) 不要出于省事或者提升首页权重的目的将首页指定为404错误页面,也不要用其它方法跳转到首页
3) 自定义的404页面必须大于512字节,不然可能会出现IE默认的404页面。例如,假设自定义了404.html,大小只有11个字节(内容为:404错误)
===== fastcgi_intercept_errors 参数=====
语法:fastcgi_intercept_errors on|off
默认值:fastcgi_intercept_errors off
使用字段:http, server, location
这个指令指定是否传递4xx和5xx错误信息到客户端,或者容许nginx使用error_page处理错误信息。
你必须明确的在error_page中指定处理方法使这个参数有效,正如Igor所说“若是没有适当的处理方法,nginx不会拦截一个错误,这个错误不会显示本身的默认页面,这里容许经过某些方法拦截错误。
===== f注意搞清楚下面状况===== f
404.html:上游服务器提供的特定404页面内容,当nginx:80访问上游服务器资源不存在(返回404),要求显示的内容页面。
404_default.html:上游服务器默认404页面。
配置以下:
error_page 404
/404
.html;
location =
/404
.html {
root
/mnt/error
;
}
或者
error_page 404
/404_default
.html;
location =
/404_default
.html {
root
/mnt/error
;
}
50x.html:上游服务器提供的特定50x页面内容,当nginx:80访问上游服务器出现50x错误(包含500, 502, 503和504),要求显示的内容页面。
50x_default.html:上游服务器提供的处理50x的默认页面
配置以下:
error_page 50x
/50x
.html;
location =
/50x
.html {
root
/mnt/error
;
}
或者
error_page 50x
/50x_default
.html;
location =
/50x_default
.html {
root
/mnt/error
;
}
|
18. nginx实现动静分离
将静态资源放在 A 主机的一个目录上,将动态程序放在 B 主机上,同时在 A 上安装 Nginx 而且在 B 上安装 Tomcat。配置 Nginx,当请求的是 html、jpg 等静态资源时,就访问 A 主机上的静态资源目录;当用户提出动态资源的请求时,则将请求转发到后端的 B 服务器上,交由 Tomcat 处理,再由 Nginx 将结果返回给请求端。
提到这,可能会有疑问,动态请求要先访问 A,A 转发访问 B,再由 B 返回结果给 A,A 最后又将结果返回给客户端,这是否是有点多余。初看的确多余,可是这样作至少有 2 点好处。第一,为负载均衡作准备,由于随着系统的发展壮大,只用一台 B 来处理动态请求显然是是不够的,要有 B1,B2 等等才行。那么基于图 2 的结构,就能够直接扩展 B1,B2,再修改 Nginx 的配置就能够实现 B1 和 B2 的负载均衡。第二,对于程序开发而言,这种结构的程序撰写和单台主机没有区别。咱们假设只用一台 Tomcat 做为服务器,那么凡是静态资源,如图片、CSS 代码,就须要编写相似这样的访问代码:<img src=”{address of A}/a.jpg”>,当静态资源过多,须要扩展出其余的服务器来安放静态资源时,访问这些资源就可能要编写这样的代码:<img src=”{address of C}/a.jpg”>、<img src=”{address of D}/a.jpg”>。能够看到,当服务器进行变动或扩展时,代码也要随之作出修改,对于程序开发和维护来讲很是困难。而基于上面的结构,程序都只 要 <img src=”a.jpg”>,无需关心具体放置资源的服务器地址,由于具体的地址 Nginx 为帮您绑定和选择。
动静分离的nginx配置以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
# 转发的服务器,upstream 为负载均衡作准备
upstream tomcat_server{
server 172.16.50.60:8080 weight=1 max_fails=2 fail_timeout=2;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root
/data/web
;
index index.html index.htm;
}
# 静态请求直接读取
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|js|css)$ {
root
/data/web
;
expires 30d;
#缓存时间,即有效时间
}
# 动态请求的转发
location ~ .*.jsp$ {
proxy_pass http:
//tomcat_server
;
proxy_set_header Host $host;
}
}
=============================================================
若是还有php文件, 则配置添加以下:
upstream php {
server 172.16.50.15 weight=1 max_fails=2 fail_timeout=2;
server 172.16.50.16 weight=1 max_fails=2 fail_timeout=2;
}
.......
location ~* \.php$ {
fastcgi_proxy http:
//php
;
}
==================================================================
|
18. nginx配置中关于url的几个变量的区别 (如$request_uri , $uri 和 $document_uri )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
$request_uri
这个变量等于从客户端发送来的原生请求URI,包括参数。它不能够进行修改。$uri变量反映的是重写后/改变的URI。不包括主机名。
其实这个$request_uri变量指的就是完整url中刨去最前面$host剩下的部分.
好比http:
//www
.baidu.com
/pan/beta/test1
?fid=3这个url地址,去掉www.baidu.com剩下的就是了,日志里会看到打印出来的$request_uri,
$request_uri其实指的就是
/pan/beta/test1
?fid=3
以下匹配规则:
if
($request_uri ~*
"^/$"
) 表示url中只有域名,后面不跟任何东西,好比www.baidu.com。
if
($request_uri ~*
"test"
) 表示域名后面那串儿只要包含
test
这个关键词,就可匹配成功。好比www.baidu.com
/pan/beta/test3
$uri
这个变量指当前的请求URI,不包括任何参数。这个变量反映任何内部重定向或index模块所作的修改。
注意,这和request_uri不一样,因$request_uri是浏览器发起的不作任何修改的原生URI。不包括协议及主机名。
好比http:
//www
.baidu.com
/pan/beta/test1
?fid=3这个url地址,日志里会看到打印出来的$uri其实指的就是
/pan/beta/test1
$document_uri
这个变量等同于$uri.
例如:
"/pan/beta/test1"
总而言之:
$request_uri变量指的则是请求的整个字符串,包含了后面的query_string的。
$uri变量: 指的是请求的文件和路径,不包括
"?"
或者
"#"
以后的东西
例如, 访问http:
//www
.kevin.com
/stat
.php?
id
=1585378&web_id=1585378
则这三个变量分别指的是:
$request_uri:
/stat
.php?
id
=1585378&web_id=1585378
$uri:
/stat
.php
$document_uri:
/stat
.php
|