1. Nginx负载均衡核心组件介绍
1.1 Nginx upstream模块
1.1.1 upstream模块介绍
Nginx负载均衡功能依赖于ngx_http_upstream_module模块,所支持的代理方式包括proxy_pass、fastcgi_pass、memcached_pass等,新版Nginx软件支持的方式有所增加。这里主要针对proxy_pass代理方式进行讲解。
ngx_http_upstream_module模块允许Nginx定义一组或多组节点服务器,使用时可以通过proxy_pass代理方式把网站的请求发送到事先定义好的对应upstream组上,具体写法为“proxy_pass http://www_pools”,其中www_pools就是一个upstream节点服务器组的名字。ngx_http_upstream_module模块官方地址:http://nginx.org/en/docs/http/ngx_http_upstream_module.html。
1.1.2 upstream模块语法
范例1:基本的upstream配置案例
upstream www_pools { ---upstream关键字必须要有,www_pools为一个upstream集群组名字,可以自己起名
server 192.168.9.7:80 weight=5;
server 192.168.9.9:80 weight=10;
server 192.168.9.10:80 weight=15;
---server关键字时固定的,后面可以接域名(门户会员)或IP。如果不指定端口,默认是80端口。weight代表权重,数值越大被分配的请求越多,注意结尾有分号
}
范例2:较完整的upstream配置案例
upstream blog_pools {
server 192.168.9.7; ---这一行标签和下一行是等价的
server 192.168.9.9:80 weight=1 max_fails=1 fail_timeout=10s; ---这一行标签是和上一行是等价的,此行多余的部分就是默认配置,不写也可以
server 192.168.9.10:80 weight=1 max_fails=2 fail_timeout=20s backup;
server 192.168.9.11:80 weight=1 max_fails=2 fail_timeout=20s backup;
}
范例3:使用域名及socket的upstream配置案例
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080; ---域名加端口。转发到后端的指定端口上
server unix:/tmp/backend3; ---指定socket文件
# 提示:server后面如果接域名,需要内网有DNS服务器或者在负载均衡器的hosts文件做域名解析
server backup1.example.com:8080 backup;
# 结尾backup表示备份服务器,其他指定服务器都不可访问时启用,backup的用法和Haproxy中用法一样
server backup2.example.com:8080 backup;
}
如果是两台Web服务器做高可用,常规方案就需要Keepalived配合,那么这里使用Nginx的backup参数通过负载均衡功能就可以实现Web服务器集群了,对于企业应用来说,能做集群就不做高可用。
1.1.3 upstream模块相关说明
upstream模块的内容应放于nginx.conf配置的http{}标签内,其默认调度节点算法是wrr(权重轮询,weighted round-robin)。下表所示为upstream模块内部server标签部分参数说明。
来看个示例:
upstream backend {
server backend1.example.com weight=5; ---如果就是单个Server,没必要设置权重
server 127.0.0.1:8000 max_fails=5 fail_timeout=10s;
---当检测次数等于5的时候,5次连续检测失败后,间隔10s再重新检测,这个参数和proxy/fastcgi/memcached_next_upstream相关
server unix:/tmp/backend3;
server backup1.example.com:8080 backup; ---热备机器设置
}
需要特别说明的是,如果是Nginx代理cache服务,可能需要使用hash算法,此时若宕机,可通过设置down参数确保客户端用户按照当前的hash算法访问,这点很重要。示例配置如下:
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com;
}
下面是Haproxy负载均衡器server标签的配置示例。
# 开启对后端服务器的健康检测,通过GET /test/index.php来判断后端服务器的健康情况。
server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2
server php_server_2 10.12.25.72:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1
server php_server_b 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup
上述命令的说明如下:
- weight:调节服务器的请求分配权重。
- check:开启对该服务器健康检查。
- inter:设置连续两次的健康检查间隔时间,单位毫秒,默认值为2000。
- rise:指定多少次连续成功的健康检查后,即可认定该服务器处于可用状态。
- fall:指定多少次不成功的健康检查后,即认为服务器为宕机状态,默认值为3。
- maxconn:指定可并发发送到该服务器的最大并发连接数。
1.1.4 upstream模块调度算法
调度算法一般分为以下两类:
第一类为静态调度算法,即负载均衡器根据自身设定的规则进行分配,不需要考虑后端节点服务器情况。例如:rr、wrr、ip_hash都属于静态调度算法。
第二类为动态调度算法,即负载均衡器会根据后端节点的当前状态来决定是否分发请求。例如:连接数少的优先获得请求,响应时间短的优先获得请求,least_conn、fair等都属于动态调度算法。
下面介绍一下常见的调度算法。
(1)rr轮询(默认调度算法,静态调度算法)
按客户端请求顺序把客户端的请求注逐一分配到不同的后端节点服务器,这相当于LVS中的rr算法,如果后端节点服务器宕机(默认情况下Nginx只检测80端口),宕机的服务器会被自动从节点服务器池中剔除,以使客户端的用户访问不受影响。新的请求会分配给正常的服务器。
(2)wrr(权重轮询,静态调度算法)
在rr轮询算法的基础上加上权重,即为权重轮询算法,当使用该算法时,权重和用户访问成正比,权重值越大,都转发的请求也就越多。可以根据服务器的配置和性能指定权重值大小,从而有效解决新旧服务器性能不均带来的请求分配问题。
举个例子:
后端服务器192.168.1.2的配置为:E5520*2 CPU,8GB内存。
后端服务器192.168.1.3的配置为:Xeon(TM)2.80GHz * 2,4GB内存。
假设希望当有30个请求到达前端时,其中20个请求交给192.168.1.3处理,剩余10个请求交给192.168.1.2处理,可做如下配置:
upstream oldboy_lb {
server 192.168.1.2 weight=1;
server 192.168.1.3 weight=2;
}
(3)ip_hash(静态调度算法)
每个请求按客户端IP的hash结果分配,当新的请求到达时,先将其客户端IP通过哈希算法哈希出一个值,在随后的客户端请求中,客户IP的哈希值只要相同,就会被分配至同一台服务器,该调度算法可以解决动态网页的session共享问题,但有时会导致请求分配不均,即无法保证1:1的负载均衡,因为在国内大多数公司都是NAT上网模式,多个客户端会对应一个外部IP,所以,这些客户端都会被分配到同一节点服务器,从而导致请求分配不均。LVS负载均衡的-p参数、Keepalived配置里的persistence_timeout 50参数都类似这个Nginx里的ip_hash参数,其功能均为解决动态网页的session共享问题。
同样来看一个示例:
upstream oldboy_lb {
ip_hash;
server 192.168.1.2:80;
server 192.168.1.3:8080;
}
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com;
}
注意:当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能写入weight和backup两个参数,即使有也不会生效。
(4)fair(动态调度算法)
此算法会根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配。这是更加智能的调度算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair调度算法的,如果需要使用这种调度算法,必须下载Nginx的相关模块upstream_fair。
示例如下:
upstream oldboy_lb {
fair;
server 192.168.1.2;
server 192.168.1.3;
}
(5)least_conn(动态调度算法)
least_conn算法会根据后端节点的连接数来决定分配情况,哪个机器连接数少就分发给哪个节点。
(6)url_hash算法(动态调度算法)
和ip_hash类似,这里是根据访问URL的hash结果来分配请求的,让每个URL定向到同一个后端服务器,后端服务器为缓存服务器时效果显著。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method使用的是hash算法。
url_hash按访问URL的hash结果来分配请求,使每个URL定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率命中率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx的hash模块软件包。
url_hash(Web缓存节点)和ip_hash(会话保持)类似。示例配置如下:
upstream oldboy_lb {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
(7)一致性hash算法(动态调度算法)
一致性hash算法一般用于代理后端业务为缓存服务(Squid、Memcached)的场景,通过将用户请求的URI或者指定字符串进行计算,然后调度到后端的服务器上,此后任何用户查找同一个URI或者指定字符串都会被调度到这一台服务器上,因此后端的每个节点缓存的内容都是不同的,一致性hash算法可以使后端某个或几个节点宕机后缓存的数据动荡的最小。
http {
upstream test {
consistent_hash $request_uri;
server 127.0.0.1:9001 id=1001 weight=3;
server 127.0.0.1:9002 id=1002 weight=10;
server 127.0.0.1:9003 id=1003 weight=20;
}
}
虽然Nginx本身不支持一致性hash算法,但Nginx的分支tengine支持。
1.2 http_proxy_module模块
1.2.1 proxy_pass指令介绍
proxy_pass指令属于ngx_http_proxy_module模块,此模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过location功能匹配指定的URI,然后把接收到的符合匹配URI的请求通过proxy_pass抛给定义好的upstream节点池。
下面是proxy_pass的使用案例。
1)将匹配URI为name的请求抛给http://127.0.0.1/remote/。
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}
2)将匹配URI为some/path的请求抛给http://127.0.0.1。
location /some/path/ {
proxy_pass http://127.0.0.1;
}
3)将匹配URI为name的请求应用指定的rewrite规则,然后抛给http://127.0.0.1。
location /name/ {
rewrite /name/([^/]+) /users?name=$1 break;
proxy_pass http://127.0.0.1;
}
1.2.2 http_proxy_module相关参数
Nginx反向代理功能主要是通过http proxy模块来实现的。默认在安装Nginx时已经安装了http proxy模块,因此可直接使用。下面详细解释模块中每个选项代表的含义。