Nginx进阶
1. 代理转发
Nginx提供代理转发功能,做动静分离,使用proxy_pass配置
1. 快入体验
1. 项目准备
创建一个普通的Maven项目


1. pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2. Application
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3. Controller
@RestController
public class NginxController {
@GetMapping("hello")
public String hello(){
return "Hello Nginx!!!";
}
}
2. nginx.conf
修改 yase.conf,内容如下
server {
#监听端口
listen 80;
#域名
server_name yase.cn;
location / {
#站点根目录,静态资源都可以放到这里
root /home/web/yase;
#首页
index yase.html;
}
location /hello {
proxy_pass http://192.168.56.1:8080;
}
}
注意:使用 nginx -t、nginx -s reload 校验
3. 测试
重新加载配置文件、启动项目后,浏览器访问:http://yase.cn/hello

原理解释:

2. 详细策略
使用proxy_pass时,有好几种情况,不同的配置会转发到不同的路径
1. 第一种

端口号后有“/”,请求是:http://192.168.56.113/ng/hello,会转发到:http://192.168.56.1:8080/hello
好处:后端接口不对外暴露
2. 第二种

端口号后没有“/”,请求是:http://192.168.56.113/ng/hello,会转发到:http://192.168.56.1:8080/ng/hello
在 DispatcherServlet 的 doDispatch 方法中打断点可以看到请求到后端的路径

3. 第三种

请求是:http://192.168.56.113/ng/hello,会转发到:http://192.168.56.1:8080/yase/hello

4. 第四种
比第三种最后少了一个“/”

请求是:http://192.168.56.113/ng/hello,会转发到:http://192.168.56.1:8080/yasehello

5. 第五种

端口号后有“/”,请求是:http://192.168.56.113/ng/hello,会转发到:http://192.168.56.1:8080//hello

6. 第六种

端口号后有“/”,请求是:http://192.168.56.113/ng/hello,会转发到:http://192.168.56.1:8080/ng/hello

7. 总结
配置 proxy_pass 时,可以实现URL路径的部分替换
proxx_pass 后的地址:
- 有 “/”,会把 path 中 跟 location 匹配的部分干掉,剩余的拼接到 proxx_pass 的地址后
- 没有 “/”,把 path 中的请求路径和参数,拼接到 proxx_pass 的地址后
8. 建议
一般建议配置如下

2. 负载均衡
1. 快速体验
1. nginx.conf
还是修改 yase.conf,直接用下面的配置全部替换
# 新增 upstream 配置,名称是:yase
upstream yase {
server 192.168.56.1:8080;
server 192.168.56.1:8888;
}
server {
#监听端口
listen 80;
#域名
server_name yase.cn;
#编码识别
#charset koi8-r;
#日志格式及日志存放路径
#access_log logs/host.access.log main;
#location 用于匹配请求路径
location / {
# 设置请求转发的 yase
proxy_pass http://yase/;
}
#错误页面
#error_page 404 /404.html;
}
注意:使用 nginx -t、nginx -s reload 校验
2. 修改项目
- 修改Controller

- 修改启动端口




- 浏览器访问结果:


8080和8888交替出现
2. 具体策略
1. 轮询
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器宕机,能自动剔除掉。
上面快速体验就是轮训策略
2. 加权轮询
使用weight,代表权重,默认为1,权重越高被分配的客户请求就越多

上图:一同访问 6 次,8888被分配 4 次,8080被分配 2 次
使用场景:两天服务器性能不一样,性能高的就权重高
3. IP Hash
生产环境不用,只做了解、测试
请求按访问 IP 的 hash 值分配,这样每个访客固定访问一个后端服务器

4. down
表示某个机器下线,不参与负载均衡

这时候再访问,就只能分配给8888
5. backup
表示备用主机,其他机器都不能用了,请求才会分配给他

上图:请求只会分配给 8080

上图:请求只会分配给备用主机 8888
3. 限流
1. 基本使用
nginx支持限流:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
修改 yase.conf,定义限流规则

在 location 中使用规则

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
# 放到location中,表示这个location使用上面的配置限流
limit_req zone=one;
解释:
limit_req_zone:进行限流访问,防止用户恶意攻击刷爆服务器
$binary_remote_addr:访问者的ip地址
zone=yase:10m:标识内存中有一块内存区域大小为10m,并分配一个名称是yase,存储访问者的ip地址
32位平台上,1M能存储大约16000个 IP 地址
rate=1r/s:限制每秒只处理一个请求
总结:同一个ip地址在每秒内只能访问1次,如果新的ip地址来访问,会清除内存中最少访问的IP,如果无法清除,请求直接失败
浏览器上1秒内,连续访问两次:http://yase.cn/
第一次成功

第二次失败

2. burst
缓冲区

上图配置:请求的频率超过rate=1r/s,会放到缓冲区中,但是缓冲区长度=1,只能放1个,其他的直接失败
在centos7上安装并发测试工具,执行: yum install httpd -y

查看版本

删除 lvbu.conf,原因:ab测试时,访问:http://localhost:80/,但是lvbu.conf中也是监控80端口,会有冲突
重新加载nginx配置文件后,使用ab测试: ab -c 10 -n 10 http://localhost/
解释:
- -c 10:一次发送10个请求
- -n 10:请求的总数量是10
- -c 10 -n 100:表示发送测试10次,每次并发10个请求

结果:

3. nodelay
设置缓冲区后,第1个请求能够快速处理,但是第2个请求就只能延期1秒后处理,因为rate=1r/s;
nodelay:立即处理正在排队的请求

重新加载配置文件后,再次使用ab测试

但 nodelay 不会清空缓冲区,里面的请求还是每秒1一个的移除
配置 nodelay 后,每秒处理的请求数=rate+burst
4. 自定义错误页面
限流后,nginx返回的页面不合适

根据返回的状态码可以自定义页面
修改yase.conf

在 /home/web/yase 目录中新增一个 503.html
<CTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>亚瑟</title>
</head>
<body>
<h1>亚瑟的大宝剑提示您:限流了</h1>
</body>
</html>
注意:切记在保存html文件的时候一定要用utf-8编码
重新加载配置文件后,浏览器高频率访问:http://yase.cn/


浙公网安备 33010602011771号