First start with the following structure, which is also included in the ngx_http_upstream_srv_conf_s structure
<code><span>typedef</span><span>struct</span> { <span>/*typedef ngx_int_t (*ngx_http_upstream_init_pt)(ngx_conf_t*cf,ngx_http_upstream_srv_conf_t *us);*/</span> ngx_http_upstream_init_pt init_upstream; ngx_http_upstream_init_peer_pt init; <span>void</span> *data; } ngx_http_upstream_peer_t</code>
The following focuses on the analysis of the two member variables init_upstream and init
init_upstream
Each upsteam configuration block is executed once;
It can be configured by configuring the keepalive or ip_hash function, that is, the keepalive or ip_hash configuration is called. If there is no configuration, the default implementation is the ngx_http_upstream_init_round_robin function. The initialization function ngx_http_upstream_init_main_conf is called in the configuration. The default setting is that there are 2 main functions.
init
init function for each arrival oringin's request is executed once;
Called in ngx_http_upstream_init_request to configure the r->upstream->peer structure. Different get and free functions will be configured for the keepalive and ip_hash functions. The default implementation is ngx_http_upstream_create_round_robin_peer
<code>struct ngx_peer_connection_s { ngx_connection_t <span>*</span>connection; struct sockaddr <span>*</span>sockaddr; socklen_t socklen; ngx_str_t <span>*</span>name; ngx_uint_t tries; ngx_msec_t start_time; <span>/*类型typedef ngx_int_t (*ngx_event_get_peer_pt)(ngx_peer_connection_t *pc, void *data);*/</span><span>/* 上面init的函数中被配置,如果配置了keepalive且从cache中找到了connection将返回NGX_DONE,*/</span><span>/* 且设置复 用已经存在的连接,如果没有配置keepalive或者,没有找到存在的connection,*/</span><span>/*但找到了下一跳地址,将返回NGX_OK,*/</span> ngx_event_get_peer_pt get; <span>/*,同样在init中被设置,连接释放时被调用*/</span> ngx_event_free_peer_pt free; <span>/* 在init中被设置,用以保存init_upstream中生成的us->peer.data数据,在get和free方法中被使用*/</span><span>void</span><span>*</span><span>data</span>; <span>...</span><span>...</span><span>...</span> };</code>
The data initialized by the init function will be rr is used to create a connection, and the calling process is as follows:
ngx_http_upstream_init_request->ngx_http_upstream_connect->ngx_event_connect_peer->
rc = pc->get(pc, pc->data);
The relationship between round_robin, ip_hash, keepalive modules
The round_robin and ip_hash modules are both used to find the ip address. The keepalive function is used to find the ip address of the ip address and then use the ip address to find out whether there is an available connection. Therefore, the get implementation methods of the two modules are different. ip_hash is currently used. Search ip_hash. If the search fails, use the default round_robin function.
The keepalive function can only be used after the ip is found. To find the ip, you can use the ip_hash method or the method provided by round_robin.
As shown below
<code>static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t <span>*</span>r, ngx_http_upstream_srv_conf_t <span>*</span>us) { ngx_http_upstream_keepalive_peer_data_t <span>*</span>kp; ngx_http_upstream_keepalive_srv_conf_t <span>*</span>kcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r<span>-></span>connection<span>-></span><span>log</span>, <span>0</span>, <span>"init keepalive peer"</span>); kcf <span>=</span> ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_keepalive_module); kp <span>=</span> ngx_palloc(r<span>-></span>pool, sizeof(ngx_http_upstream_keepalive_peer_data_t)); <span>if</span> (kp <span>==</span><span>NULL</span>) { <span>return</span> NGX_ERROR; } <span>if</span> (kcf<span>-></span>original_init_peer(r, us) <span>!=</span> NGX_OK) { <span>return</span> NGX_ERROR; } kp<span>-></span>conf <span>=</span> kcf; kp<span>-></span>upstream <span>=</span> r<span>-></span>upstream; <span>/*保存默认的original_get_peer方法,仍将在新的get方法中被调用,r->upstream->peer.get;可以是round_robin,也可以是iphash模块提供的 */</span> kp<span>-></span>original_get_peer <span>=</span> r<span>-></span>upstream<span>-></span>peer<span>.</span>get; kp<span>-></span>original_free_peer <span>=</span> r<span>-></span>upstream<span>-></span>peer<span>.</span>free; <span>...</span><span>...</span><span>/*保存默认的在original_init_peer中初始化好的数据,get和free方法中需要使用*/</span> kp<span>-></span><span>data</span><span>=</span> r<span>-></span>upstream<span>-></span>peer<span>.</span><span>data</span>; <span>/*可以通过r->upstream->peer.data找到keepalive模块*/</span> r<span>-></span>upstream<span>-></span>peer<span>.</span><span>data</span><span>=</span> kp; <span>/*设置新的get和free钩子*/</span> r<span>-></span>upstream<span>-></span>peer<span>.</span>get <span>=</span> ngx_http_upstream_get_keepalive_peer; r<span>-></span>upstream<span>-></span>peer<span>.</span>free <span>=</span> ngx_http_upstream_free_keepalive_peer; <span>return</span> NGX_OK; } static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t <span>*</span>pc, <span>void</span><span>*</span><span>data</span>) { ngx_http_upstream_keepalive_peer_data_t <span>*</span>kp <span>=</span><span>data</span>; ngx_http_upstream_keepalive_cache_t <span>*</span>item; ngx_int_t rc; ngx_queue_t <span>*</span>q, <span>*</span><span>cache</span>; ngx_connection_t <span>*</span>c; <span>/* ask balancer 此源码注释应不准确*/</span><span>/*适用round_robin或者ip_hash等功能找到下一跳地址*/</span> rc <span>=</span> kp<span>-></span>original_get_peer(pc, kp<span>-></span><span>data</span>); <span>if</span> (rc <span>!=</span> NGX_OK) { <span>return</span> rc; } <span>/* search cache for suitable connection */</span><span>cache</span><span>=</span><span>&</span>kp<span>-></span>conf<span>-></span><span>cache</span>;</code>
, we can see that keepalive is similar to the decorator model, that is, adding a keepalive function to the next hop IP. The keepalive contains the function pointer implemented by origin
The ip_hash and round_robin can be similar to the strategy model, that is, setting different strategies for request to find IP in init_upstream.
The overall relationship between these three modules is similar to the relationship between builders, that is, they must implement and call init_upstream, init, get, free and other functions in order.
Postscript:
round_robin provides a create function, which is used when the resolved member in upstream is set, for example through
Proxy_pass http://$vhost; is set to the origin address. At this time, init is replaced by create and cannot have the keepalive and ip_hash functions. Both keepalive and iphash can only be used in the upstream module.
The above has introduced the analysis of nginx roundrobin, keepalive, and ip_hash modules, including relevant content. I hope it will be helpful to friends who are interested in PHP tutorials.