[nginx] 负载均衡策略--RobinRound

  • 负载均衡:将负载尽量均衡的分摊到多个不同的后端服务单元,以保证服务的可用性和可靠性;
  • upstreamproxy和upstream模块

nginx默认采用robin round策略,详情参考Nginx学习之十二-负载均衡-加权轮询策略剖析

一、主体结构

upstream backend {
    server 192.168.0.1:8080 weight=2 max_fails=3;
    server 192.168.0.2:8080 weight=1 max_fails=3;
}
  • 解析server项,ngx_http_upstream_server(),指令详情参考:Server
  • upstream配置加载后的初始化函数ngx_http_upstream_init_main_conf(),调用RobinRound初始化函数ngx_http_upstream_init_round_robin()
  • ngx_http_upstream_init_round_robin(),初始化upstream中的每个server为peer,填充peer的权重、最大失败次数、超时、是否失败,并设置请求初始化函数us->peer.init = ngx_http_upstream_init_round_robin_peer
  • 每次请求都会调用us->peer.init(),实际调用ngx_http_upstream_init_round_robin_peer(),创建tried和tries变量,其中tried表示peer已使用的bit图,tries表示本次请求获取后端的次数。并设置了peer的获取、释放句柄。
    该执行入口在ngx_http_upstream_init_request()upstream请求初始化函数尾部;
  • 获取后端服务器ngx_http_upstream_get_round_robin_peer(),负载均衡策略获取一个后端务器返回,入口函数为ngx_http_upstream_connect() ==> ngx_event_connect_peer()
  • 当遇到错误或与后端通信结束,需要释放后端服务器ngx_http_upstream_free_round_robin_peer(),记录一些状态,以供若遇到错误时可以获取下一个后端服务器。入口函数为ngx_http_upstream_next()获取下一个peer或ngx_http_upstream_finalize_request()upstream结束请求。

二、获取peer

获取一个后端服务器,若后端服务器只有一个,直接返回即可,但若有多个供选择,则调用ngx_http_upstream_get_peer()。RoundRobin用tried位图记录后端服务器是否访问过,uintptr_t数组,每个元素8bit记录8个服务器,所以服务器i的状态表示为

n = i / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
if (tried[n] & m) {
    // 表示i服务器已访问过
}

负载均衡策略为Weighted Round Robin,遍历所有可用服务器(非down,fails < max_fails),权重累加为total,同时挑出权重最大的peer,并将该peer的当时权重减去total,返回该peer。

三、释放peer

释放正在使用的后端服务器,如果只有一个后端直接释放即可,若有多个后端则

// 如果请求出现异常,则会进入该分支
if (state & NGX_PEER_FAILED) {
    now = ngx_time();

    peer->fails++;
    peer->accessed = now;
    peer->checked = now;

    if (peer->max_fails) {
        peer->effective_weight -= peer->weight / peer->max_fails;
    }

    if (peer->effective_weight < 0) {
        peer->effective_weight = 0;
    }
} else {  // 如果请求正常关闭
    if (peer->accessed < peer->checked) {
        peer->fails = 0;
    }
}

if (pc->tries) {
    pc->tries--;
}

当该peer访问失败时,会使失败计数器加1,记录当时时间到时accessed、checked变量:

  • accessed,表示该peer最近访问失败时的时间;
  • checked,表示该peer最近访问失败时的时间或从“死”到“活”时的活时间,如果checked > accessed,则会对失败计数器清零。

所以有如下场景:后端服务器A失败次数达到max_fails,并时间checked未超过fail_timeout,则该peer不会在候选列表(if … continue)。冷却时间到,该peer又回到候选列表中,且被选中则更新checked。若peer又“活”过来能进行正常请求,则在peer释放环节checked>accessed将失败计数器清零,恢复正常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值