最近公司内部用的阿里云SLB实例感觉不够用,主要因为https实例在一个slb实例内只能创建10个,http实例好像是50个,目前这边主要都是https,随着项目的增多,slb实例费用就上去了,所以只好自建了。另一方面一些内网调用就不用创建内网SLB实例(内网实例也需要收费的-.-)

upstream

1
2
3
Syntax:upstream name { ... }
Default:—
Context:http

定义一个上游服务器组,样例:

1
2
3
4
5
6
7
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;

server backup1.example.com backup;
}

upstream内使用server指令配置每个真实后端服务器

1
2
3
Syntax:server address [parameters];
Default:—
Context:upstream

upstream块内的server指令中几个重要的参数

  • weight=_number_:设置负载权重,默认值是1,nginx默认的负载算法是wrr
  • max_conns=_number_:限制代理到上游服务器之间的连接数。默认值为0,即不限制
  • max_fails=_number_:定义代理与上游服务器通信最大错误尝试次数。默认值为1,为0则禁用尝试计数
  • fail_timeout=_time_:心跳检测间隔,代理尝试与上游服务器通信的时间,超过设定值判断为错误max_fails则计数+1。默认值为10s
  • backup:定义为备用服务器,当其他上游服务器不可用时才会使用。注意该指令不能和hash/ip_hash/random算法一起使用
  • down:下线上游服务器,即代理不分配流量至该服务器
  • resolve:如果server指令接的是域名,则可以配置该指令来实现动态切换上游服务器,需要提前配置reslover指令
  • slow_start=_time_:设置慢启动时间

upstream块内的其他指令

  • keepalive:代理与后端服务器的长链接数,减少连接创建与销毁的代销
  • keepalive_requests:每个长链接最大处理请求数,超过阈值后closed该长链接,另创建新的链接
  • keepalive_time:每个活动中的长链接的存活时间,超过阈值后closed该长链接,达到此时间后,将在后续请求处理后关闭连接
  • keepalive_timeout:每个长链接的超时时间,在此期间与上游服务器的空闲保持连接将保持打开状态

负载均衡样例

简单样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
upstream backend {
# 30s内检查心跳发送两次包,未回复就代表该机器宕机,请求分发权重比为1:2
server 192.168.44.131:8080 weight=100 max_fails=2 fail_timeout=30s;
server 192.168.44.131:8090 weight=200 max_fails=2 fail_timeout=30s;
# 长连接数
keepalive 32;
# 每个长连接提供的最大请求数
keepalived_requests 100;
# 每个长连接没有新的请求时,保持的最长时间
keepalive_timeout 60s;
}
server {
######## 略
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 请求交给名为backend的upstream上
proxy_pass http://nginx_boot;
}
}

websocket上游服务器样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
upstream qa_backend {
hash $remote_addr consistent;
server 192.168.44.178:8080;
server 192.168.44.179:8080;
}

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

server {
####### 略
location / {
proxy_pass http://qa_backend;
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 30s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "$connection_upgrade";
}
}

nginx负载均衡算法

轮询

每个请求按时间顺序逐一分配到上游服务器

1
2
3
4
upstream qa_backend {
server 192.168.44.178:8080;
server 192.168.44.179:8080;
}

加权轮询

weight 的值越大,分配到的访问概率越高

1
2
3
4
upstream qa_backend {
server 192.168.44.178:8080 weight 10;
server 192.168.44.179:8080 weight 20;
}

ip_hash

每个请求按访问 IP 的哈希结果分配,使来自同一个 IP 的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的 session 共享问题

1
2
3
4
5
upstream qa_backend {
ip_hash
server 192.168.44.178:8080;
server 192.168.44.179:8080;
}

fair

需要配第三方插件模块 upstream_fair 模块,对比 weight、ip_hash 更加智能的负载均衡算法,fair 算法可以根据页面大小和加载时间长短智能地进行负载均衡,响应时间短的优先分配

1
2
3
4
5
upstream qa_backend {
server 192.168.44.178:8080 weight 10;
server 192.168.44.179:8080 weight 20;
fair;
}

url_hash

需要安装nginx的hash软件包,按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率

1
2
3
4
5
6
upstream qa_backend {
server 192.168.44.178:8080;
server 192.168.44.179:8080;
hash $request_uri;
hash_method crc32;
}

upstream中可用的变量

  • $upstream_addr
  • $upstream_bytes_received
  • $upstream_bytes_sent
  • $upstream_cache_status
  • $upstream_connect_time
  • $upstream_cookie_name
  • $upstream_header_time
  • $upstream_http_name
  • $upstream_queue_time
  • $upstream_response_length
  • $upstream_response_time
  • $upstream_status

官方文档:https://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream