nginx其他常用配置

除了nginx安装及配置多域名初体验里的一些配置,这里详细说下几个常用的配置:状态信息、访问日志、限制访问、错误页面、Nginx代理等。

nginx常用命令

nginx -v:查看nginx版本

nginx -s stop:停止nginx服务

nginx -s reload:平滑重新加载nginx配置文件

nginx -t:检查默认配置文件

nginx -t -c file.conf:指定配置文件进行检查

nginx默认目录

工作目录:/etc/nginx

执行文件: /usr/sbin/nginx

日志目录:/var/log/nginx

启动文件:/etc/init.d/nginx

web目录:/var/www/html/,首页文件是index.nginx-debian.html

​ /usr/share/nginx/html/ 首页文件是index.html

nginx默认配置文件

默认文件:/etc/nginx/nginx.conf

其他目录:/etc/nginx/{sites-available/sites-enabled/conf.d}

配置文件结构

1
2
3
4
|- 全局配置段
│ ├─ http配置段
│ │ ├─ server配置段(项目或者应用)
│ │ │ ├─ location配置段(url配置)

nginx全局配置段

主要是全局性的和服务级别的属性配置,常见的主要有以下几种设置:

1
2
3
4
5
6
7
user 					设置使用用户(worker)
worker_processes 进行增大并发连接数的处理 跟cpu保持一致 八核设置八个
error_log nginx的错误日志
pid nginx服务启动时候pid
events 定义事件相关的属性
worker_connections 一个进程允许处理的最大连接数
use 定义使用的内核模型

http配置段

主要配置server通用的一些配置

1
2
3
4
5
6
7
8
include mime.types;              # 文件扩展名与文件类型映射表
default_type application/octet-stream; # 默认文件类型
sendfile on; # 开启高效文件传输模式。
autoindex on; # 开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on; # 防止网络阻塞
tcp_nodelay on; # 防止网络阻塞
keepalive_timeout 120; # 长连接超时时间,单位是秒
gzip on; # 开启gzip压缩输出

Server常见配置属性

server配置段最重要的属性是listen和server_name。它们都是用于匹配并处理请求的。

常见样式

1
2
3
4
5
server {
listen 端口;
server_name 主机名;
...
}

listen属性

作用

定义Server监听的ip和port,当ip/port匹配时候才进行下一步匹配

表现形式
形式描述示例完整示例
IP:Port地址精确表示样式listen 10.10.10.10:99listen 10.10.10.10:99
IP自动监听 IP:80地址listen 10.10.10.10listen 10.10.10.10:80
Port自动监听 全地址:Portlisten 99或 [::]:99listen 0.0.0.0:99
default_server自动使用默认的地址listen default_serverlisten localhost:80
使用原则

首先将所有样式补全成IP:Port,然后匹配,匹配Server多,那么接着使用Server_name匹配

server_name属性

作用

定义Server监听的域名,当域名匹配时候才进行下一步操作

表现形式
格式完整样式前缀正则样式后缀正则样式禁止非法域名或IP
形式www.example.com*.example.comwww.example.*_
使用原则

优先使用完整样式,然后使用前缀正则样式,最后使用后缀正则样式,如果正则样式相同的时候,匹配最长,否则就走非法规则。

非法域名/IP,表示请求到该主机上一个不存在的IP或者域名

root属性

后面location中会详细介绍该属性

作用

定义Server相应请求的html文件所在路径

表现形式

root /var/www/html;

index属性

作用

定义响应请求后返回的文件名称或格式

表现形式

index index.html index.htm index.nginx-debian.html;

return属性

location中会详细介绍该属性

作用

定义响应请求后返回的http状态码

表现形式

return 444;

Nginx状态信息(status)配置

Nginx状态信息(status)配置及信息详解

nginxphp-fpm一样内建了一个状态页,对于想了解nginx的状态以及监控nginx非常有帮助。为了后续的zabbix监控,我们需要先了解一下nginx的状态页。

Nginx状态信息(status)介绍

Nginx软件在编译时又一个with-http_stub_status_module模块,这个模块功能是记录Nginx的基本访问状态信息,让使用者了解Nginx的工作状态。
要想使用状态模块,在编译时必须增加--with-http_stub_status_module参数。

