Nginx系列(四):upstream模块

配置解析阶段

在这里插入图片描述

init_main阶段

在init_upstream时,因为upstream的每个server在DNS后可能存在多个IP,所以init_upstream生成的peer是所有解析结果的集合,例如,一个server的权值为10,解析后由5个IP,那么,将申请5个rrp,每个的权值都是10。

调用kcf->original_init_upstream(ngx_http_upstream_init_round_robin):
生成ngx_http_upstream_rr_peers_t结构体,全局,根据所有后端服务器信息,生成一张表,包含地址信息、权重、最大连接数、最大失败数等。

调用uscf->peer.init_upstream(ngx_http_upstream_init_keepalive):
初始化cache和free队列,其中cache保存已建立的连接,全局,free保存已释放的连接,申请max_cached个节点,挂在free队列。

连接初始化阶段

调用kcf->original_init_peer(ngx_http_upstream_init_round_robin_peer):
初始化ngx_http_upstream_rr_peer_data_t结构体(r->upstream->peer.data,最终保存在kp->data),请求私有数据,用户保存所有可用后端peers、目前选择后端current、后端是否连接过的位图,初始化get和free方法。

typedef struct {
    ngx_uint_t                      config;
    ngx_http_upstream_rr_peers_t   *peers; //指向全局的rrps
    ngx_http_upstream_rr_peer_t    *current; //目前使用的rrp
    uintptr_t                      *tried; //位图指针,位数为rrp的个数,代表该连接是否尝试过这个rrp
    uintptr_t                       data; //位图
} ngx_http_upstream_rr_peer_data_t;

调用uscf->peer.init(ngx_http_upstream_init_keepalive_peer)
初始化ngx_http_upstream_keepalive_peer_data_t结构体(kp)(r->upstream->peer.data),请求私有数据,初始化get和free方法。

typedef struct {
    ngx_http_upstream_keepalive_srv_conf_t  *conf; //配置
    ngx_http_upstream_t               *upstream; //保存连接的upstream结构体
    void                              *data; //保存ngx_http_upstream_rr_peer_data_t
    ngx_event_get_peer_pt              original_get_peer;
    ngx_event_free_peer_pt             original_free_peer;
} ngx_http_upstream_keepalive_peer_data_t;

连接获取阶段

调用kp->original_get_peer(ngx_http_upstream_get_round_robin_peer):
(1)获取最优后端;
(2)当最优后端获取失败时,尝试从backup中获取后端。

struct ngx_http_upstream_rr_peer_s {
    ngx_str_t                       server; //解析前域名
    ngx_int_t                       current_weight; //该rrp当前权值
    ngx_int_t                       effective_weight; //该rrp当前有效权值
    ngx_int_t                       weight; //定权值
    ngx_uint_t                      conns; //该rrp目前连接数
    ngx_uint_t                      max_conns; //该rrp最大连接数
    ngx_uint_t                      fails; //“一段时间”内失败次数
    time_t                          accessed; //最近一次失败时间
    time_t                          checked;  //用于检查是否超过了“一段时间”,上一次判断时间
    ngx_uint_t                      max_fails; //最大失败次数
    time_t                          fail_timeout; //“一段时间”
    ngx_uint_t                      down; //该server不参与负载均衡
};

round_robin的负载均衡算法:A、B、C三个rrp,weight分别为1、2、3,那么初始effective_weight也是1、2、3,current_weight初始为0,当进行一次负载均衡算法后,current_weight分别为1、2、3,C的current_weight最大为3,此时将C选为best,并将C的current_weight
= 3 - (1 + 2 + 3) = -3,那么后续的负载均衡,即使每次给C加上current_weight = 3,其current_weight也不是所有rrp中最大值。可以理解为current_weight是一个排序好的队列,每次选取best都是取队列头,同时减小其current_weight并重新排序。当某个rrp后端连接失败时,其effective_weight也会被减小。
当fails大于max_fails时,该rrp将不可用,直到不可用持续时间超过fail_timeout。另外,每worker都拥有自己的rrps内存空间,即不使用共享内存,所以类似current_weight、fails数据每worker都不相同,且keepalive指定的数量为每worker数量。

调用r->upstream->peer.get(ngx_http_upstream_get_keepalive_peer):
(1)从cache队列中查找最优后端是否有已经建立的连接。

连接释放阶段

调用r->upstream->peer.free(ngx_http_upstream_free_keepalive_peer):
(1)如果free队列为空,那么从cache中获取队尾节点,用于存储该连接,原节点中缓存的连接将被释放。注意,这里keepalive节点数并不是该upstream支持的连接上限,只是已建立的、未被使用的上游连接缓存数。
(2)如果free队列不为空。则从free队列获取节点。

调用kp->original_free_peer(ngx_http_upstream_free_round_robin_peer):
(1)如果该后端peer在连接时失败,则修改peer的部分参数值,包括失败次数fails、有效权重effective_weight等;
(2)减少peer中连接个数conns。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值