Nginx常⻅问题

  1. Server优先级
  2. location优先级
  3. try_files的使用
  4. alias与root区别
  5. 获取用户真实IP
  6. 常见HTTP状态码
  7. 网站相关术语
  8. 网站访问原理
  9. Nginx优化⽅案
  10. Nginx架构总结

参考地址:

  1. Nginx常见问题,多sevrer优先级
  2. nginx中server的匹配顺序
  3. Nginx location配置类别和匹配优先级
  4. nginx 获取真实ip

Server优先级

在开始处理一个http请求时,nginx会取出header头中的host,与nginx.conf中每个server的server_name进行匹配,以此决定到底由哪一个server块来处理这个请求。

server_name与host匹配优先级如下:

  1. 完全匹配
  2. 通配符在前的,如*.test.com
  3. 通配符在后的,如www.test.*
  4. 正则匹配,如~^\.www\.test\.com$

如果都不匹配

  1. 如果有default或者default_server , 优先选择listen配置项后有default或default_server的
  2. 如果没有default或者default_server ,找到匹配listen端口的第一个server块

执行优先级可以使用nginx -t检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
listen 80;
server_name testserver1 192.168.69.113;
location / {
root /soft/code1;
index index.html;
}
}
server {
listen 80;
server_name testserver2 192.168.69.113;
location / {
root /soft/code2;
index index.html;
}
}
server {
listen 80;
server_name testserver3 192.168.69.113;
location / {
root /soft/code3;
index index.html;
}
}
1
2
3
4
5
nginx -t
# nginx: [warn] conflicting server name "192.168.69.113" on 0.0.0.0:80, ignored
# nginx: [warn] conflicting server name "192.168.69.113" on 0.0.0.0:80, ignored
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

正则与default的优先级

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 ~^\w+\.1$;

location / {
default_type text/html;
echo "正则匹配";
}
}

server {
listen 80;
server_name xi.xi;

location / {
default_type text/html;
echo "不匹配";
}
}

server {
listen 80 default;
server_name ha.ha;

location / {
default_type text/html;
echo "不匹配dafault"
}
}
1
2
3
4
curl http://server.1/test
# 正则匹配
curl http://sevrer.2/test
# 不匹配default

正则匹配虽然优先级较低,但是仍然高于default;在都匹配不到的情况下,default开始起作用。

在全部匹配失败时,使用default

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80 default;
sever_name *.1;
location / {
default_type text/html;
echo "通配符在前";
}
}
server {
listen 80;
server_name server.1;
location / {
default_type text/html;
echo "完全匹配";
}
}
1
2
curl http://server.1/test
# 完全匹配

default只能作用于匹配不到的情况下,而且nginx.conf不可以配多个default,否则nginx重启时候会提示错误

全部匹配失败,且没有default,靠前为赢

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
sever_name xi.xi;
location / {
default_type text/html;
echo "不匹配.位置靠前"
}
}
server {
listen 80;
sevrer_name ha.ha;
echo "不匹配,位置靠后";
}
1
2
curl http://sever.1/test
# 不匹配.位置靠前

在server_name都匹配失败的前提下,并且listen没有default属性,那么端口号和server的顺序将发挥作用,它会去找端口匹配的位置最靠前的server。

location优先级

⼀个 server 出现多个 location

匹配 优先级由高到低 示例
= 进⾏普通字符精确匹配, 完全匹配 location = /static/img/file.jpg
^~ 表示普通字符匹配, 使⽤前缀匹配 location ^~/static/img/
~ 执行一个正则匹配,区分大小写 location ~ /static/img/.*.jpg$
~* 执行一个正则匹配,不区分大小写 location ~* /static/img/.*.jpg$
  • 字符匹配成功(=,^~) , 则不再查找其他匹配项。
  • 正则匹配成功(~ , ~*) , 则使用正则表达式最长的那个。

以下是按优先级排列说明:

  1. 先匹配精确模式,命中精确模式,直接返回。否则,继续匹配前缀模式。
  2. 前缀模式中使用最大前缀原则,选出匹配普通匹配(空格)或非正则匹配(^~)的最长location。
  3. 若最长前缀location是非正则匹配(^~),则返回该最长前缀location。否则,还需要继续匹配正则模式。
  4. 正则模式的原则是按照正则location定义顺序匹配,第一个匹配的location为正则模式结果。
  5. 若正则模式匹配成功,返回正则模式结果。否则,返回前缀模式中的最长前缀location。

注意 :如果命中多个前缀匹配,则记住最长的前缀匹配

1
2
3
4
5
location /static/ {
}

location /static/img/ {
}

记住最长的前缀匹配,即上例中的 /static/img/

简记

  1. = , 精确匹配 , 优先级为1
  2. ^~ , 前缀匹配 , 优先级为2
  3. ~ , 正则匹配(不区分大小写) , 优先级为3
  4. ~*, 正则匹配(区分大小写) , 优先级为3

try_files的使用

nginx 的 try_files 按顺序检查⽂件是否存在

1
2
3
4
5
6
location / {
try_files $uri $uri/ /index.php;
}
#1.检查用户请求的uri内容是否存在本地,存在则解析
#2.将请求加/, 类似于重定向处理(看看这个目录下有没有这个文件)
#3.最后交给index.php处理

alias与root区别

1
2
3
4
5
6
7
server {
listen 80;
index index.html;
location /request_path/code/ {
root /local_path/code/;
}
}

curl http://192.168.69.113/request_path/code/index.html的实际请求本地⽂件路径为 : /local_path/code/request_path/code/index.html

1
2
3
4
5
6
7
server	{
listen 80;
index index.html;
location /request_path/code/ {
alias /local_path/code/;
}
}

curl http://192.168.69.113/request_path/code/index.html的实际访问本地路径为 : /local_path/code/index.html

获取用户真实IP

Nginx 传递用户的真实IP地址

1575874685617

  • 经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址。
  • 这句话的意思是说,当你使用了nginx反向服务器后,在web端使用request.getRemoteAddr()(本质上就是获取$remote_addr),取得的是nginx的地址,即$remote_addr变量中封装的是nginx的地址,当然是没法获得用户的真实ip的
  • $remote_addr 只能获取到最近⼀台服务器访问IP
  • x_forwarded_for 头部信息容易被篡改

最佳实践:

  1. 在代理1里执行set x_real_ip=$remote_addr
  2. 在后端服务你直接获取$x_real_ip
1
2
3
proxy_set_header  Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;

然后,在web端可以这样获取:request.getAttribute("X-Real-ip")

示例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 88;
server_name localhost;

location / {
root html;
index index.html index.htm;
proxy_pass http://backend;
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;
# proxy_set_header X-Forwarded-For $http_x_forwarded_for;
}

常⻅HTTP状态码

  1. 200 正常请求
  2. 301 永久跳转
  3. 302 临时跳转
  4. 400 请求参数错误
  5. 401 账户密码错误(authorization required)
  6. 403 权限被拒绝(forbidden)
  7. 404 ⽂件没找到(Not Found)
  8. 413 用户上传⽂件⼤⼩限制(Request Entity Too Large)
  9. 502 后端服务⽆响应(bad gateway)
  10. 504 后端服务执行超时(Gateway Time-out)

网站相关术语

PV(page view,页面浏览量)

  • 用户每打开1个网站页面,记录1个PV。用户多次打开同一页面,PV值累计多次。即访问量
  • 主要用来衡量网站用户访问的网页数量。是评价网站流量最常用的指标之一。

UV( unique visitor,网站独立访客)

  • 通过互联网访问、流量网站的自然人。1天内相同访客多次访问网站,只计算为1个独立访客。
  • 该概念的引入,是从用户个体的角度对访问数据进行划分。
  • cookie 为依据。

