设为首页 - 加入收藏 焦点技术网
热搜:java
当前位置:首页 >

Nginx的负载均衡 - 加权轮询 (Weighted Round Robin) 下篇

2016-04-05 21:50:19.0 java  
导读:本文天下杰论给大家介绍 Nginx的负载均衡 - 加权轮询 (Weighted Round Robin) 下篇。 上篇blog讲述了加权轮询算法的原理、以及负载均衡模块中使用的数据结构,接着我们来看看加权轮询算法的具体实现。 。。。

上篇blog讲述了加权轮询算法的原理、以及负载均衡模块中使用的数据结构,接着我们来看看加权轮询算法的具体实现。

 指令的解析函数

 如果upstream配置块中没有指定使用哪种负载均衡算法,那么默认使用加权轮询。

也就是说使用加权轮询算法,并不需要特定的指令,因此也不需要实现指令的解析函数。

而实际上,和其它负载均衡算法不同(比如ip_hash),加权轮询算法并不是以模块的方式实现的,

而是作为Nginx框架的一部分。

 初始化upstream块 

在执行ngx_http_upstream_module的init main conf函数时,会遍历所有upstream配置块,调用它们

事先指定的初始化函数。对于一个upstream配置块,如果没有指定初始化函数,则调用加权轮询算法

提供的upstream块初始化函数 - ngx_http_upstream_init_round_robin。 

来看下ngx_http_upstream_module。

ngx_http_upstream_init_round_robin做的工作很简单:

指定请求的负载均衡初始化函数,用于初始化per request的负载均衡数据。

创建和初始化后端集群、备份集群。

 初始化请求的负载均衡数据

当收到一个请求后,一般使用的反向代理模块(upstream模块)为ngx_http_proxy_module,

其NGX_HTTP_CONTENT_PHASE阶段的处理函数为ngx_http_proxy_handler,在初始化upstream机制的

函数ngx_http_upstream_init_request中,调用在第二步中指定的peer.init,主要用于:

创建和初始化该请求的负载均衡数据块

指定r->upstream->peer.get,用于从集群中选取一台后端服务器(这是我们最为关心的)

指定r->upstream->peer.free,当不用该后端时,进行数据的更新(不管成功或失败都调用)

指定r->upstream->peer.tries,请求最多允许尝试这么多个后端

 选取一台后端服务器

 一般upstream块中会有多台后端,那么对于本次请求,要选定哪一台后端呢?

这时候第三步中r->upstream->peer.get指向的函数就派上用场了:

采用加权轮询算法,从集群中选出一台后端来处理本次请求。 选定后端的地址保存在pc->sockaddr,pc为主动连接。

函数的返回值:

NGX_DONE:选定一个后端,和该后端的连接已经建立。之后会直接发送请求。

NGX_OK:选定一个后端,和该后端的连接尚未建立。之后会和后端建立连接。

NGX_BUSY:所有的后端(包括备份集群)都不可用。之后会给客户端发送502(Bad Gateway)。

ngx_http_upstream_get_peer用于从集群中选取一台后端服务器。

 释放一台后端服务器

当不再使用一台后端时,需要进行收尾处理,比如统计失败的次数。

这时候会调用第三步中r->upstream->peer.get指向的函数。函数参数state的取值:

0,请求被成功处理

NGX_PEER_FAILED,连接失败

NGX_PEER_NEXT,连接失败,或者连接成功但后端未能成功处理请求

 

一个请求允许尝试的后端数为pc->tries,在第三步中指定。当state为后两个值时:

如果pc->tries不为0,需要重新选取一个后端,继续尝试,此后会重复调用r->upstream->peer.get。

如果pc->tries为0,便不再尝试,给客户端返回502错误码(Bad Gateway)。

判断后端是否可用

相关的变量的定义

ngx_uint_t fails; /* 一段时间内,已经失败的次数 */

time_t accessed; /* 最近一次失败的时间点 */

time_t checked; /* 用于检查是否超过了“一段时间” */

ngx_uint_t max_fails; /* 一段时间内,允许的最大的失败次数,固定值 */

time_t fail_timeout; /* “一段时间”的长度,固定值 */

相关变量的更新

accessed:释放peer时,如果发现后端出错了,则更新为now。

checked:释放peer时,如果发现后端出错了,则更新为now。选定该peer时,如果now - checked > fail_timeout,则更新为now。

fails:释放peer时,如果本次成功了且accessed < checked,说明距离最后一次失败的时间点,已超过fail_timeout了,清零fails。

 

上述变量的准备定义

fails并不是“一段时间内”的失败次数,而是两两间时间间隔小于“一段时间”的连续失败次数。

max_fails也不是“一段时间内”允许的最大失败次数,而是两两间的时间间隔小于“一段时间”的最大失败次数。

举例说明,假设fail_timeout为10s,max_fails为3。

10s内失败3次,肯定会导致接下来的10s不可用。

27s内失败3次,也可能导致接下来的10s不可用,只要3次失败两两之间的时间间隔为9s。

 

下图用来简要说明

 

 

(编辑: 天下杰论)

网友评论
相关文章