检测status模块

1
2
3
4
5
6
root@Tony-PC:~# nginx -V
nginx version: nginx/1.13.12
built with OpenSSL 1.1.0h 27 Mar 2018
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-THAKdv/nginx-1.13.12=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --c
onf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module

通过ab压测命令检测

1
2
yum -y install httpd-tools
# 安装测试工具
1
2
3
4
5
ab -kc 1000 -n 100000 http://192.168.119.10/
# -n requests #执行的请求数,即一共发起多少请求。
# -c concurrency #请求并发数。
# -k #启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。
# 执行测试

1
2
3
4
5
6
7
8
9
10
Active connections: 596 # 正在处理的活动连接数596个
server accepts handled requests # 服务器接收的请求数
2604 2604 3712
# nginx启动到现在共处理了2604个链接
# nginx共成功创建2604次握手
# handled requests表示处理了3712次请求
Reading: 0 Writing: 1 Waiting: 595
# Reading: nginx读取到的header信息数
# Writing: nginx返回给客户端的header数
# Waiting: 已处理完,等待下次请求的连接数

Nginx访问日志

日志功能对每个用户访问网站的日志信息记录到指定的日志文件里,开发运维人员可以分析用户的浏览器行为。

1
2
3
4
5
6
7
8
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 /var/log/nginx/access.log main;

# log_format 记录日志的格式,可定义多种格式
# accsss_log 指定日志文件的路径以及格式
#log_format是日志关键字参数,不能变;main是日志格式指定的标签,记录日志时通过main标签选择指定的格式。

log_format参数:

1
2
3
4
5
6
7
8
9
$remote_addr    记录客户端ip
$remote_user 远程用户,没有就是 “-”
$time_local    对应[14/Aug/2018:18:46:52 +0800]
$request     对应请求信息"GET /favicon.ico HTTP/1.1"
$status     状态码
$body_bytes_sent  571字节 请求体的大小
$http_referer  对应“-”  由于是直接输入浏览器就是 -
$http_user_agent  客户端身份信息
$http_x_forwarded_for  记录客户端的来源真实ip 97.64.34.118

日志效果:

1
2
79.107.136.94 - - [16/Aug/2019:14:17:44 +0800] "GET / HTTP/1.1" 200 3706 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.
36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36" "-"

限制访问

如果哪天发现你的nginx很慢,或者检查access.log时候,有一个some body疯狂请求你的nginx server,那么可以禁止这个IP访问

1
2
3
4
5
6
# 限制ip或ip段访问;禁止访问/av/底下的资源
location /av {
deny 122.71.240.254;
#alias /opt/nginx1-12/html/av;
allow 10.1.1.0/16;
}

使用浏览器访问,提示如下:

且日志里自动写入了该条访问记录,状态码为:403

1
2
180.169.32.34 - - [16/Aug/2019:14:30:28 +0800] "GET /av HTTP/1.1" 403 169 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv
:11.0) like Gecko Core/1.70.3722.400 QQBrowser/10.5.3738.400" "-"

错误页面

在网站运行过程中,可能因为页面不存在等原因,导致网站无法正常响应请求,此时web服务会返回系统的错误码,但是默认的错误页面很不友好。

因此我们可以将404,403等页面的错误信息重定向到网站首页或者其他指定的页面,提升用户访问体验

1
2
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

修改404.html文件,重新访问一个不存在的页面提示如下:

Location配置

location主要是根据Server匹配到的请求路径和关键字去响应和处理。

语法:

1
2
location optional_modifier location_match { ... } 
location @name { ... }

其中:optional_modifier是匹配条件,location_match是匹配的样式,{}是要执行的操作。匹配条件主要有两种:正则/前缀字符。

匹配规则

正则匹配

类型含义匹配方式优先级样式
`~!~`普通正则-敏感|不敏感正则符号3
`~*!~*`普通正则-不敏感|敏感正则符号3

普通匹配

类型含义匹配方式优先级样式
=/路径精确匹配前缀1location = /image {}
^~优先匹配前缀2location ^~ /page {}
@内部重定向前缀location @name {}
空 /通用匹配前缀4location / {}

使用原则

前提:根据请求url,获取uri即除了域名/IP之外的部分,用于location匹配

