nginx健康检查源码分析

源码路径:

nginx_upstream_check_module/ngx_http_upstream_check_module.c at master · yaoweibin/nginx_upstream_check_module · GitHubHealth checks upstreams for nginx. Contribute to yaoweibin/nginx_upstream_check_module development by creating an account on GitHub.https://github.com/yaoweibin/nginx_upstream_check_module/blob/master/ngx_http_upstream_check_module.c

源码分析:

ngx_uint_t

ngx_http_upstream_check_add_peer(ngx_conf_t *cf,

    ngx_http_upstream_srv_conf_t *us,

    ngx_addr_t *peer_addr

    )

{

...

    // 获取健康检查server块配置

    ucscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_check_module);

    // 获取peers

    ucmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_check_module);

    peers = ucmcf->peers;

    peer = ngx_array_push(&peers->peers);

    // 赋值peer

    ngx_memzero(peer, sizeof(ngx_http_upstream_check_peer_t));

    peer->index = peers->peers.nelts - 1;

    peer->conf = ucscf;

    peer->upstream_name = &us->host;

    peer->peer_addr = peer_addr;

...

}

peer全部初始化后启动健康检查

static ngx_int_t

ngx_http_upstream_check_init_process(ngx_cycle_t *cycle)

{

    return ngx_http_upstream_check_add_timers(cycle);

}

static ngx_int_t

ngx_http_upstream_check_add_timers(ngx_cycle_t *cycle)

{

...

    // check_peers_ctx 全局变量

    peers = check_peers_ctx;

    for (i = 0; i < peers->peers.nelts; i++) {

    ngx_http_upstream_check_add_timer(&peer[i], ucscf->check_type_conf, t, cycle->log);  

}

...

}

static ngx_int_t

ngx_http_upstream_check_add_timer(ngx_http_upstream_check_peer_t *peer,

    ngx_check_conf_t *check_conf, ngx_msec_t timer, ngx_log_t *log)

{

...

    peer->check_ev.handler = ngx_http_upstream_check_begin_handler;

    peer->check_ev.log = log;

    peer->check_ev.data = peer;

    peer->check_ev.timer_set = 0;

    peer->check_timeout_ev.handler = ngx_http_upstream_check_timeout_handler;

    peer->check_timeout_ev.log = log;

    peer->check_timeout_ev.data = peer;

    peer->check_timeout_ev.timer_set = 0;

    if (check_conf->need_pool) {

        peer->pool = ngx_create_pool(ngx_pagesize, log);

        if (peer->pool == NULL) {

            return NGX_ERROR;

        }

    }

    peer->send_handler = check_conf->send_handler;

    peer->recv_handler = check_conf->recv_handler;

    peer->init = check_conf->init;

    peer->parse = check_conf->parse;

    peer->reinit = check_conf->reinit;

    ngx_add_timer(&peer->check_ev, timer);

    /* TODO: lock */

    peer->shm->ref++;

    return NGX_OK;

...

}

static char *

ngx_http_upstream_check_init_main_conf(ngx_conf_t *cf, void *conf)

{

    return ngx_http_upstream_check_init_shm(cf, conf);

}

//check_peers_ctx全局变量初始化

static char *

ngx_http_upstream_check_init_shm(ngx_conf_t *cf, void *conf)

{

    check_peers_ctx = ucmcf->peers;

}

upstream_srv_conf与upstream_check_conf的peer起着不同的作用

两个数组一个是用于和后端upstream连接,一个用于健康检查。

选择peer upstream流程

ngx_int_t

ngx_http_upstream_init_round_robin(ngx_conf_t *cf,

    ngx_http_upstream_srv_conf_t *us)

{

...

    us->peer.init = ngx_http_upstream_init_round_robin_peer;

...

}

// 函数两个参数比较重要,第一个为熟悉的request_t结构体

//第二个参数为upstream server块配置结构体

ngx_int_t

ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,

    ngx_http_upstream_srv_conf_t *us)

{

...

    

    ngx_uint_t n;
    ngx_http_upstream_rr_peer_data_t *rrp;
    
    // 创建请求的负载均衡数据块
    rrp = r->upstream->peer.data;
    if (rrp == NULL) {
        rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t));
        if (rrp == NULL) 
            return NGX_ERROR;
        

        //保存请求负载均衡数据的地址
        r->upstream->peer.data = rrp;
    }

    //upstream块的后端集群

    rrp->peers = us->peer.data;
    rrp->current = NULL;

    //后端peer数量

    n = rrp->peers->number;


    // 如果存在备份集群,且其服务器数量超过n
    if (rrp->peers->next && rrp->peers->next->number > n) {
        n = rrp->peers->next->number;
    }

    //rrp->tried指向后端服务器的位图,每一位代表一台后端的状态,0表示可用,1表示不可用
    //如果后端数较少,直接使用rrp->data作为位图。如果后端数较多,则需要申请一块内存
   
    if (n <= 8 *sizeof(uintptr_t)) {
        rrp->tried = &rrp->data;
        rrp->data = 0;
    } else {
        n = ( n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); // 向上取整
        rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
        if (rrp->tried == NULL) {
            return NGX_ERROR;
        }
    }

    //指定peer.get,用于从集群中选取一台后端服务器

    r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;

    //指定peer.free,当不用该后端时,进行数据的更新
    r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;

    //指定peer.tries,是请求允许尝试的后端服务器个数
    r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers);

...

}

ngx_int_t

ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)

{

...

    ngx_http_upstream_rr_peer_data_t  *rrp = data;

    peers = rrp->peers;

    peer = ngx_http_upstream_get_peer(rrp);

    pc->sockaddr = peer->sockaddr;

    pc->socklen = peer->socklen;

    pc->name = &peer->name;

    pc->host = &peer->host;

...

}

static ngx_http_upstream_rr_peer_t *

ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)

{

    // 算法选出peer

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值