nginx回源函数
init_upstream函数是peer调用的时候使用的函数
初始化回源负载均衡算法ngx_http_upstream_init_round_robin函数
回源负载均衡算法函数如下:
ngx_http_upstream_init_round_robin ngx_http_upstream_init_chash ngx_http_upstream_init_dynamic ngx_http_upstream_init_hash ngx_http_upstream_init_ip_hash ngx_http_upstream_init_keepalive ngx_http_upstream_init_least_conn ngx_http_upstream_session_sticky_init_upstream |
在init main conf阶段调用init main conf方法。
upstream module只有main conf。
static ngx_http_module_t ngx_http_upstream_module_ctx = { ngx_http_upstream_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ ngx_http_upstream_create_main_conf, /* create main configuration */ ngx_http_upstream_init_main_conf, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ NULL, /* create location configuration */ NULL /* merge location configuration */ }; |
ngx_http_upstream_init_round_robin函数
init_main_conf中调用ngx_http_upstream_init_round_robin来为rr初始化整个upstream下的upstream_srv_conf。
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; // 遍历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; } // 按照server数量pcalloc peers peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); // 赋值 peers->single = (n == 1); peers->number = n; peers->weighted = (w != n); peers->total_weight = w; peers->name = &us->host; n = 0; peer = peers->peer; // 遍历两层循环 for (i = 0; i < us->servers->nelts; i++) { if (server[i].backup) { continue; } for (j = 0; j < server[i].naddrs; j++) { // 将peer中赋值 ...... // 健康检查 #if (NGX_HTTP_UPSTREAM_CHECK) if (!server[i].down) { peer[n].check_index = ngx_http_upstream_check_add_peer(cf, us, &server[i].addrs[j] } ... } |
ngx_connect_peer函数
ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc) { ... #ifdef CONFIG_NGX_NS struct ksock_vgw kv; bzero(&kv, sizeof(struct ksock_vgw)); #endif // init round robin设置声明了get函数 rc = pc->get(pc, pc->data); // 获取socket s = ngx_socket(pc->sockaddr->sa_family, SOCK_STREAM, 0); ...... } int mss = 1460; if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)) == -1 ) { ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, "setsockopt(TCP_MAXSEG) failed"); goto failed; } #endif ... } |
总结
在解析upstream{}server配置的时候放在us→servers中。
在init_round_robin建立整个upstream对应的peers,将所有servers对应监听地址都建立peer联系起来。
随后在create_round_robin_peer中,
rrp = r->upstream->peer.data;
rrp->peers = peers;
将peers和request联系起来,并将upstream_server级别的一些信息填充peer。
在ngx_http_upstream_get_round_robin_peer中,真正挑选出来peer,并且将peer对应的内容赋给peer_connection,发起ngx_event_connect,结束。