如果有精确匹配,即 =/路径,找到匹配项后,结束匹配。

location = 路径 {} 或者 location 完整路径 {}

如果有优先匹配,即 ^~,找到匹配项后,结束匹配。

location ^~ 路径

如果有正则匹配,即 ~|!~|~*|!~*,找到匹配项后,不会终止继续匹配,直到找到合适的

location ~* 正则字符 {}

如果匹配到多个,则使用location_match最长的。

匹配示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
location = / {
#精确规则A
# 访问根目录会被匹配
}
location = /login {
#精确规则B
#完全匹配访问/login
}
location ^~ /static/ {
# 优先规则C
# 访问/static/开头的请求且区分大小写,大写不会被匹配到
}
location ~ \.(gif|jpg|png|js|css)$ {
#正则规则D
# 访问以.gif、.jpg、.png、.js、.css结尾,且区分大小写
}
location ~* \.png$ {
#正则规则E
# 访问以.png结尾会被匹配,不缺分大小写
}
location / {
#通用规则F
}

访问效果如下:

访问根目录/, 比如http://a.com/ 将匹配规则A

访问 http://a.com/login 将匹配规则B

访问 http://a.com/static/a.html 将匹配规则C

访问 http://a.com/a.gif, http://a.com/b.png 规则D和E均适合,按顺序优先使用规则D,而 http://a.com/static/c.png 则优先匹配到规则C

访问 http://a.com/a.PNG 则匹配规则E,因为规则E不区分大小写。

访问 http://a.com/category/id/1111 则最终匹配到规则H。

注意:

1 location中的location_match字符有无”/“不受影响。/user/等同/user。

2 对于访问网站域名(https://www.diandian100/),尾部有无"/"不受影响。因为浏览器会自动补全"/"。

3 对于访问网站域名后面的路径(https://www.diandian100.cn/archives/)。尾部的"/"很重要。

URL尾部的”/“表示目录,没有”/“表示文件,而且文件找不到的话,会发生重定向。

​ /archives/:表示服务器会自动去该目录下找对应的默认文件。

​ /archives:表示服务器会先去找archives文件,找不到的话会将archives当成目录,重定向到/archives/,去该目录下找默认文件。

location语法优先级

字符优先级解释
=1表示精确匹配,如果找到,立即停止搜索并立即处理此请求。
^~2以某个字符串开头,即表示只匹配普通字符(跟空格类似,但是它优先级比空格高)。使用前缀匹配,^表示“非”,即不查询正则表达式。如果匹配成功,并且所匹配的字符串是最长的, 则不再匹配其他location。
~3表示执行一个正则匹配,区分大小写匹配
~*4表示执行一个正则匹配,不区分大小写匹配, 注意,如果是运行 Nginx server 的系统本身对大小写不敏感,比如 Windows ,那么 ~* 和 ~ 这两个表现是一样的
/5通用匹配,任何请求都会匹配到

nginx.conf配置文件实例

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
server {
listen 80;
server_name diandian100.cn;

#优先级1,精确匹配,根路径
location =/ {
return 400;
}

#优先级2,以某个字符串开头,以av开头的,优先匹配这里,区分大小写
location ^~ /av {
root /data/av/;
}

#优先级3,区分大小写的正则匹配,匹配/media*****路径
location ~ /media {
alias /data/static/;
}

#优先级4 ,不区分大小写的正则匹配,所有的****.jpg|gif|png 都走这里
location ~* .*\.(jpg|gif|png|js|css)$ {
root /data/av/;
}

#优先7,通用匹配
location / {
return 403;
}
}

expires

控制页面资源在浏览器缓存的时间。在指定事件内再次访问该静态资源,将不再像nginx发送请求,而是直接从浏览器缓存中获取。

使用本指令可以控制HTTP应答中的“Expires”和“Cache-Control”的头标,(起到控制页面缓存的作用)。

语法: expires [time|epoch|max|off]

默认值: expires off

作用域: http, server, location

可以在time值中使用正数或负数。“Expires”头标的值将通过当前系统时间加上您设定的 time值来获得。

1
2
3
4
5
6
7
8
expires 2s; # 2秒
expires 2m; # 2分钟
expires 2h; # 2小时
expires 2d; # 2天
expires -1; # 不缓存,用于过期;指定“Expires”的值为当前服务器时间-1s,即永远过期。
expires epoch; # 指定“Expires”的值为 1 January,1970,00:00:01 GMT
expires max; # 指定“Expires”的值为31 December2037 23:59:59GMT,"Cache-Control"的值为10年。
expires off; # 不修改“Expires”和"Cache-Control"的值

allow

允许某个ip或者一个ip段访问.如果指定unix:,那将允许socket的访问.注意:unix在1.5.1中新加入的功能,如果你的版本比这个低,请不要使用这个方法。

语法: allow address | CIDR | unix: | all;
默认值: —
配置段: http, server, location, limit_except

1
2
3
4
5
location / {
allow 192.168.1.0; # 允许单个ip
allow 10.1.1.0/16; # 允许ip段
allow all; # 允许所有ip
}

deny

禁止某个ip或者一个ip段访问.如果指定unix:,那将禁止socket的访问.注意:unix在1.5.1中新加入的功能,如果你的版本比这个低,请不要使用这个方法。

语法: deny address | CIDR | unix: | all;
默认值: —
配置段: http, server, location, limit_except

1
2
3
4
5
location / {
deny 192.168.1.0; # 禁止单个ip
deny 10.1.1.0/16; # 禁止ip段
deny all; # 禁止所有ip
}

综合示例

1
2
3
4
5
6
7
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}

如上的例子先禁止了192.16.1.1,接下来允许了3个网段,其中包含了一个ipv6,最后未匹配的IP全部禁止访问. 在实际生产环境中,我们也会使用nginx 的geo模块配合使用

stub_status

提供对基本信息状态的访问

1
2
3
location /status {
stub_status on; # 开启nginx的状态页面,默认关闭
}

预览返回结果:

1
2
3
4
Active connections: 1 
server accepts handled requests
1162164 1162164 2031091
Reading: 0 Writing: 1 Waiting: 0

返回各数据项说明:

Active connections: 当前nginx正在处理的活动连接数.

Server accepts handled requests request_time: nginx总共处理了1162164 个连接;成功创建1162164 握手(证明中间没有失败的);总共处理了2031091 个请求。

Reading: nginx读取到客户端的Header信息数。

Writing:nginx返回给客户端的Header信息数.

Waiting: 开启keep-alive的情况下,这个值等于 active – (reading + writing),意思就是nginx已经处理完成,正在等候下一次请求指令的驻留连接。

所以,在访问效率高,请求很快被处理完毕的情况下,Waiting数比较多是正常的.如果reading +writing数较多,则说明并发访问量非常大,正在处理过程中。

目录列表

Nginx默认是不允许列出整个目录的。如需此功能,打开nginx.conf文件或你要启用目录浏览虚拟主机的配置文件,在server或location 段里添加上autoindex on;来启用目录流量,

配置说明
autoindex是否开启目录自动索引
autoindex_exact_size默认为 on,显示出文件的确切大小,单位是bytes。 改为 off 后,显示出文件的大概大小,单位是kB或者MB或者GB
autoindex_localtime默认为off,显示的文件时间为GMT时间。 改为on后,显示的文件时间为文件的服务器时间
1
2
3
4
5
6
location /upload {
alias /mnt/vdb1/test/uploads; # 指定查看文件列表路径(绝对路径)
autoindex on; # 开启目录自动索引
autoindex_exact_size off; # 默认on,显示文件确切大小(bytes)。off表示显示文件的大概大小(kB/MB/...)
autoindex_localtime on; # 默认off,显示的文件时间为GMT时间。on表示显示文件的服务器时间
}

预览效果

rootalias

nginx指定文件路径有root和alias两种方法。root和alias区别在nginx如何解释location后面的url,这会使得两者分别以不同的方式讲请求映射到服务器文件上

root

root的处理结果是:root路径+location位置

语法

语法 root 路径;
默认值 root html;
配置块 http{} server {} location{}

实例

1
2
3
4
location ^~ /av {
# 注意这里可有可无结尾的/
root /data/av;
}

请求url是localhost/av/index.html时,web服务器会返回服务器上的/data/av/av/index.html

alias

alias的处理结果是:使用alias路径替换location路径

alias是一个目录的别名,注意alias必须有 “/“ 结束!alias只能位于location块中

语法

语法: alias 路径
配置块 location{}

实例

1
2
3
location ^~ /av {
alias /data/static/;
}

请求url是localhost/av/index.html时,web服务器会返回服务器上的/data/static/index.html

root和alias区别

root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。

1、root的处理结果是:root路径+location路径;alias的处理结果是:使用alias路径替换location路径
2、alias是一个目录别名的定义;root则是最上层目录的定义。
3、alias后面必须要用“/”结束,否则会找不到文件的;而root则可有可无
4、alias只能位于location块中;root可以不放在location中(可以放在http、server、location中)
5、一般情况下,在location /中配置root;在location /other中配置alias

return和try_files

return

该指令一般用于对请求的客户端直接返回响应状态码。在该作用域内return后面的所有nginx配置都是无效的。
可以使用在server、location以及if配置中。

返回状态码
1
2
3
location /test/ {
return 403;
}

通过返回的页面为: 403 Forbidden 正常的403错误返回码报错可以看出 对于单独返回返回码的场景, 可以进行过滤拦截场景使用)

返回字符串
1
2
3
4
5
location /test/ {
# 响应类型
default_type application/json;
return 200 '{"name":"张学友", "age":18}';
}

如果要想返回字符串,必须要加上状态码,否则会报错

跳转页面
1
2
3
4
location /test/ {
# 302跳转
return https://www.diandian100.cn;
}

等同于

1
2
3
4
location /test/ {
# 302跳转
return 302 https://www.diandian100.cn;
}

我们看下访问日志,可以看出进行了302跳转,并且我这边使用postman进行测试的。

1
127.0.0.1 - - [31/Mar/2021:17:34:41 +0800] "GET /test/ HTTP/1.1" 302 145 "-" "PostmanRuntime/7.26.8" "-"

默认为302临时跳转,你也可以指定301永久跳转

1
2
3
4
location /test/ {
# 301永久跳转
return 301 https://www.diandian100.cn;
}

再次查看访问日志

1
127.0.0.1 - - [31/Mar/2021:17:37:45 +0800] "GET /test/ HTTP/1.1" 301 169 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:87.0) Gecko/20100101 Firefox/87.0" "-"
301与302

301 redirect: 301 代表永久性转移(Permanently Moved)

302 redirect: 302 代表暂时性转移(Temporarily Moved )

ps:这里也顺带记住了两个比较相近的英语单词(permanently、temporarily),嘻哈!

详细来说,301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。

1、什么是重定向啊?

就是地址A跳转到地址B啦。百度百科的解释:重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。

2、可是,为什么要进行重定向啊?什么时候需要重定向呢?

想跳就跳,就跳的漂亮。还是借鉴百度百科:

1)网站调整(如改变网页目录结构);

2)网页被移到一个新地址;

3)网页扩展名改变(如应用需要把.php改成.Html或.shtml)。

这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。

3、那么,什么时候进行301或者302跳转呢?

当一个网站或者网页24—48小时内临时移动到一个新的位置,这时候就要进行302跳转,打个比方说,我有一套房子,但是最近走亲戚去亲戚家住了,过两天我还回来的。而使用301跳转的场景就是之前的网站因为某种原因需要移除掉,然后要到新的地址访问,是永久性的,就比如你的那套房子其实是租的,现在租期到了,你又在另一个地方找到了房子,之前租的房子不住了。

清晰明确而言:

使用301跳转的场景:

1)域名到期不想续费(或者发现了更适合网站的域名),想换个域名。

2)在搜索引擎的搜索结果中出现了不带www的域名,而带www的域名却没有收录,这个时候可以用301重定向来告诉搜索引擎我们目标的域名是哪一个。

3)空间服务器不稳定,换空间的时候。

使用302跳转的场景:

–尽量使用301跳转!

4、为什么尽量要使用301跳转?——网址劫持!

这里摘录百度百科上的解释:

