源码路径:
源码分析:
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; //保存请求负载均衡数据的地址 //upstream块的后端集群 rrp->peers = us->peer.data; //后端peer数量 n = rrp->peers->number;
//rrp->tried指向后端服务器的位图,每一位代表一台后端的状态,0表示可用,1表示不可用 //指定peer.get,用于从集群中选取一台后端服务器 r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer; //指定peer.free,当不用该后端时,进行数据的更新 //指定peer.tries,是请求允许尝试的后端服务器个数 ... } 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 } |