NGX的第三方负载均衡模块fair

本文介绍了NGX的第三方负载均衡模块fair,该模块基于服务器的状态和处理请求的统计,实现更公平的负载均衡。主要函数 ngx_http_upstream_fair_try_peer 负责尝试选择服务器,考虑服务器的空闲状态、失败次数和请求超时等因素。在初始化和节点选择过程中,fair模块会对权重进行排序并考虑服务器的繁忙程度。在IDLE和BUSY选择阶段,会根据不同的模式和条件选择最合适的服务器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

源码地址 https://github.com/gnosek/nginx-upstream-fair

一、模块简介:

        fair模块会对全局的请求进行统计,并根据该服务器空闲状态,及处理过的请求及所有请求数进行权衡,实现负载均衡。

二、主要函数:

2.1、主要函数:

2.1.1、ngx_http_upstream_fair_try_peer:

        该函数出现在idle调度和busy调度,会对一些符合条件的候选服务器中进行尝试。

        尝试首先会判断该候选服务器是否已经进行了尝试,在未尝试且服务器未下线的情况下,会判断服务器的失败次数,如果服务器失败的次数在允许范围之内,会根据服务器上一次接受请求的时间与当前时间的时间差,判断上一次请求是否已经超时,如果已经超时,会重置该服务器的失败次数,同时返回尝试成功。

    if (ngx_bitvector_test(fp->tried, peer_id))
        return NGX_BUSY;

    peer = &fp->peers->peer[peer_id];

    if (!peer->down) {
        if (peer->max_fails == 0 || peer->shared->fails < peer->max_fails) {
            return NGX_OK;
        }

        if (ngx_time() - peer->accessed > peer->fail_timeout) {
            ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] resetting fail count for peer %d, time delta %d > %d",
                peer_id, ngx_time() - peer->accessed, peer->fail_timeout);
            peer->shared->fails = 0;
            return NGX_OK;
        }
    }
2.1.2、ngx_http_upstream_fair_sched_score:

         该函数出现在busy调度,根据候选服务器当前承载的请求和所有服务器的总请求数进行计算,获得该候选服务器的状况评分。

         分数计算比较简单,用候选服务器的当前承载请求构成分数的高位,用候选服务器上一次请求和总请求之差(即空闲时间)的取反构成分数的低位,最后分数取小,即当前总请求数越少,优先级越高(暂不考虑weight),请求差越大,优先级越高。

SCHED_SCORE(ngx_upstream_fair_min(fs->nreq, SCHED_NREQ_MAX),
            ngx_upstream_fair_min(req_delta, SCHED_COUNTER_MAX));


#define SCHED_COUNTER_BITS 20
#define SCHED_NREQ_MAX ((~0UL) >> SCHED_COUNTER_BITS)
#define SCHED_COUNTER_MAX ((1 << SCHED_COUNTER_BITS) - 1)
#define SCHED_SCORE(nreq,delta) (((nreq) << SCHED_COUNTER_BITS) | (~(delta) & SCHED_COUNTER_MAX))
#define ngx_upstream_fair_min(a,b) (((a) < (b)) ? (a) : (b))

三、代码流程:

1、 初始化(ngx_http_upstream_init_fair):

1.1、服务器初始化(ngx_http_upstream_init_fair_rr):

       初始化的第一步是根据配置初始化所有配置的服务器,这里初始化和round robin初始化过程类似,初始化主备服务器,唯一的区别是fair会对权重进行排序。

        如果没有配置,会按照代理的模式去搜索相应的域名,对域名解析出来的的地址进行默认的初始化。

1.2、其余初始化:

        对共享内存进行相应的初始化,以及一些函数指针的初始化。

2、节点选择(ngx_http_upstream_choose_fair_peer):

        节点选择分为两步,一步选择idle(ngx_http_upstream_choose_fair_peer_idle),当没有任何可用的idle服务器时,将对所有busy的服务器进行选择(ngx_http_upstream_choose_fair_peer_busy)。

2.1、IDLE选择:

        IDLE选择的时候,对于有失败过的服务器,或者当前服务器所承载的请求数过多(大于权重,不是WM_IDLE模式时候有请求就算?),就放弃选择该服务器。

        当该服务器所承载的请求在可接受范围内,就会接着进行尝试,尝试部分和busy时候的尝试是相同的。

        尝试成功之后,对于不是WM_IDLE且关闭轮询的情况下,会返回这个尝试成功的服务器。

        在WM_IDLE和no_rr开启的情况下,会根据当前所承载的请求数来轮询选优,选择承载请求数最少的服务器。

2.2、BUSY选择:

        在BUSY选择过程中,如果是WM_PEAK模式,会保证当前服务器承载的请求数小于权重的值。

        接着对候选服务器进行尝试,尝试成功的话就去计算候选服务器的评分,并选择分数最低的服务器。

        如果是WM_DEFAULT模式,计算出来的评分还会进行加权,这里权重的计算会根据失败次数而变化。最后实际分数会除以权值。fails越多,weight越小,最终分数越高,优先级越低。

if (peer->max_fails) {
    ngx_uint_t mf = peer->max_fails;
    weight = peer->shared->current_weight * (mf - peer->shared->fails) / mf;
}
if (weight > 0) {
    sched_score /= weight;
}
2.3、后处理:

        成功选择一台服务器以后,把相应的标志位置位,如果是WM_DEFAULT模式,会减少当前权重,防止busy时候,权重没有变化而导致总是选择了相同的服务器(比如nreq处理较快,总是比其他少一些,在基础评分时候总是优于其他同权值的服务器,如果权值还是没有变化,最终选择的总是该服务器)。

    ngx_bitvector_set(fp->tried, best_idx);

    if (weight_mode == WM_DEFAULT) {
        ngx_http_upstream_fair_peer_t      *peer = &fp->peers->peer[best_idx];

        if (peer->shared->current_weight-- == 0) {
            peer->shared->current_weight = peer->weight;
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] peer %d expired weight, reset to %d", best_idx, peer->weight);
        }
    }
        选优之后还需要更新相应节点的请求数,最后接受的请求,总请求数

    peer->shared->last_req_id = fp->peers->shared->total_requests;
    ngx_http_upstream_fair_update_nreq(fp, 1, pc->log);
    peer->shared->total_req++;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值