使用 NGINX 做 HTTP 负载均衡

Introduction

负载均衡一般被用来优化资源利用率、最大化吞吐量、降低延迟和容错配置。

Nginx 可以作为一种十分有效的 HTTP 负载均衡工具来使用,通过 nginx 的负载均衡分发流量到不同的应用服务器,可以提升 web 应用的性能、伸展性和可靠性。

Load balancing methods

Nginx 支持下面几种负载均衡策略:

  • round-robin(轮询) — 根据轮询分发请求到不同的服务器
  • least-connected(最少连接) — 将最新请求分发到活动连接最少的服务器
  • ip-hash(ip 哈希) — 用一个哈希函数来决定最新请求应该被分发到哪一个服务器(基于客户端的 ip).

Default load balancing configuration

举个栗子
最简单的 nginx 负载均衡配置看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}

server {
listen 80;

location / {
proxy_pass http://myapp1;
}
}
}

在上面的例子中,有三个一样的应用跑在 srv1-srv3 服务器上。当我们没有配置任何负载均衡策略的时候,nginx 会采用默认的负载均衡策略——轮询。所有的请求都被代理到 myapp1 服务器群,然后 nginx 根据 HTTP 负载均衡分发请求。

Nginx 反向代理包括对 HTTP, HTTPS, FastCGI, uwsgi, SCGI, and memcached 的负载均衡策略。

如果想要配置 HTTPS 的负载均衡,只需要使用 “https” 协议就可以了。

当设置 FastCGI, uwsgi, SCGI, or memcached 的负载均衡策略时,只需要使用分别使用 fastcgi_pass , uwsgi_pass , scgi_pass , and memcached_pass 指令就可以了。

Least connected load balancing

另一种负载均衡策略是最少连接。当一些连接完成所需时间更长时,使用最少连接策略可以更公平地控制均衡负载。

当使用最少连接负载均衡策略时,nginx 会把新请求分发给不太忙的服务器,从而避免分发过多的请求给忙碌的服务器造成过载。

只要把 least_conn 指令配置成服务器群配置的一部分 nginx 就会采用最少连接负载均衡策略:

1
2
3
4
5
6
upstream myapp1 {
least_conn;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}

Session persistence

值得注意的是,轮询和最少连接负载均衡可能会把来自同一个客户端的请求分发到不同的服务器。它们不保证同一个客户端的请求会分发到同样的服务器上。

如果需要把同一个客户端请求分发到同样的服务器的,换句话说就是让客户端的会话“持续”而又“有粘性”地选择连接到特定的服务器,那么可以使用 ip 哈希负载均衡策略。

ip 哈希负载均衡策略会使用客户端的 ip 地址作为哈希的 key 来决定选择服务器群中某台服务器来处理客户端的请求。这种方式确保来自同一台客户端的请求会分发到同一台服务器上,除非这台服务器处于不可用状态。

只需要把 ip_hash 指令添加到服务器群(upstream)配置中就可以使用 ip 哈希负载均衡策略了:

1
2
3
4
5
6
upstream myapp1 {
ip_hash;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}

Weighted load balancing

除了上面三种负载均衡策略,我们还可以通过配置服务器权重来更深入地影响 nginx 负载均衡算法。

在上面几个例子中,并没有配置服务器权重,那么这意味着 nginx 在进行负载均衡计算的时候会同等地看待配置的服务器。

假如有足够的请求,并且请求的处理模式一致而且完成的速度足够快,那么轮询负载均衡策略意味着根据基本上一致的权重来分发请求到服务器上。

当一个服务器被配置了权重的时候,权重值就会被当做负载均衡算法决策因素的一部分。

1
2
3
4
5
upstream myapp1 {
server srv1.example.com weight=3;
server srv2.example.com;
server srv3.example.com;
}

当采用上面的配置的时候,每5个请求将会如下方式分发到应用服务器上:
三个请求会分发到 srv1,一个会分发到 srv2,另一个会分发到 srv3

权重式负载均衡策略可以在最近版本的 nginx 运用到最少连接和 ip hash 负载均衡策略中。

Health checks

nginx 的反向代理实现包括了被动的 health checks 策略。当某个特定的服务器由于错误而响应失败时,nginx 会把这台服务器标记为 failed,并且会在一短时间内不把后续的请求分发到这台服务器上。

max_fails 指令可以设置允许的在 fail_timeout 时间内尝试与服务器交互的最大连续失败次数。max_fails 默认为 1。当 max_fails 设置成 0 的时候,这台服务器的 health checks 功能将会被禁用。fail_timeout 参数同时也定义了服务器被标记为 failed 的时长。服务器出错并且经过 fail_timeout 的时间间隔之后, nginx 会开始优雅地用活跃的客户端请求来探测出错的服务器。如果这些探测成功了,那么这台服务器将会被标记为正常。

强烈建议读完 max_failsfail_timeout 的链接。

Further reading

另外,还有很多的命令以及参数可以控制 nginx 的负载均衡,例如 proxy_next_upstream , backup , down , and keepalive 。同时,可以通过阅读 reference documentation 来获取更多信息。

Reference links

http://nginx.org/en/docs/http/load_balancing.html
http://nginx.org/en/docs/http/ngx_http_upstream_module.html
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash
http://blog.csdn.net/xiajun07061225/article/details/9318871
http://blog.csdn.net/xiajun07061225/article/details/9318871

本文链接 http://sfyumi.github.io/2016/03/15/Using-nginx-as-HTTP-load-balancer/
作者 sfyumi
译自 Using nginx as HTTP load balancer