从网址A 做一个302 重定向到网址B 时,主机 服务器的隐含意思是网址A 随时有可能改主意,重新显示本身的内容或转向其他的地方。大部分的搜索引擎在大部分情况下,当收到302 重定向时,一般只要去抓取目标网址就可以了,也就是说网址B。如果搜索引擎在遇到302 转向时,百分之百的都抓取目标网址B 的话,就不用担心网址URL 劫持了。问题就在于,有的时候搜索引擎,尤其是Google,并不能总是抓取目标网址。比如说,有的时候A 网址很短,但是它做了一个302 重定向到B 网址,而B 网址是一个很长的乱七八糟的URL 网址,甚至还有可能包含一些问号之类的参数。很自然的,A 网址更加用户友好,而B 网址既难看,又不用户友好。这时Google 很有可能会仍然显示网址A。由于搜索引擎排名算法只是程序而不是人,在遇到302 重定向的时候,并不能像人一样的去准确判定哪一个网址更适当,这就造成了网址URL 劫持的可能性。也就是说,一个不道德的人在他自己的网址A 做一个302 重定向到你的网址B,出于某种原因, Google 搜索结果所显示的仍然是网址A,但是所用的网页内容却是你的网址B 上的内容,这种情况就叫做网址URL 劫持。你辛辛苦苦所写的内容就这样被别人偷走了。302 重定向所造成的网址URL 劫持现象,已经存在一段时间了。不过到目前为止,似乎也没有什么更好的解决方法。在正在进行的谷歌大爸爸数据中心转换中,302 重定向问题也是要被解决的目标之一。从一些搜索结果来看,网址劫持现象有所改善,但是并没有完全解决。

我的理解是,从网站A(网站比较烂)上做了一个302跳转到网站B(搜索排名很靠前),这时候有时搜索引擎会使用网站B的内容,但却收录了网站A的地址,这样在不知不觉间,网站B在为网站A作贡献,网站A的排名就靠前了。

301跳转对查找引擎是一种对照驯良的跳转编制,也是查找引擎能够遭遇的跳转编制,它告诉查找引擎,这个地址弃用了,永远转向一个新地址,可以转移新域名的权重。而302重定向很容易被搜索引擎误认为是利用多个域名指向同一网站,那么你的网站就会被封掉,罪名是“利用重复的内容来干扰Google搜索结果的网站排名”。

try_files

try_files是nginx中http_core核心模块所带的指令,主要是能替代一些rewrite的指令,提高解析效率。

语法

格式1:try_files file file1 file2uri;

格式2:try_files file file1 file2 … =code;

可应用的上下文:server,location段

执行流程

1.按指定的file顺序查找存在的文件,并使用第一个找到的文件进行请求处理

2.查找路径是按照给定的root或alias为根路径来查找的

3.如果给出的file都没有匹配到,则重新请求最后一个参数给定的uri,就是新的location匹配

4.如果是格式2,如果最后一个参数是 = 404 ,若给出的file都没有匹配到,则最后返回404的响应码

简单示例
1
2
3
4
location /images/ {
root /opt/html/;
try_files $uri $uri/ /images/default.png;
}

如果此时客户端请求localhost/images/flag.png的话,nginx依次查找顺序为:

1.查找文件:/opt/html/images/flag.png

2.查找文件夹(目录)下的index文件(如:/opt/html/images/flag.png/index.html):/opt/html/images/flag.png/

3.以上都找不到请求默认文件:/opt/html/images/default.png

转发请求

try_files中可以用过@location名称进行请求转发,如:

1
2
3
4
5
6
7
8
location /images/ {
root /opt/html/;
try_files $uri $uri/ @none
}

location @none {
return 404
}

注意:try_files不能用于根路径的请求处理,只能用于子路径。即:不能用于location / {}中,

Nginx代理

正向代理

正向代理,也就是传说中的代理,他的工作原理就像一个跳板(VPN),简单的说:

我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。

反向代理

对于客户端而言,代理服务器就像是原始服务器。

正反向代理区别

用途上

正向代理-为局域网客户端向外访问Internet服务。可以使用缓冲特性减少网络使用率。

反向代理-为局域网服务器向外提供Internet服务。可以使用负载平衡提高客户访问量。还可以基于高级URL策略和管理技术对服务进行高质量管控。

安全性上

正向代理-必须采取安全措施确保内网客户端通过它访问外部网站。隐藏客户端的身份

反向代理-对外提供服务是透明的,客户端并不知道自己访问的是一个代理。隐藏服务端的身份

proxy_pass

