负载均衡

  • 当我们的应用单例不能支撑用户请求时, 此时就需要扩容, 从一台服务器扩容到两台、 几十台、 几百台, 我们需要一个入口, 将客户端请求均衡分布在后台的多个服务器上。
  • 负载均衡在服务端开发中算是一个比较重要的特性, nginx 提供的负载均衡可以实现上游服务器的负载均衡、 故障转移、 失败重试、 容错、 健康检查, 当某些上游服务器出现问题时, 可以将请求转到其它的上游服务器从而保障高可用。

负载均衡使用

  • 第一步我们需要给 nginx 配置上游服务器, 即负载均衡到真实的处理业务的服务器 通过在 http 指令下配置 upstream 即可。
  • 指定一组上游服务器地址, 其中, 地址可以是域名、 IP地址。 可以在域名或者IP地址后加端口, 如果不加端口, 那么默认使用80端口。
语法: 
upstream name { ... }
默认值: —
上下文: http

upstream 指令当中包含server指令
语法: server address [parameters];
默认值: —
上下文: upstream

例子:
#当访问Nginx时, 会将请求反向代理到backend配置的upstream server。
upstream backend {
	server backend1.example.com weight=5;
	server backend2.example.com:8080;
} 
server {
	location / {
		proxy_pass http://backend;
	}
}

upstream 指令当中包含server指令的参数

可以定义下面的参数:

  • weight=number 设定服务器的权重, 默认是1, 权重越大被访问机会越大, 要根据机器的配置情况来配置
  • max_fails=number 设定Nginx与服务器通信的尝试失败的次数。 在fail_timeout参数定义的时间段内, 如果失败的次数达到此值, Nginx就认为服务器不可用。 在下一个fail_timeout时间段, 服务器不会再被尝试。 失败的尝试次数默认是1。
    可以通过指令proxy_next_upstream 和memcached_next_upstream来配置什么是失败的尝试。 默认配置时, http_404状态不被认为是失败的尝试。
  • fail_timeout=time
    统计失败尝试次数的时间段。 在这段时间中, 服务器失败次数达到指定的尝试次数, 服务器就被认为不可用。 默认情况下, 该超时时间是10秒。
  • backup
    标记为备用服务器。 当主服务器不可用以后, 请求会被传给这些服务器, 配置这个指令可以实现故障转移。
  • down
    标记服务器永久不可用, 可以跟ip_hash指令一起使用。

负载均衡的方法

nginx支持以下负载均衡机制:

  1. 轮询
    默认轮询方式
    每一个来自网络中的请求, 轮流分配给内部的服务器, 从1到N然后重新开始。 此种负载均衡算法适合服务器组内部的服务器都具有相同的配置并且平均服务请求相对均衡的情况。
  2. 加权轮询
    通过 weight 参数控制权重
    根据服务器的不同处理能力, 给每个服务器分配不同的权值, 使其能够接受相应权值数的服务请求。 例如: 服务器A的权值被设计成1, B的权值是3, C的权值是6, 则服务器A、 B、 C将分别接受到10%、 30%、 60%的服务请求。
    此种均衡算法能确保高性能的服务器得到更多的使用率, 避免低性能的服务器负载过重。
  3. IP Hash
    在 upstream 当中配置 ip_hash ;
    这种方式通过生成请求源IP的哈希值, 并通过这个哈希值来找到正确的真实服务器。 这意味着对于同一主机来说他对应的服务器总是相同。
    使用这种方式, 你不需要保存任何源IP。 将客户端会话"沾住"或者"持久化", 以便总是能选择特定服务器, 那么可以使用 ip-hash 负载均衡机制。
    使用 ip-hash 时, 客户端IP地址作为 hash key 使用, 用来决策选择服务器集群中的哪个服务器来处理这个客户端的请求。
    这个方法保证从同一个客户端发起的请求总是定向到同一台服务器, 除非服务器不可用。
  4. 最少连接数
    在 upstream 当中配置 least_conn 实现最少连接数
    客户端的每一次请求服务在服务器停留的时间可能会有较大的差异, 随着工作时间加长, 如果采用简单的轮循或随机均衡算法, 每一台服务器上的连接进程可能会产生极大的不同, 并没有达到真正的负载均衡。
    最少连接数均衡算法对内部中需负载的每一台服务器都有一个数据记录, 记录当前该服务器正在处理的连接数量, 当有新的服务连接请求时, 将把当前请求分配给连接数最少的服务器, 使均衡更加符合实际情况, 负载更加均衡。

失败重试

通过配置上游服务器 max_fails 和 fail_timeout, 指定每个上游服务器, 当 fail_timeout 时间内失败了 max_fails 次请求, 则认为该上游服务器不可用/不存活, 然后这段时间将不会访问这台上游服务器, fail_timeout 时间后会再次进行重试。
max_fails=2 fail_timeout=30s 这2个一起搭配使用, 表示: 当失败2次的时候, 就停止使30秒

proxy_next_upstream 指令

在nginx的配置文件中, proxy_next_upstream 项定义了什么情况下进行重试

语法: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 http_503 | http_504 |http_404 | off ...;
默认值: proxy_next_upstream error timeout;
上下文: http, server, location

其中

error 表示和后端服务器建立连接时, 或者向后端服务器发送请求时, 或者从后端服务器接收响应头时, 出现错误。
timeout 表示和后端服务器建立连接时, 或者向后端服务器发送请求时, 或者从后端服务器接收响应头时, 出现超时。
invalid_header 表示后端服务器返回空响应或者非法响应头
http_500 表示后端服务器返回的响应状态码为500
.............
off 表示停止将请求发送给下一台后端服务器

重试不能无限制进行,因此,需要如下两个指令控制重试次数和重试超时时间。

proxy_next_upstream_tries number: 设置重试次数, 默认0表示不限制, 注意此重试次数指的是所有请求次数(包括第一次和之后的重试次数之和) 。

proxy_next_upstream_timeout time: 设置重试最大超时时间, 默认0表示不限制。

即在 proxy_next_upstream_timeout 时间内允许 proxy_next_upstream_tries 次重试。 如果超过了其中一个设置, 则 Nginx 也会结束重试并返回客户端响应(可能是错误码) 。

proxy_send_timeout 后端服务器数据回传时间(代理发送超时时间)
proxy_read_timeout 连接成功后, 后端服务器响应时间(代理接收超时时间)
proxy_connect_timeout nginx连接后端的超时时间, 一般不超过75s
backup(故障转移)

标记为备用服务器。 当主服务器不可用以后, 请求会被传给这些服务器。

  • down
    标记服务器永久不可用, 可以跟ip_hash指令一起使用。