Nginx之反向代理与负载均衡
1. 反向代理与负载均衡
1. 反向代理
反向代理服务器接收到用户的请求后,会代理用户重新向代理后的节点服务器发送请求,最后节点服务器把数据返回给代理服务器,然后代理服务器返回给客户端。节点服务器看到的是代理服务器的信息。
2. 负载均衡
转发用户请求的数据包,节点服务器看到的还是真实的客户信息。
3. nginx的负载均衡严格来说是利用反向代理实现的,而不是像LVS一样使用的转发。
4. nginx负载均衡的组件

这两个模块不需要编译,默认在http模块中。
2. 配置一个简单的nginx负载均衡
1. 准备四台服务器
一台主负载均衡
一台从负载均衡
两台节点服务器
2. 分别在主从安装nginx软件,两台节点服务器可以使用apache或者nginx或者其他web应用软件。
3. 要保持两台节点服务器的配置一致,可以采用NFS,他们共同一套代码。
4. 主从负载均衡的配置如下:
[root@nginx-server-proxy conf]# cat k8s_www.conf
upstream k8s_www{
server 172.16.20.215:30001 weight=1;
server 172.16.20.214:30001 weight=1;
}
server {
listen 80 ;
server_name ceshiwww.cmr.net.cn;
location / {
access_log logs/cswww.log main;
proxy_pass http://k8s_www/;
}
}
5. 做一些测试,关闭一个节点,关闭所有节点,看报错。
3. Nginx负载均衡核心组件
1. upstream模块
1. Nginx的负载均衡功能依赖于ngx_http_upstream_module模块,所支持的代理方式包括proxy_pass,fastcgi_pss,memcached_pass。
2. upstream模块内参数
server 10.0.0.1:80 可以是IP或者域名,不写端口默认为80
weight=1 默认为1,值越大,表示接收的请求比例越大。如果不写就是默认值。
max_fails=1 默认为1,nginx尝试连接后端主机失败的次数,这个数值是配合proxy_next_upstream,fastcgi_next_upstream,memcached_next_upstream三个参数来使用的.
backup 热备配置,当主服务器全部宕机时,就会向它转发请求。
fail_timeout=10s 默认为10s。在这个指定的时间内服务器必须提供响应,如果在这个时间内没有收到响应,那么服务器将会被标记为down状态
down 服务器永不可用,这个参数可配合ip_hash使用
keepalive 32 Nginx服务器将会为每一个worker进程保持同上游服务器的连接。保持32个连接数。
例子:
nginx反向代理两台tomcat,一台192.168.1.166:8095,一台192.168.1.164:8095
其中一台192.168.1.166的tomcat已经宕机,观察nginx访问日志会发现(max_fails=1,fail_timeout=10s)
当访问nginx站点,每10s会执行一次,访问192.168.1.166,192.168.1.166因为已经无法响应请求,所以他会把请求转交给192.168.1.164节点。所以看到的访问日志内容如下:
test.zhenpin.com 222.222.106.54 192.168.1.166:8095, 192.168.1.164:8095 [19/Apr/2021:10:43:07 +0800] "GET /oms/whsendorders/gtExpress.json HTTP/1.1" 200 894 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36" 0.001, 0.009 0.010
这种方式是被动健康检查,会导致访问的时候,响应很慢。
3. upstream模块调度算法
1. rr(默认调度算法,静态调度算法)
按客户端请求顺序,逐一分配到不同的后端节点服务器,如果后端节点服务器宕机,宕机的服务器会自动从节点服务器池中剔除。
2. wrr(权重轮询,静态调度算法)
在轮询算法的基础上加权重,权重值越大,被转发的请求也就越多。
3. ip_hash(静态调度算法)
每个请求按客户端IP的hash结果分配,当新的请求到达时,先将客户端IP通过哈希算法哈希出一个值,在随后的客户端请求中,客户IP的哈希值只要相同,就分配到同一台服务器,该调度算法可以解决动态网页的session共享问题,但可能会导致请求分配不均,当调度算法为ip_hash,不能有weigth和backup,有也不生效。键值基于C类地址。
upstream k8s_www{
ip_hash;
server 172.16.20.215:30001 ;
server 172.16.20.214:30001 ;
}
4. fail(动态调度算法)
根据后端服务器的响应时间来分配请求,响应时间短优先分配。需要下载upstream_fair模块。
例子:
upstream k8s_www{
server 172.16.20.215:30001 ;
server 172.16.20.214:30001 ;
fair;
}
5. least_conn
根据后端服务器的连接数来分配请求,哪个机器连接数少就分发。
6. url_hash算法
根据访问URL的hash结果来分配请求,后端服务器为缓存服务器效果显著。必须安装nginx的hash模块软件包。
7. 一致性hash算法
一般用于后端为缓存服务。
2. http_proxy_module模块
1. proxy_pass指令介绍
proxy_pass URL;
例子:
proxy_pass http://www.baidu.com/uri; 重定向到其他站点,地址栏会有变化,301跳转
proxy_pass http://localhost:8000/uri/;
proxy_pass后面也可以跟一组服务器。
注意1: 如果在proxy_pass里面指明了传输协议http,那么在upstream里面就不需要指明。如果在upstream指明了,则在proxy_pass不需要指明。
注意2:URL包含uri与不包含uri有很大的区别。
包含uri,nginx会使用新的uri替换原来的uri.
不包含uri,nginx还保持原来的uri不变。
例子1:

因为url包含uri"/loc/",所以客户端访问的时候,请求为:"http://www.myweb.name/server/",nginx服务器会把地址转向"http://192.168.1.1/loc/"

因为url不包含uri,所以客户端请求为:http://www.myweb.com/server,转向的地址为:http://192.168.1.1/server
例子2:

像这种情况之下,url包含或不包含uri,客户端请求:http://www.myweb.com,都会转向http://192.168.1.1
例子3:

配置2 url包含uri,客户端请求:http://www.myweb.com/server,转向地址:http://192.168.1.1/
配置1 url不包含uri,客户端请求:http://www.myweb.com/server,转向地址:http://192.168.1.1/server
2. proxy_set_header 设置http请求头然后传给后端服务器。
语法结构:proxy_set_header field value;
field:要更改的信息所在的头域
value:更改的值,支持使用文本,变量或者变量的组合
默认情况下,该指令的设置为:
proxy_set_header Host $proxy_host; 将proxy_pass指令后面的名称作为Host头域的值
例子:

$proxy_host就是www.baidu.com,如果proxy_pass指令后面是: www.baidu.com:8080,那么$proxy_host就是:www.baidu.com:8080
proxy_set_header Connection close;
其它设置:
1. proxy_set_header Host $host; 以下顺序获得:请求行中的host、请求头中的Host、配置文件中匹配到的server_name
例子:

$host就是server块里的server_name定义的值
2. proxy_set_header Host $http_host; 请求头"Host"的值
3. proxy_set_header Host $host:$proxy_port; 将proxy_pass指令中指定的端口,或者是默认协议的端口,一起作为Host头域的值
例子:

$proxy_port是8088
4. proxy_set_header Host $host:$server_port; 将listen指令监听的端口和server_name一起作为Host头域的值
5. proxy_set_header X-Real-IP $remote_addr; 客户端的IP地址,如果有代理的话表示最后一个代理服务器的IP
6. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 如果每个代理服务器都设置了,那么它就是remote_addr用逗号合起来,如果请求头中没有X-Forwarded-For则proxy_add_x_forwarded_for为remote_addr,会记录请求的路由顺序。
3. proxy_connect_timeout
定义一个与被代理服务器的建立连接的超时时间。通过不会超过75秒。
4. proxy_send_timeout
设置传输一个请求到被代理的服务器的超时时间。超时不是整个请求时间,而是在两次连续write操作期间。如果超时后,upstream没有收到新的数据,nginx会关闭连接
5. proxy_read_timeout
定义了从被代理的服务器读一个响应的超时时间。超时不是获得整个response的时间,而是两次连续reading操作的时间。如果被代理的服务器在这个时间内不再传输任何数据,那么连接被关闭。
3. 反向代理特例
1. 如果location定义了一个正则表达式,那么在URI部分没有转换发生。URI /local将被直接传递到上游服务器,而不会如期地转换为/foreign