nginx中有两个模块都有proxy_pass指令。两个proxy_pass都是用来做后端代理的指令。

ngx_http_proxy_moduleproxy_pass

语法:proxy_pass URL;
场景:location, if in location, limit_except
说明:设置后端代理服务器的协议(protocol)和地址(address),以及location中可以匹配的一个可选的URI。协议可以是”http”或”https”。地址可以是一个域名或ip地址和端口,或者一个 unix-domain socket 路径( 详见参考文档)

官方的代理属性很多,我们主要介绍proxy_pass和proxy_set_header属性。proxy_pass 指令设置被代理服务器的地址和被映射的URI,地址可以使用主机名或IP加端口号的形式

1
2
3
4
location / {
proxy_pass http://localhost:8000; # 设定请求跳转后的地址,可以使用hostname或IP:Port形式
proxy_set_header X-Real-IP $remote_addr; # 后端请求携带原始请求的真实IP地址
}

proxy_pass后面的路径最后的/作用很重要!!!

示例代码:

1
2
3
4
location /html/ {
proxy_pass https://www.diandian100.cn;
proxy_pass https://www.diandian100.cn/;
}

假设我们访问的url是 http://domain.com/html/test.js,如何理解上述两种proxy_pass的区别呢?

对于 1 来说 https://www.diandian100.cn后面没有”/“,表示”/html/“ 请求(包括自己)后续的路径及其参数等关键字都由https://www.diandian100.cn来处理,代理后的样式如下:

https://www.diandian100.cn/html/test.js

对于 2 来所 https://www.diandian100.cn后面有”/“,表示”/html/“ 请求后续的路径及其参数等关键字都由https://www.diandian100.cn来处理,代理后的样式如下:

https://www.diandian100.cn/test.js

nginx反向代理实例

代理配置文件

9000端口的配置文件

1
2
3
location /proxy {
proxy_pass http://localhost:9001/hello/;
}
后端服务配置环境

9001端口配置文件

1
2
3
location /hello/ {
return 200 '我是代理后端';
}
重载配置
1
2
nginx -t
nginx -s reload
预览效果

ngx_stream_proxy_moduleproxy_pass

语法: proxy_pass address;

场景:server

说明:设置后端代理服务器的地址。这个地址(address)可以是一个域名或ip地址和端口,或者一个 unix-domain socket路径(详见官方文档))。

ngx_stream_proxy_module模块的proxy_pass用法

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 127.0.0.1:12345;
proxy_pass 127.0.0.1:8080;
}

server {
listen 12345;
proxy_connect_timeout 1s; # nginx与proxy_pass设置的地址的连接超时时间
proxy_timeout 1m;
proxy_pass example.com:12345;
}

server {
listen 53 udp;
proxy_responses 1;
proxy_timeout 20s;
proxy_pass dns.example.com:53;
}

server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}

两个proxy_pass的关系和区别

在两个模块中,两个proxy_pass都是用来做后端代理的指令。
ngx_stream_proxy_module模块的proxy_pass指令只能在server段使用使用, 只需要提供域名或ip地址和端口。可以理解为端口转发,可以是tcp端口,也可以是udp端口。
ngx_http_proxy_module模块的proxy_pass指令需要在location段,location中的if段,limit_except段中使用,处理需要提供域名或ip地址和端口外,还需要提供协议,如”http”或”https”,还有一个可选的uri可以配置。

负载均衡

负载均衡是什么?

我们之前使用proxy_pass的方式实现了nginx代理请求到后端的效果,随着我们的网站访问量越来越多,一个后端就不现实了,那么接下来我们应该如果在访问量日渐增大的情况下,满足线上业务的稳定呢?

解决方法就是:负载均衡

负载均衡简单说来人多力量大,打群架。

在nginx中的负载均衡主要有两种:四层负载(IP:Port)、七层负载

nginx upstream模块

官方介绍

官方资料:http://www.nginx.cn/doc/standard/httpupstream.html

官方的代理属性很多,我们主要介绍upstream和ip_hash属性

官方代码示例

1
2
3
4
5
6
7
8
9
10
11
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
server unix:/tmp/backend3;
}

server {
location / {
proxy_pass http://backend;
}
}

属性详解

