您的位置:首页 > 运维架构 > Nginx

Nginx负载均衡代码之加权轮询

2016-01-07 10:40 477 查看
1. 简介:

       加权轮询以轮询的方式对不同的服务器进行调度,并不记录当前服务器的状态,是一种无状态的调度方法。在Nginx中,当调度后的服务器执行失败后,会通过对权重的控制来简单控制服务器状态。

2. 主要变量:

        控制权重的主要三个变量:

1) weight:表示配置的权重原始值,不参与实际调度过程,主要用于当服务器执行失败以后的权重衰减后恢复过程的最大值。

2) effect_weight:当前权重的有效值,初始化时设置为配置的权重值,当调度到的服务器执行失败后,有效权重会衰减,并在后续调度过程中逐渐恢复。

3) current_weight:当前的权重值,每轮调度时会加上有效权重,当服务器被选择时,会衰减一个值(本轮有效总权重)。

3. 轮询过程:

        轮询主要在两个函数中完成,ngx_http_upstream_get_round_robin_peer是主要入口,主要处理了单机场景以及轮询结果的返回。ngx_http_upstream_get_peer这个函数实现实际的轮询过程。

1) ngx_http_upstream_get_round_robin_peer:

if (peers->single) {
peer = &peers->peer[0];

if (peer->down) {
goto failed;
}
}
单机场景下如果唯一的一个服务器并没有下线,则直接返回该服务器。

failed:

if (peers->next) {

/* ngx_unlock_mutex(peers->mutex); */

ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers");

rrp->peers = peers->next;

n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
/ (8 * sizeof(uintptr_t));

for (i = 0; i < n; i++) {
rrp->tried[i] = 0;
}

rc = ngx_http_upstream_get_round_robin_peer(pc, rrp);

if (rc != NGX_BUSY) {
return rc;
}

/* ngx_lock_mutex(peers->mutex); */
}


主服务器群轮询失败,则在备用服务器中进行轮询。

2) ngx_http_upstream_get_peer:

轮询阶段,将对所有服务器进行遍历,对于已经尝试过、下线、失败次数超过限制的服务器不参与实际轮询过程。

轮询实际计算过程比较简单,单纯是对有效权重的计算和恢复。
peer->current_weight += peer->effective_weight;
total += peer->effective_weight;

if (peer->effective_weight < peer->weight) {
peer->effective_weight++;
}

if (best == NULL || peer->current_weight > best->current_weight) {
best = peer;
}
选出最优值以后需要更新最优值当前的权重,减去所有轮询节点的有效权重值总和。

if (best == NULL) {
return NULL;
}

i = best - &rrp->peers->peer[0];

rrp->current = i;

n = i / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));

rrp->tried
|= m;

best->current_weight -= total;

if (now - best->checked > best->fail_timeout) {
best->checked = now;
}

return best;


当服务器全都有效时(也没有超时等异常),所有服务器的有效权重值不变,每轮轮询时候的总有效权重都一样,基础权重值越大的服务器在当前权重为负数时恢复越快,重新激活的频率也越高。

4. Patch附带例子[2]:

a b c 对应权重为 5 1 1,期间有效权重不变。第一行为轮询完成,第二行为选择完成后的当前权重。

a b c

0 0 0 (initial state)

第一轮:

5 1 1 (a selected)

-2 1 1

第二轮:

3 2 2 (a selected)

-4 2 2

第三轮

1 3 3 (b selected)

1 -4 3

第四轮

6 -3 4 (a selected)

-1 -3 4

第五轮

4 -2 5 (c selected)

4 -2 -2

第六轮:

9 -1 -1 (a selected)

2 -1 -1

第七轮:

7 0 0 (a selected)

0 0 0

5. 参考文档:

[1]http://blog.csdn.net/zhangskd/article/details/50194069

[2]https://github.com/phusion/nginx/commit/27e94984486058d73157038f7950a0a36ecc6e35
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: