Nginx學習之十二-負載均衡-加權輪詢策略剖析
阿新 • • 發佈:2019-01-26
函式的完整程式碼如下(ngx_http_upstream_round_robin.c):typedef struct ngx_http_upstream_rr_peers_s ngx_http_upstream_rr_peers_t; struct ngx_http_upstream_rr_peers_s { ngx_uint_t number;//佇列中伺服器數量 /* ngx_mutex_t *mutex; */ ngx_uint_t total_weight;//所有伺服器總權重 unsigned single:1;//為1表示後端伺服器總共只有一臺,用於優化,此時不需要再做選擇 unsigned weighted:1;//為1表示總的權重值等於伺服器數量 ngx_str_t *name; ngx_http_upstream_rr_peers_t *next;//後備伺服器列表掛載在這個欄位下 ngx_http_upstream_rr_peer_t peer[1]; };
//函式:初始化伺服器負載均衡表 //引數: //us:ngx_http_upstream_main_conf_t結構體中upstreams陣列元素 ngx_int_t ngx_http_upstream_init_round_robin(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { ngx_url_t u; ngx_uint_t i, j, n, w; ngx_http_upstream_server_t *server; ngx_http_upstream_rr_peers_t *peers, *backup; //回撥指標設定 us->peer.init = ngx_http_upstream_init_round_robin_peer; //伺服器陣列指標不為空 if (us->servers) { server = us->servers->elts; n = 0; w = 0; //遍歷所有伺服器 for (i = 0; i < us->servers->nelts; i++) { //是後備伺服器,跳過 if (server[i].backup) { continue; } //伺服器地址數量統計 n += server[i].naddrs; //總的權重計算 w += server[i].naddrs * server[i].weight; } if (n == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no servers in upstream \"%V\" in %s:%ui", &us->host, us->file_name, us->line); return NGX_ERROR; } //為非後備伺服器分配空間 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); if (peers == NULL) { return NGX_ERROR; } //非後備伺服器列表頭中各屬性設定 peers->single = (n == 1); peers->number = n; peers->weighted = (w != n); peers->total_weight = w; peers->name = &us->host; n = 0; //後備伺服器列表中各伺服器項設定 for (i = 0; i < us->servers->nelts; i++) { for (j = 0; j < server[i].naddrs; j++) { if (server[i].backup) { continue; } peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; peers->peer[n].socklen = server[i].addrs[j].socklen; peers->peer[n].name = server[i].addrs[j].name; peers->peer[n].max_fails = server[i].max_fails; peers->peer[n].fail_timeout = server[i].fail_timeout; peers->peer[n].down = server[i].down; peers->peer[n].weight = server[i].weight; peers->peer[n].effective_weight = server[i].weight; peers->peer[n].current_weight = 0; n++; } } //非後備伺服器列表掛載的位置 us->peer.data = peers; /* backup servers */ //後備伺服器 n = 0; w = 0; for (i = 0; i < us->servers->nelts; i++) { if (!server[i].backup) { continue; } //後備伺服器地址數量統計 n += server[i].naddrs; //後備伺服器總權重計算 w += server[i].naddrs * server[i].weight; } if (n == 0) { return NGX_OK; } //後備伺服器列表地址空間分配 backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); if (backup == NULL) { return NGX_ERROR; } peers->single = 0; //後備伺服器列表頭中各屬性設定 backup->single = 0; backup->number = n; backup->weighted = (w != n); backup->total_weight = w; backup->name = &us->host; n = 0; //後備伺服器列表中各伺服器項設定 for (i = 0; i < us->servers->nelts; i++) { for (j = 0; j < server[i].naddrs; j++) { if (!server[i].backup) { continue; } backup->peer[n].sockaddr = server[i].addrs[j].sockaddr; backup->peer[n].socklen = server[i].addrs[j].socklen; backup->peer[n].name = server[i].addrs[j].name; backup->peer[n].weight = server[i].weight; backup->peer[n].effective_weight = server[i].weight; backup->peer[n].current_weight = 0; backup->peer[n].max_fails = server[i].max_fails; backup->peer[n].fail_timeout = server[i].fail_timeout; backup->peer[n].down = server[i].down; n++; } } //後備伺服器掛載 peers->next = backup; return NGX_OK; } //us引數中伺服器指標為空,例如使用者直接在proxy_pass等指令後配置後端伺服器地址 /* an upstream implicitly defined by proxy_pass, etc. */ if (us->port == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no port in upstream \"%V\" in %s:%ui", &us->host, us->file_name, us->line); return NGX_ERROR; } ngx_memzero(&u, sizeof(ngx_url_t)); u.host = us->host; u.port = us->port; //IP地址解析 if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "%s in upstream \"%V\" in %s:%ui", u.err, &us->host, us->file_name, us->line); } return NGX_ERROR; } n = u.naddrs; peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); if (peers == NULL) { return NGX_ERROR; } peers->single = (n == 1); peers->number = n; peers->weighted = 0; peers->total_weight = n; peers->name = &us->host; for (i = 0; i < u.naddrs; i++) { peers->peer[i].sockaddr = u.addrs[i].sockaddr; peers->peer[i].socklen = u.addrs[i].socklen; peers->peer[i].name = u.addrs[i].name; peers->peer[i].weight = 1; peers->peer[i].effective_weight = 1; peers->peer[i].current_weight = 0; peers->peer[i].max_fails = 1; peers->peer[i].fail_timeout = 10; } us->peer.data = peers; /* implicitly defined upstream has no backup servers */ return NGX_OK; }