IP(独立IP)

  • 1天之内(00:00~24:00),访问网站的不重复的IP数
  • 拥有特定唯一IP的计算机访问网站的次数,因为这种统计方式比较容易实现,具有较高的真实性。

如果⼀栋⼤厦里所有⼯作⼈员通过1个IP公网接⼝上网, 总共100个设备, 当所有⼈同时请求⼀个网站, 并且刷新了5次, 那么请求pv、ip、uv分别是多少

  • pv : 500
  • uv : 100
  • ip : 1

用户访问网站的流程

粗略流程

  1. DNS解析
  2. CDN
  3. HTTP三次握手
  4. 负载均衡
  5. web应用
  6. 程序框架 Opcache
  7. Redis/Memcached/RabbitMq
  8. MySQL

每一层都会有响应的缓存

详细流程

  1. DNS流程
    1. 查询本地Hosts
    2. 请求本地localDNS
    3. 返回对应的IP
  2. HTTP连接
    1. 建立TCP三次握手,发送请求内容, 请求头、请求的行、请求的主体
    2. 将请求传递给负载均衡, 负载均衡做对应的调度
      • 如果请求的是静态页面, 那么调度至对应的静态集群组即可
      • 如果请求的是动态页面, 将请求调度至动态集群组
        • 如果仅仅是请求页面, 可能会经过Opcache缓存返回
        • 如果请求页面需要查询数据库, 或者是往数据库插入内容 , 检查对应的操作是查询还是写入,
          • 如果是写入数据库 , 写入 , 并且使用Redis缓存对应的查询结果
          • 如果是查询数据库 , 检查查询的内容是否有被缓存,
            • 如果有缓存 , 则返回 , 并且使用Redis缓存对应的查询结果
            • 如果没有缓存 , 则执行查询操作, 并且使用Redis缓存对应的查询结果
    3. 返回对应客户端请求的内容至于WEB节点
    4. WEB节点收到请求后返回内容至负载均衡
    5. 负载均衡返回客户端内容, TCP四次挥手断开
  3. HTTP断开连接

Nginx优化⽅案

  1. gzip压缩
  2. expires静态⽂件缓存
  3. 调整⽹络IO模型,调整Nginx worker进程的最⼤连接数
  4. 隐藏Nginx名称和版本号
  5. 配置防盗链,防⽌资源被盗用
  6. 禁⽌通过IP地址访问,禁⽌恶意域名解析,只允许域名访问
  7. 防DDOS、cc攻击, 限制单IP并发请求连接
  8. 配置错误⻚⾯,根据错误代码指定⽹⻚反馈用户
  9. 限制上传资源⽬录被程序访问,防⽌⽊⻢⼊侵系统
  10. Nginx加密传输优化

Nginx架构总结

基于Nginx中间件的架构

  1. 了解需求(定义Nginx在服务体系中的⻆⾊)
    • 静态资源服务的功能设计
      • 类型分类(视频、图⽚、html)
      • 浏览器缓存
      • 防盗链
      • 流量限制
      • 防资源盗用
      • 压缩(压缩模式, 压缩⽐例, 压缩类型)
    • 代理服务
      • 协议类型
      • 正向代理
      • 反向代理
      • 负载均衡
      • 代理缓存
      • 头信息处理
      • Proxy_Pass
      • LNMP
      • 动静分离
  2. 设计评估
    • 硬件 CPU、内存、磁盘
    • 系统(用户权限、日志⽬录存放)
    • 代理服务/负载均衡 (CPU、内存)
    • 静态资源服务(硬盘容量、硬盘转速)
    • 动态资源服务(硬盘转速、读写效率)
    • 缓存资源服务(SSD固态)
  3. 配置注意事项
    • 合理配置
      • 定义http块
      • 定义优化参数
      • 定义server , location , log
    • 了解原理
      • http协议原理
      • http状态原理
      • 操作系统原理
    • 关注日志
      • 日志是否有打开
      • 是否有对应请求
      • 请求状态码信息符合
      • 错误日志信息吐出来
      • 错误日志内容和含义