upstream 主要是定义一个后端服务地址的集合列表,每个后端服务使用一个server命令表示

upstream {} 和 Server {} 两部分内容属于平级关系。

后端服务状态

在upstream模块中,可以使用server命令指定后端服务器的地址,同时还可以设置后端服务器在负载均衡调度中的状态,常用的状态有以下几种:

down: 表示当前server主机暂时不参与负载均衡。

backup:后备主机,当所有非backup机器出现故障或者繁忙的时候,才会请求backup机器。

max_fails:允许请求的最大失败数,默认为1,配合fail_timeout一起使用

fail_timeout:经历max_fails次失败后,暂停服务的时间,默认为10s

负载均衡实例

负载均衡配置文件
1
2
3
4
5
6
7
8
9
10
11
12
upstream backends {
server localhost:9001;
server localhost:9002;
}

server{
listen 9000;

location / {
proxy_pass http://backends;
}
}
后端配置文件
9001后端配置文件
1
2
3
4
5
6
server{
listen 9001;
location / {
return 200 '我是9001服务';
}
}
9002后端配置文件
1
2
3
4
5
6
server{
listen 9002;
location / {
return 200 '我是9002服务';
}
}
重启配置
1
2
nginx -t
nginx -s reload
预览

反复刷新可以看到两个端口提供的内容轮番响应。

负载均衡调度算法

Nginx提供的负载均衡策略有两种:

内置策略:nginx自带的算法

雨露均沾型:轮训、加权轮训、哈希

定向服务型:ip_hash、least_conn、cookie、route、lean、

商业类型:ntlm、least_time、queue、stick

扩展策略:各种结合业务场景自定义的算法或者第三方算法

自定义算法

第三方算法:fairurl_hash

常用算法简介:

轮询(默认):请求按顺序逐一分配到不同的后端服务器。

weight:指定轮询权重,值越大,分配到的几率就越高,适用于后端服务器性能不均衡情况。

ip_hash:按访问IP的哈希结果分配请求,分配后访客访问固定后端服务器,有效的解决动态网页会话共享问题。

fair:基于后端服务器的响应时间来分配请求,响应时间短的优先分配。

url_hash:按访问URL的哈希结果分配请求,使同URL定向到同一台后端服务器,可提高后端缓存服务器的效率。

加权轮询实例

负载均衡配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
upstream backends {
server localhost:9001 backup; # 后备主机,当所有非backup机器出现故障或者繁忙的时候,才会请求backup机器。
server localhost:9002 weight=1;
server localhost:9003 weight=2;
}

server{
listen 9000;

location / {
proxy_pass http://backends;
}
}
后端配置文件
9001后端配置文件
1
2
3
4
5
6
server{
listen 9001;
location / {
return 200 '我是9001服务';
}
}
9002后端配置文件
1
2
3
4
5
6
server{
listen 9002;
location / {
return 200 '我是9002服务';
}
}
9003后端配置文件
1
2
3
4
5
6
server{
listen 9003;
location / {
return 200 '我是9003服务';
}
}
重启配置
1
2
nginx -t
nginx -s reload
预览

9003权重最高访问频率最多,9001因为未设置了backup,只有其他服务器都故障或者繁忙的时候才会请求该主机

1
2
3
4
5
6
7
我是9002服务
我是9003服务
我是9003服务
……
我是9002服务
我是9003服务
我是9003服务

ip_hash实例

负载均衡配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream backends {
ip_hash;
server localhost:9001;
server localhost:9002;
server localhost:9003;
}

server{
listen 9000;

location / {
proxy_pass http://backends;
}
}
后端配置文件
9001后端配置文件
1
2
3
4
5
6
server{
listen 9001;
location / {
return 200 '我是9001服务';
}
}
9002后端配置文件
1
2
3
4
5
6
server{
listen 9002;
location / {
return 200 '我是9002服务';
}
}
9003后端配置文件
1
2
3
4
5
6
server{
listen 9003;
location / {
return 200 '我是9003服务';
}
}
重启配置
1
2
nginx -t
nginx -s reload
预览

第一次请求被转到了9001,后续每次都被转到9001

1
2
3
4
5
6
7
我是9001服务
我是9001服务
我是9001服务
……
我是9001服务
我是9001服务
我是9001服务