如何使用Nginx进行负载均衡?
当我们单台机器不能够支撑我们用户的请求时,就会部署多台机器,此时用户一般访问时,会通过DNS服务器去解析访问的域名,找到对应的ip地址,然后通过ip去访问对应的服务器。
基本的方式都是一个域名映射多个服务器IP地址,这种方式会存在问题:
某台服务器故障或者重启中,DNS会有缓冲时间,故障后需要切换到另一条服务器,这个切换的时间会比较长。而且没用提供对后端服务器进行心跳检查和故障检测的机制。
因此外网就需要使用DSLB(全局负载均衡)进行流量调度,即将用户流量分配到距离他最近的机房或服务器来提升体验,当机房不可用,可以使用DNS进行切换到其他地区的IP来使用。
对于内网,可以实现简单的负载均衡。
定义
重新解释一下,负载均衡就是对流量或者用户的请求通过某种依据方式进行合理的调度到不同的服务器上执行。有了负载均衡,我们可以将应用服务器部署多台,然后通过负载均衡将用户的请求分发到不同的服务器用来提高网站、应用、数据库或其他服务的性能以及可靠性。
负载均衡的层
一、七层负载均衡
一般来讲,我们会使用Nginx,实现七层负载均衡,Nginx提供了HTTP(nginx_http_upstream_module)七层负载均衡。但是有一定的限制,比如吞吐量。
七层负载均衡是根据端口号和应用层协议如 HTTP 协议的主机名、URL, 转发报文到上游服务器(不同的 IP 地址+端口),如 HaProxy、Nginx。通过虚拟的URL或者主机名接收请求,然后再分配到真实服务器,因为处于OSI协议第七层,所以叫七层负载均衡。
七层的负载均衡,就是在四层的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比如同一个Web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可根据七层的URL、浏览器类别、语言来决定是否要进行负载均衡。举个例子,如果你的Web服务器分成两组,一组是中文语言的,一组是英文语言的,那么七层负载均衡就可以当用户来访问你的域名时,自动辨别用户语言,然后选择对应的语言服务器组进行负载均衡处理。
二、四层负载均衡
为了提升整体吞吐量,会在 DNS 和 Nginx 之间引入接入层,如使用 LVS (软件负载均衡器)、 F5 (硬负载均衡器)可以做四层负载均衡,即首先 DNS解析到 LVS/F5, 然后 LVS/F5 转发给 Nginx, 再由 Nginx 转发给后端 RealServer 。
在nginx1.9.0的版本开始也提供了TCP,支持 TCP(ngx stream upstream—m odule)四层负载均衡。
四层负载均衡就是通过发布第三层的IP地址(VIP),然后加四层的端口号,来决定哪些流量需要做负载均衡,对需要处理的流量进行NAT处理(网络地址转换处理),转发至后台服务器,并记录这个TCP或者UDP是由哪台服务器进行处理。如 LVS NAT 模式、HaProxy。
三、二层负载均衡(改写目标报文的mac地址)
二层负载均衡是通过改写报文的目标 MAC 地址为上游服务器 MAC 地址实现负载均衡,也就是第二层数据链路层,源 IP 地址和目标 IP 地址是没有变的,负载均衡服务器和真实服务器共享同一个VIP,上游服务器直接响应到客户端,不经过LVS,从而提高性能, 如LVS DR 工作模式就是这样实现的。
但是LVS和上游服务器必须要在通过一个子网,为了解决跨域问题又不影响负载均衡,可以选择在LVS后挂一个HaProxy,通过四到七层负载均衡器HaProxy集群来解决跨网和性能问题
四、三层负载均衡
基于IP地址的三层负载均衡.就不做更多的概述了。
怎么理解是第几层负载??
看下图,是利用基于OSI网络协议的第几层协议,那个就是几层负载均衡。对于负载均衡要关心的几个方面:
-
上游服务器配置:使用upstream server配置上游服务器。
-
负载均衡算法:配置多个上游服务器时的负载均衡机制。
-
失败重试机制:配置当超时或上游服务器不存活时,是否需要重试.
-
其他上游服务器。服务器心跳检查:上游服务器的健康检查I心跳检查。
一般来讲,Nginx提供的负载均衡都可以去实现上面的功能,包括负载均衡算法,故障转移,失败重试,容错,心跳等,当上游服务器出现问题时,可以通过OpenResty实现更智能的负载均衡,如降热点与肺热点流量分离等等,Nginx还是一台反向代理服务器,将用户的请求通过Nginx代理到内网中的某台上游服务器进行处理,反向代理服务器可以对响应结果进行缓存、压缩等处理,进一步提升性能。
我会在下面一一介绍,如何使用。
一、配置upstream Server
第一步,我们通常需要给nginx配置上游服务器的地址,也就是负载均衡到真实处理业务的服务器,通过在Http指令下配置即可。
- IP地址和端口: 配置上游服务器的ip地址和端口。
- weight:代表权重,就是表示分配给这台服务器的请求占比,权重越大,分配的流量越多。
当访问Nginx时,会将请求反向代理到backend对应的配置的上游服务器。
以上的配置需要配置在nginx的nginx.conf文件中。
二、负载均衡算法的设置
关于负载均衡算法
在nginx中提供了很多负载均衡算法,默认使用的是轮询。
round-robin: 轮询,默认负载均衡算法,即以轮询的方式将请求转发到上游服务器,通过配合weight配置可以实现基于权重的轮询。
ip_hash: 根据客户IP进行负载均衡 ,即相 、同的IP将 载均衡到 同一 个upstream server。
设置如下,在nginx的server中配置:hash key [consistent]: 对某一 个key进行哈希或者使用一 致性哈希算法进行负载均衡。使用Hash算法存在的问题是,当添加/删除一 台服务器时,将导致很多key被重新负载均衡到不同的服务器(从而导致后端可能出现问题);因此,建议考虑使用一 致性哈希算法 ,这样当添加/删除一台服务器时,只有少数key将被重新负载均衡到不同的服务器。
Hash算法: 根据请求的uri进行负载均衡,可以使用Nginx变量,因此可以实现复杂的算法。
hash使用方式如下:
如果使用一致性hash算法:consistent_key指定:
看上图,location指定了一致性哈希key,此处会优先处理请求参数cat类目,如果没有,则再根据请求uri进行处理。
然后在实际中会通过lua设置一致性hash key。
set_by_lua_file $consistent_key "lua_balancing.lua";
具体代码如下:
三、失败重试
主要有两部分配置: upstream server 和proxy_pass.
图中表示的是: 设置该上游服务器的最大失败次数为2次,失败时间为10秒,当这个时间内失败了2次,则认为该上游服务器不可用或者宕机,然后可以摘掉该上游服务器。
proxy_pass配置:
按上面的配置,当请求遇到错误时,会重试下一台服务器。
四、健康检查
Nginx对上游服务器的健康检查一般是默认采用惰性策略,商业版提供了主动的健康检查,也可以集成一个模块(nginx_upstream_check_module)来进行主动健康检查。
nginx_upstream_check_module: 支持TCP心跳以及HTTP心跳来实现健康检查。
- TCP方式的心跳检查使用
upstream backend {
server 192.168.61.1:9080 weight= l;
server 192.168.61.1:9090 weight= 2;
check interval=3000 rise=l fall=3 timeout= 2000 type= tcp;
}
• interval: 检测间隔时间,此处配置了每隔3秒检测一 次。
• fall: 检测失败多少次后,上游服务器被标识为不存活。
• rise: 检测成功多少次后,上游服务器被标识为存活,并可以处理请求。
• timeout: 检测请求超时时间配置。
- HTTP方式的心跳检查使用
upstream backend {
server 192.168.61.1:9080 weight=l;
server 192.168.61.1:9090 weight= 2;
check interval= 3000 rise= l fall= 3 timeout=2000 type=http;
check_http_send "HEAD /status HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
对比TCP,HTTP心跳检查新增了两个额外的配置:
check_http_send: 检查时发的HTTP内容。
check http expect_alive: 当上游服务器返回对应的响应状态码时,认为上游服务器存活。
(提醒: 心跳检测的时间间隔不能太短,同时需要控制好超时时间一般是2秒,http)
通过以上的配置,我们基本上可以实现负载均衡涉及的一些常用的功能和机制。另外我们也可以基于域名配置上游服务器。如:
upstream backend {
server www.c.com
server www.c2.com
}
当域名对应的ip地址发生变化时,nginx不会动态更新,只有商业版才支持更新。
其他的配置
备份上游服务器
另外我们还可以配置备份的上游服务器,就是说,当配置的所有主上游服务器都不存活时,可以把请求转发给备份的服务器进行处理,避免影响到功能。
应用方面: 为了压测进行缩容上游服务器时,会设置一些备份的上游服务器,避免服务器挂了之后,会影响用户的处理。
长连接的配置
keepalive配置长连接的连接数量。该指令可以配置每个工作进程与上游服务器可缓存的空闲连接的最大数量,超出该数量,最近最少使用的连接将被关闭。同时还要在location配置:
,如果是http1.0的连接,需要配置发送"Connection:Keep-Alive" 请求头.
HTPP进行动态负载均衡
上面的问题中,我们每次上游服务器如果有变更,都需要去更改nginx配置信息,我们提到了一个概念:动态负载均衡。因此我们就需要一种服务注册的方式,可以将上游服务器器动态注册到nginx上,这就是动态负载均衡。
介绍一款产品: Consul,这是一款开源的分布式服务注册与发现系统,可以通过http api进行服务发现与注册。这部分内容我后续会更新。
Nginx四层负载均衡应用
前面我们讲了几种负载均衡的区别,七层的吞吐量受限,nginx还提供了四层的负载均衡解决七层的问题,现在就简单实现下:
- 配置http负载均衡时,是在http指令下的,而四层的负载均衡是在stream指令下。
stream {
upstream mysql_backend {
//进行失败重试、惰性健康检查、负载均衡算法相关配置
server 192.168.0.10:3306 max_fails= 2 fail_timeout= 10s weight=l;
server 192.168.0.11:3306 max_fails= 2 fail_timeout= lOs weight=l; least conn;
}
server {
#监听端口
listen 3308;
#失败重试
proxy_next_upstream on; 失败重试开启
proxy_next_upstream_timeout 0; 超时连接时间,默认60秒
proxy_next_upstream_tries 0; 重试次数
#超时配置
proxy_connect_timeout 1s;
proxy_timeout 1m;
#限速配置
proxy_upload_rate 0;
proxy_download_rate 0;
#上游服务器
proxy_pass mysql_backend;
}
}
proxy_ connect_ timeout配置与上游服务器连接超时时间,默认60s。proxy_timeout配置与客户端或上游服务器连接的两次成功读/写操作的超时时间,如果超时,将自动断开连接,即连接存活时间,通过它可以释放那些不活跃的连接,默认10分钟。
以上配置都是静态配置。关于动态负载均衡我后续会更新一篇使用consul进行nginx动态负载均衡使用的文章。
待续。。。