目录
- 反向代理
- 去掉前缀
- 场景1:去掉一层前缀
- 场景2:去掉两层前缀
- 返回固定json
- 增加后缀映射
- 情况一
- 情况二
- 情况三
- 情况四
- 正向代理
- 负载均衡
- 正则匹配
- ~ /item/(\d+)
反向代理
通过Nginx我们可以实现反向代理,这也是我在项目中使用到的一个功能,那么什么是反向代理呢?我们用户对代理是无感知的,因为我们不需要进行任何配置就可以进行访问。我们只需要将请求发送至反向代理服务器,由反向代理服务器帮我们决定需要访问哪个资源并且将资源返回给我们。此时反向代理服务器和目标服务器对外就是服务器,但是只对外暴露了代理服务器的地址,目标服务器的地址是隐藏的。
去掉前缀
场景1:去掉一层前缀
正常情况下:在nginx配置文件中中设置了 location /api/
时 浏览器访问 /api/test
反向代理到后端服务后,后端服务接收到的url地址实际还是/api/test
需要实现的功能需求:访问url路径/api/test
经过nginx反向代理后,到达后端服务的实际url地址为/test
。
location ^~/api/ {
proxy_pass http://localhost:12345/;
}
需要注意和修改的是:在proxy_pass的最后加一个/即可。
修改完成后执行 nginx -s reload 刷新nginx配置文件,然后打开浏览器测试即可
场景2:去掉两层前缀
比如把/gatway/api/test
转发到后端是/test
location ^~/gateway/api/ {
add_header Cache-Control 'no-store';
client_max_body_size 100m;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
proxy_connect_timeout 1;
proxy_send_timeout 20;
proxy_read_timeout 30;
proxy_pass http://192.168.0.88:8208/;
}
返回固定json
location = /time2 {
default_type application/json;
add_header 'Access-Control-Allow-Origin' '*';
autoindex_localtime on;
add_header 'Access-Control-Allow-Credentials' 'true';
return 200 '{"code":0,"year":"2022","month":"05","day":"31","hour":"11","minute":"20","second":"21"}';
}
增加后缀映射
参考:nginx代理路径配置总结
情况一
这个结果说明代理的时候,按照请求路径中的/api匹配到了对应的代理,代理到服务端的时候,把请求的ip和port替换为代理服务的ip和port,而对应的uri则完全没有变化,是整体的复制过去。
请求nginx:http://192.168.0.105:8087/api/system/common/doLogin
Nginx代理替换之后:http://192.168.0.105:8089/api/system/common/doLogin
代理过程:将图中红色部分替换为绿色部分,其他都不变,然后发送到服务端:
情况二
location后的路径为“/api”,代理服务的上下文为“/”(http://192.168.0.105:8089/),看下图:
服务端接收的uri为:
这个结果说明按照请求路径中的/api匹配到了对应的代理之后,把请求中的“/api”替换为代理服务上下文路径“/”,“/api”之后的路径不变,替换如下:
请求nginx:http://192.168.0.105:8087/api/system/common/doLogin
Nginx代理替换之后:http://192.168.0.105:8089/ /system/common/doLogin
代理过程:将红色的部分替换为绿色的部分,其他都不变,然后发送服务端:
情况三
location后的路径为“/api/”,代理服务的上下文为空(http://192.168.0.105:8089),看下图:
服务端接收的uri为:
这个结果和情况一是一样的,按照请求路径中的/api/匹配到了对应的代理,代理到服务端的时候,把请求的ip和port替换为代理服务的ip和port,而对应的uri则完全没有变化,是整体的复制过去。
请求nginx:http://192.168.0.105:8087/api/system/common/doLogin
Nginx代理替换之后:http://192.168.0.105:8089/api/system/common/doLogin
情况四
location后的路径为“/api/”,代理服务的上下文为“/”(http://192.168.0.105:8089/),看下图:
服务端接收的uri为:
这个结果说明和情况二是一样的,按照请求路径中的/api/匹配到了对应的代理之后,把请求中的“/api/”替换为代理服务上下文路径“/”,“/api/”之后的路径不变,替换如下:
请求nginx:http://192.168.0.105:8087/api/system/common/doLogin
Nginx代理替换之后:http://192.168.0.105:8089/system/common/doLogin
代理过程:将红色部分替换为绿色部分,其他部分不变:
正向代理
Nginx不仅可以实现反向代理,还能实现正向代理,那么什么是正向代理呢?前面说到反向代理我们是无感知的,我们并不知道我们需要访问的目标,我们只是知道代理的地址。而正向代理则不同,我们是很清楚我们需要访问的目标的,但是访问过程中出现了一个代理去帮我们完成这个请求并将结果返回。 此时服务器只知道请求来自哪个代理服务器,而不知道是哪个客户端发起的请求,正向代理模式屏蔽或者隐藏了真实客户端的信息。
负载均衡
Nginx提供了六种不同的负载均衡策略,分别为:
- 轮询(默认):最基本的配置方法,它是upstream模块默认的负载均衡默认策略。每个请求会按时间顺序逐一分配到不同的后端服务器。
来了一个订单会按照时间顺序来分发,比如现在是A分店接的单,再来一个订单就将订单交给B分店,这样循环。 - weight(权重):权重方式,在轮询策略的基础上指定轮询的几率。
这种方式会按照每个分店的权重来分发订单,比如A分店最大,能够处理的订单最多,这时候就应该将A分店的权重设置大一些,分发的订单就多一点。 - ip_hash:指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。
这种方式可以理解成根据用户的地址信息来选择将订单分发给哪家店,当然这并不意味着哪个地址近我就将这个订单分发给哪家店,因为在实际情况中我们是无法通过IP地址来判定客户端离目标服务器的距离的,你可以理解成外卖小哥也不知道这个地址离哪个分店近,他只是按照一定的规则按照订单地址分发,比如有四家分店,我可以按照地址最后一个字的音调来决定选择哪家,第一声我就选择A分店,以此类推。 - least_conn:把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。
这种方式选择的是订单数最少(连接数最少)的店来分配订单,轮询方案是将订单均匀分发给不同的店,但是不同的订单制作时间不一样,比如分店A接到的订单全是要加葱的,这时候分店A刚好没有葱了,还得花时间准备葱,这样采用轮询方案会导致订单在分店A堆积。这时候假如来了个订单按照轮询应该给A分店,但是我选择了最少订单的分店B来处理这个订单就会达到更好的负载效果。 - fair(第三方):按照服务器端的响应时间来分配请求,响应时间短的优先分配。
这种方式可以理解成按照店的处理速度来选择,哪家店能够最快处理这笔订单就交给谁。 - url_hash(第三方):按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。
这种方式要和ip_hash理解分开,ip_hash确保的是同一个用户的订单是交给固定的分店处理的,而url_hash虽然也是按照某一信息来决定分发,但是却跟ip_hash有很大的区别,可以理解成url_hash是根据点的火锅种类来分发的。试想这样一个场景,分店A做了很多汤卤火锅,分店B做了很多清炖火锅,分店C做了很多清水火锅,这时候假如来了一个订单是点汤卤火锅的,假如按照ip_hash是将该订单交给分店B,这样显然不太合适,而且假如分店B做了这份订单,但是一天下来分到的订单就只有这笔订单是汤卤火锅的,这样就会造成时间和资源上的浪费,这时候url_hash的优势就出来了,我可以根据客户请求的资源来决定要分发到哪个位置。
正则匹配
~ /item/(\d+)
location ~ /item/(\d+) {
}
- ~ 表示正则匹配
- **()**表示一个分组
- \d表示数字
- + 表示任意数量