2. 如果在location内有rewrite规则改变了URI,那么nginx使用这个URI处理请求,不再发生转换
4. 根据URL的目录地址实现代理转发
1. 实战例子:
通过nginx实现动静分离,即通过反向代理配置规则实现动态资源和静态资源及其他业务分别由不同的服务器解析。
1. 首先要创建三个upstream池,分别对应动态和静态和其他业务,三个池中可以由多台服务器构成。

2. 利用location或者if语句,把不同的url路径分别传给不同的upstream。



5. 根据客户端的设备(user_agent)转发

6. 根据文件扩展名实现代理转发


7. Nginx负载均衡监测节点状态
1. nginx需要安装补丁,补丁地址:https://github.com/yaoweibin/nginx_upstream_check_module
Tengine原生就支持,不需要安装。
2. nginx安装该模块过程。


3. 配置upstream_check


1. 指令配置:
Syntax: check interval=milliseconds [fall=count] [rise=count] [timeout=milliseconds] [default_down=true|false] [type=tcp|http|ssl_hello|mysql|ajp] [port=check_port]
Default: 如果没有配置参数,默认值是:interval=30000 fall=5 rise=2 timeout=1000 default_down=true type=tcp
Context: upstream
2. 参数意义
interval:向后端发送的健康检查包的间隔。单位为毫秒。 fall(fall_count): 如果连续失败次数达到fall_count,服务器就被认为是down。 rise(rise_count): 如果连续成功次数达到rise_count,服务器就被认为是up。 timeout: 后端健康请求的超时时间。 default_down: 设定初始时服务器的状态,如果是true,就说明默认是down的,如果是false,就是up的。默认值是true,也就是一开始服务器认为是不可用,要等健康检查包达到一定成功次数以后才会被认为是健康的。 type:健康检查包的类型,现在支持以下多种类型 tcp:简单的tcp连接,如果连接成功,就说明后端正常。 ssl_hello:发送一个初始的SSL hello包并接受服务器的SSL hello包。 http:发送HTTP请求,通过后端的回复包的状态来判断后端是否存活。 mysql: 向mysql服务器连接,通过接收服务器的greeting包来判断后端是否存活。 ajp:向后端发送AJP协议的Cping包,通过接收Cpong包来判断后端是否存活。 port: 指定后端服务器的检查端口。你可以指定不同于真实服务的后端服务器的端口,比如后端提供的是443端口的应用,你可以去检查80端口的状态来判断后端健康状况。默认是0
3. 其它指令
Syntax: check_http_send http_packet
Default: "GET / HTTP/1.0\r\n\r\n"
Context: upstream
该指令可以配置http健康检查包发送的请求内容。为了减少传输数据量,推荐采用"HEAD"方法。
例子: check_http_send "HEAD /advert/testConfig.txt HTTP/1.0\r\n\r\n";
Syntax: check_http_expect_alive [ http_2xx | http_3xx | http_4xx | http_5xx ]
Default: http_2xx | http_3xx
Context: upstream
该指令指定HTTP回复的成功状态,默认认为2XX和3XX的状态是健康的。
例子: check_http_expect_alive http_2xx http_3xx http_4xx;
8. memcached上游服务器
upstream memcaches{
server 192.168.1.100:11211;
server 192.168.1.101:11211;
}
server {
location / {
set $memcached_key "$uri?args";
memcached_pass memcaches;
error_page 404 = @appserver;
}
location @appserver {
proxy_pass http://127.0.0.1:8080;
}
}
memcached_pass指令使用memcached_key实现key的查找,如果没有响应,将请求转发到localhost
9. FastCGI上游服务器
upstream fastcgis{
server 192.168.1.100:9000;
server 192.168.1.101:9000;
}
server {
location / {
fastcgi_pass fastcgis;
}
}

浙公网安备 33010602011771号