Nginx的负载均衡配置

前言

负载均衡本质就是一个反向代理。
通俗点讲, 就类似10086客服电话, 如果只有一个通话员, 那全国十几亿人肯定处理不过来, 这时候就多招聘一堆通话员, 做负载均衡, 这样就减少了通话员的压力。

SLB和GSLB

负载均衡又分为

  1. GSLB(Global Server Load Balance)全局负载均衡
  2. SLB(Server load balancing)负载均衡

还是以10086为例, 如果只有北京开设了一个通话员中心(SLB), 即使通话员(server)的数量足够, 但是广东省的要打电话过去, 西藏的要打电话过去, 路途遥远。那么就设立多个通话员中心(SLB), 广东省的打广东省的10086, 西藏的打西藏的10086, 如果解决不了问题, 再上升到北京的10086

也就是说, 多个SLB组成了GSLB

OSI模型上的负载均衡

学过计算机网络的应该都知道OSI模型, 分为物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
比如数据链路层是根据mac地址进行数据包发送的, 那么就可以在这里做负载均衡。(一般是用虚拟mac地址方式,外部对虚拟mac地址请求,负载均衡接收后分配后端实际的mac地址响应)。

最常用的就是
四层负载均衡(IP + port)
七层负载均衡(IP + port + URL)
Nginx是应用层, 也就是七层负载均衡。

基本配置

假设我们有三台机器192.168.0.100192.168.0.101example.com
下面是一个简单的配置方法, upstream块必须在http块内。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
http {
upstream tomcats {
server 192.168.0.100:8080;
server 192.168.0.101:8080;
server example.com:8080;
}
server {
# 1. 负载均衡, 首页单独处理, 加快速度
location = / {
proxy_pass http://tomcats/index
}
location / {
proxy_pass http://tomcats
}
}
}

默认是以请求次数做轮询条件, 比如第一次请求, 则分配到192.168.0.100:8080, 第二次请求, 则分配到192.168.0.101:8080, 以此类推。

额外配置

追加到server后面

1
2
3
4
5
upstream tomcats {
server 192.168.0.100:8080;
server 192.168.0.101:8080 weight=2;
server example.com:8080 down;
}
配置 说明
weight=2 权重越高, 越容易被轮询到
down 暂不参与负载均衡
backup 预留的备份服务器, 当其他所有服务挂了的时候启用
max_fails=1 允许请求失败的次数
fail_timeout=10s 经过max_fails失败后, server暂停的时间, 默认10s
max_conns=10 限制最大的接收连接数

负载均衡策略

除了默认的轮询策略, 还有其他的负载均衡策略, 配置到upstream内即可。

轮询策略 说明
轮询(默认) 按请求顺序分配到不同的server
加权轮询 weight值越大, 分配到的访问几率越高(最常用)
ip_hash 每个请求按访问IPhash结果分配, 同一个IP固定访问一个server
url_hash 按照访问的URLhash结果分配, 同一个URL固定访问一个server
least_conn 最少链接数, 哪个server连接数少就分配给谁
hash关键数值 hash自定义的key, url_hash是具体实现, 在Nginx 1.7.2后可用
fair 响应时间短的服务器优先分配

下面只简单介绍下应用场景

ip_hash

保证同一个用户访问同一台服务器, 并且不用对项目做多大改动.
用于需要对SessionCookie保持一致的情况.

但是不能保证平均负载.
并且如果多台机器走同一个代理服务器, Nginx根据代理服务器的IPHash, 会导致多台服务器走的都是同一个server.

1
2
3
4
5
6
upstream tomcats {
ip_hash;
server 192.168.0.100:8080;
server 192.168.0.101:8080;
server example.com:8080;
}

url_hash

能保证同一个服务, 同一个url访问同一个服务器.
这种负载均衡策略也不能保证平均负载, 请求频繁的url会请求到同一个服务器上.

url_hash是将$request_uri作为自定义hashkey
注意, 自定义hash key只有在Nginx 1.7.2后可用。

1
2
3
4
5
6
upstream tomcats {
hash $request_uri;
server 192.168.0.100:8080;
server 192.168.0.101:8080;
server example.com:8080;
}

最佳实践

没有最佳实践, 具体场景具体分析.
但是实际上解决Session同步问题, 一般都用Redis做分布式Session.
这里就不展开讲了, 和Nginx无关.

参考资料