Nginx应用

12/17/2022

# 反向代理

# 代理介绍

代理是常见设计模式,它是指我们不直接访问目标对象,而是通过代理对象来间接访问目标对象。网络代理是指将网络请求发送给代理服务器,代理服务器再与目标服务器进行通讯。直接来感受如下图所示。

在这里插入图片描述

通常代理分为正向代理和反向代理。

  • 正向代理,指的是通过代理服务器 代理浏览器/客户端去重定向请求访问到目标服务器 的一种代理服务。

    在这里插入图片描述

  • 反向代理,指的是浏览器/客户端并不知道自己要访问具体哪台目标服务器,只知道去访问代理服务器代理服务器再通过反向代理 +负载均衡实现请求分发到应用服务器的一种代理服务。

    在这里插入图片描述

简单来说是正向代理是客户端代理,反向代理是服务端代理。

# 反向代理配置

nginx反向代理配置核心就是一个指令proxy_pass

http{ 		
 		server {
        listen       80;
        server_name  localhost;

        location / { 
        		proxy_pass http://xxx;
                #root   html/test; 
                #index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
		}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

当我们启动proxy_pass时,rootindex字段都会失效。proxy_pass的地址必须写完整的http://xxx(目标服务器),不支持https

当我们访问nginx服务器时,浏览器地址栏是nginx的服务器的地址,但是网页的内容是代理服务器的内容。

# 拓展

nginx代理,一般称为隧道代理,即所有请求和响应数据都要经过nginx。通常情况下请求数据一般较小,大多数为get和post等方式http请求,而响应数据类型复杂,数据量不稳定。由于nginx的带宽有限的,当响应数据量较大时,可能会产生性能瓶颈。因此我们也可以将响应数据直接放回到客户端,不经过代理服务器,这种方式称为DR代理,实现中间件有LSV。

# 负载均衡

由于代理的每台目标服务器性能不一致,通常会实现负载均衡算法,将网络请求按照一定策略进行分发,保证应用具有高可用和高并发。

在这里插入图片描述

nginx负载均衡配置核心就是一个指令upstream。这个配置就是写一组被代理的服务器地址,然后配置负载均衡算法。

upstream mysvr { 
    server 192.168.10.121:3333;
    server 192.168.10.122:3333;
}
server {
    ....
    location  / {         
        proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表         
    }
}
1
2
3
4
5
6
7
8
9
10

负载均衡算法常用的有轮询加权轮询ip_hash算法,默认是轮询算法。

# 基于轮询负载均衡

轮询原理是每一个请求按时间顺序逐一被分发到不同的应用服务器,如果接收请求的应用服务器挂了,并且请求超过最大失败次数max_fails1次),则在失效时间fail_timeout10秒)内不会再转发请求到该节点。

upstream weightReverseProxyServer{
    server 192.168.0.1:8080 max_fails=1 fail_timeout=10s;
    server 192.168.0.2:8080 max_fails=1 fail_timeout=10s;
}
1
2
3
4

# 基于权重的负载均衡

加权轮询就是在轮询算法基于上新增weight参数。每一个请求按照权重被分发到不同的应用服务器。同样,如果接收请求的应用服务器挂了,并且请求超过最大失败次数max_fails默认1次或可设置N次),则在失效时间fail_timeout默认10秒,可设置N秒)内,不会再转发请求到该节。

upstream weightReverseProxyServer{
    server 192.168.0.1:8080 weight=10 max_fails=2 fail_timeout=5s;
    server 192.168.0.2:8080 weight=5 max_fails=2 fail_timeout=5s;
}
1
2
3
4

一般使用的是基于权重的算法,因为现在很多情况下都是集群部署,而且集群下的各个服务器资源大多都是不均匀的,资源高的则分配权重高一些,资源低的则分配权重低一些,这种情况使用基于权重的负载均衡算法,可以更高效的利用资源和提高并发处理能力。

# 基于ip_hash的负载均衡

ip_hash原理是每一个请求按用户访问IP的哈希结果分配,如果请求来自同一个用户IP则固定这台IP访问一台服务器,这种策略算法能有效解决动态网络中存在的session共享问题。

upstream ipHashReverseProxyServer{
    ip_hash;
    server 192.168.0.1:8080;
    server 192.168.0.2:8080;
}
1
2
3
4
5

# 状态参数

在每个server后面还可以配置状态参数,用于控制server的作用,主要介绍两个参数是downbackup

  • down,表示当前的server暂时不参与负载均衡。

    upstream mysvr { 
        server 127.0.0.1:7878; 
        server 192.168.10.121:3333 down;  #不会请求到该server     
    }
    
    1
    2
    3
    4
  • backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。

    upstream mysvr { 
        server 127.0.0.1:7878; 
        server 192.168.10.121:3333 backup;  #热备     
    }
    
    1
    2
    3
    4
  • max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。

  • fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。

# 动静分离

动静分离就是指当用户请求资源时,动态请求分配到tomcat业务服务器,静态资源请求分配到nginx服务器。这样一方面减少tomcat服务器的压力,同时也有效nginx服务器高可用,能在一定程度上提高系统性能。

# 手动配置静态资源

手动配置静态资源就是在location指令配置资源静态访问URL。

server {
        listen       80;
        server_name  localhost;
				
    	location / { # /的优先级比较低,如果下面的location没匹配到,就会走http://xxx这个地址的机器
            proxy_pass http://xxx;
    	}
        
        location /css {  # root指的是html,location/css指的是root下的css,所以地址就是html/css
        		root html;
            	index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 如果请求的资源地址是location//的优先级比较低,如果下面的location没有匹配到,就会走http://xxx这个地址的机器
  • 如果请求的资源地址是location/css/*,就会被匹配到nginx的html目录下的css文件夹中(我们把css静态资源放在这个位置)

# 正则表达式配置静态资源

手动配置缺点就是重复写很多location,我们也可用通过正则表达式来统一写静态资源的匹配路径。

location ~*/(js|css|img){
	root html;
    index  index.html index.htm;
}
1
2
3
4

# URL重写

rewrite指令能够实现URL重写,URL重写是指将一个URL请求重写写成另一个URL过程。举个例子来说,在开发中可能经常遇到这样的需求,比如通过浏览器请求的http://localhost:8080/getUser?id=1,但是需要通过SEO优化等等原因,需要把请求的地址重写为http://localhost:8080/getUser/1这样的URL,从而符合需求或者更好的被网站阅读。

当遇到这种请求的时候,就需要使用到URL重写或者使用一些网关路由,如SpringCloud的Gateway,Zuul,又或者是Nginx来实现这个功能。

rewrite指令的语法为:

rewrite    <regex>   <replacement>  [flag];
关键字	      正则		  替代内容      flagt标记
1
2
  • 正则:正则表达式语句进行规则匹配
  • 替代内容:将正则匹配的内容替换成replacement
  • flag标记有四种选项
    • last:本条规则匹配完成后,继续向下匹配新的1ocation URI规则
    • break:本条规则匹配完成即终止,不再匹配后面的任何规则
    • redirect:返回302临重定向,游览器地址会显示跳转后的URL地址
    • permanent:返回301永久重定向,测览器地址栏会显示跳转后的URL地址

当我们配置一个URL重写如下时,浏览器地址栏访问 xxx/123.html实际上是访问xxx/index.jsp?pageNum=123

server {
        listen       80;
        server_name  localhost;
				
				location / { 
						rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1  break;
        				proxy_pass http://xxx;
        }
      
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 防盗链

防盗链是指当我们请求到一个页面后,这个页面一般会再去请求其中的静态资源,这时候请求头中,会有一个refer字段,表示当前这个请求的来源,我们可以限制指定来源的请求才返回,否则就不返回,这样可以节省资源。

image-20220503162830153

nginx设置防盗链是指令是valid_referers,语法格式为:

valid_referers none|server_name
1
  • none:检测地址没有refer,则有效。
  • server_name:检测主机地址,refer显示是从这个地址来的,则有效(server_name必须是完整的http://xxxx

例子:这里设置nginx服务器中的img目录下的图片必须refer为http:192.168.174/133才能访问

server {
    listen       80;
    server_name  localhost;

    location / { 
        proxy_pass http://xxx;
    }

    location /img{
        valid_referers http:192.168.174/133;
        if ($invalid_referer){#无效的
            return 403;#返回状态码403
        }
        root html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

如果引用这张图片的页面且refer并没有被设置,图片无法加载出来。

如果直接访问图片地址,因为没有refer字段指向来源,会直接显示Nginx的页面。

若我们需要设置防盗链的图片提示,可将提示图片放在html/img/x.png,访问设置防盗链图片时,就返回这x.png张图。

location /img{
    valid_referers http:192.168.174/133;
    if ($invalid_referer){#无效的
        rewrite ^/  /img/x.png break;
    }
    root html;
    index  index.html index.htm;
}
1
2
3
4
5
6
7
8

# 参考

  • https://bbs.huaweicloud.com/blogs/301714
  • https://www.runoob.com/w3cnote/nginx-proxy-balancing.html
Last Updated: 1/6/2023, 11:41:59 AM