From d6e300a53327a5c0dffc712dabbdd82f3740af12 Mon Sep 17 00:00:00 2001 From: Vladimir Khomutov Date: Sat, 25 Feb 2023 17:18:06 +0300 Subject: [PATCH] Upstream: save rr-based modules private data into client context. The client context is either http request or stream session. Both can be used to keep module-specific data. The patch modifies round-robin based load balancing modules to store their data in request/session context. This allows to leave peer.data untouched, pointing to peers as set by round robin module itself. --- src/event/ngx_event_connect.h | 2 + .../modules/ngx_http_upstream_hash_module.c | 161 ++++++++++-------- .../ngx_http_upstream_ip_hash_module.c | 69 ++++---- .../ngx_http_upstream_keepalive_module.c | 103 ++++------- .../modules/ngx_http_upstream_random_module.c | 86 ++++++---- src/http/ngx_http_upstream_round_robin.c | 2 + src/stream/ngx_stream_upstream_hash_module.c | 128 +++++++------- .../ngx_stream_upstream_random_module.c | 83 +++++---- src/stream/ngx_stream_upstream_round_robin.c | 3 + 9 files changed, 331 insertions(+), 306 deletions(-) diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h index d3b23782e..ffed3fce0 100644 --- a/src/event/ngx_event_connect.h +++ b/src/event/ngx_event_connect.h @@ -1,5 +1,6 @@ /* + * Copyright (C) 2023 Web Server LLC * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ @@ -47,6 +48,7 @@ struct ngx_peer_connection_s { ngx_event_free_peer_pt free; ngx_event_notify_peer_pt notify; void *data; + void *ctx; #if (NGX_SSL || NGX_COMPAT) ngx_event_set_peer_session_pt set_session; diff --git a/src/http/modules/ngx_http_upstream_hash_module.c b/src/http/modules/ngx_http_upstream_hash_module.c index 380b08530..c81340b6c 100644 --- a/src/http/modules/ngx_http_upstream_hash_module.c +++ b/src/http/modules/ngx_http_upstream_hash_module.c @@ -33,9 +33,6 @@ typedef struct { typedef struct { - /* the round robin data must be first */ - ngx_http_upstream_rr_peer_data_t rrp; - ngx_http_upstream_hash_srv_conf_t *conf; ngx_str_t key; ngx_uint_t tries; ngx_uint_t rehash; @@ -138,7 +135,7 @@ ngx_http_upstream_init_hash_peer(ngx_http_request_t *r, return NGX_ERROR; } - r->upstream->peer.data = &hp->rrp; + ngx_http_set_ctx(r, hp, ngx_http_upstream_hash_module); if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { return NGX_ERROR; @@ -155,7 +152,6 @@ ngx_http_upstream_init_hash_peer(ngx_http_request_t *r, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upstream hash key:\"%V\"", &hp->key); - hp->conf = hcf; hp->tries = 0; hp->rehash = 0; hp->hash = 0; @@ -168,33 +164,39 @@ ngx_http_upstream_init_hash_peer(ngx_http_request_t *r, static ngx_int_t ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) { - ngx_http_upstream_hash_peer_data_t *hp = data; + ngx_http_upstream_rr_peer_data_t *rrp = data; - time_t now; - u_char buf[NGX_INT_T_LEN]; - size_t size; - uint32_t hash; - ngx_int_t w; - uintptr_t m; - ngx_uint_t n, p; - ngx_http_upstream_rr_peer_t *peer; + time_t now; + u_char buf[NGX_INT_T_LEN]; + size_t size; + uint32_t hash; + ngx_int_t w; + uintptr_t m; + ngx_uint_t n, p; + ngx_http_request_t *r; + ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_hash_peer_data_t *hp; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get hash peer, try: %ui", pc->tries); - ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); + r = pc->ctx; + + hp = ngx_http_get_module_ctx(r, ngx_http_upstream_hash_module); - if (hp->tries > 20 || hp->rrp.peers->number < 2 || hp->key.len == 0) { - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + ngx_http_upstream_rr_peers_rlock(rrp->peers); + + if (hp->tries > 20 || rrp->peers->number < 2 || hp->key.len == 0) { + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } #if (NGX_HTTP_UPSTREAM_ZONE) - if (hp->rrp.peers->generation - && hp->rrp.generation != *hp->rrp.peers->generation) + if (rrp->peers->generation + && rrp->generation != *rrp->peers->generation) { - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } #endif @@ -226,8 +228,8 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) hp->hash += hash; hp->rehash++; - w = hp->hash % hp->rrp.peers->total_weight; - peer = hp->rrp.peers->peer; + w = hp->hash % rrp->peers->total_weight; + peer = rrp->peers->peer; p = 0; while (w >= peer->weight) { @@ -239,17 +241,17 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) n = p / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t)); - if (hp->rrp.tried[n] & m) { + if (rrp->tried[n] & m) { goto next; } - ngx_http_upstream_rr_peer_lock(hp->rrp.peers, peer); + ngx_http_upstream_rr_peer_lock(rrp->peers, peer); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get hash peer, value:%uD, peer:%ui", hp->hash, p); if (peer->down) { - ngx_http_upstream_rr_peer_unlock(hp->rrp.peers, peer); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } @@ -257,12 +259,12 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) && peer->fails >= peer->max_fails && now - peer->checked <= peer->fail_timeout) { - ngx_http_upstream_rr_peer_unlock(hp->rrp.peers, peer); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } if (peer->max_conns && peer->conns >= peer->max_conns) { - ngx_http_upstream_rr_peer_unlock(hp->rrp.peers, peer); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } @@ -271,13 +273,13 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) next: if (++hp->tries > 20) { - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } } - hp->rrp.current = peer; - ngx_http_upstream_rr_peer_ref(hp->rrp.peers, peer); + rrp->current = peer; + ngx_http_upstream_rr_peer_ref(rrp->peers, peer); pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; @@ -294,10 +296,10 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) peer->stats.selected = now; #endif - ngx_http_upstream_rr_peer_unlock(hp->rrp.peers, peer); - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); + ngx_http_upstream_rr_peers_unlock(rrp->peers); - hp->rrp.tried[n] |= m; + rrp->tried[n] |= m; return NGX_OK; } @@ -512,6 +514,7 @@ ngx_http_upstream_init_chash_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) { uint32_t hash; + ngx_http_upstream_rr_peer_data_t *rrp; ngx_http_upstream_hash_srv_conf_t *hcf; ngx_http_upstream_hash_peer_data_t *hp; @@ -521,24 +524,26 @@ ngx_http_upstream_init_chash_peer(ngx_http_request_t *r, r->upstream->peer.get = ngx_http_upstream_get_chash_peer; - hp = r->upstream->peer.data; + hp = ngx_http_get_module_ctx(r, ngx_http_upstream_hash_module); hcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_hash_module); hash = ngx_crc32_long(hp->key.data, hp->key.len); - ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); + rrp = r->upstream->peer.data; + + ngx_http_upstream_rr_peers_rlock(rrp->peers); #if (NGX_HTTP_UPSTREAM_ZONE) - if (hp->rrp.peers->generation + if (rrp->peers->generation && (hcf->points == NULL - || hcf->generation != *hp->rrp.peers->generation)) + || hcf->generation != *rrp->peers->generation)) { if (ngx_http_upstream_update_chash(NULL, us) != NGX_OK) { - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + ngx_http_upstream_rr_peers_unlock(rrp->peers); return NGX_ERROR; } - hcf->generation = *hp->rrp.peers->generation; + hcf->generation = *rrp->peers->generation; } #endif @@ -546,7 +551,7 @@ ngx_http_upstream_init_chash_peer(ngx_http_request_t *r, hp->hash = ngx_http_upstream_find_chash_point(hcf->points, hash); } - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + ngx_http_upstream_rr_peers_unlock(rrp->peers); return NGX_OK; } @@ -555,50 +560,56 @@ ngx_http_upstream_init_chash_peer(ngx_http_request_t *r, static ngx_int_t ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) { - ngx_http_upstream_hash_peer_data_t *hp = data; - - time_t now; - intptr_t m; - ngx_str_t *server; - ngx_int_t total; - ngx_uint_t i, n, best_i; - ngx_http_upstream_rr_peer_t *peer, *best; - ngx_http_upstream_chash_point_t *point; - ngx_http_upstream_chash_points_t *points; - ngx_http_upstream_hash_srv_conf_t *hcf; + ngx_http_upstream_rr_peer_data_t *rrp = data; + + time_t now; + intptr_t m; + ngx_str_t *server; + ngx_int_t total; + ngx_uint_t i, n, best_i; + ngx_http_request_t *r; + ngx_http_upstream_rr_peer_t *peer, *best; + ngx_http_upstream_chash_point_t *point; + ngx_http_upstream_chash_points_t *points; + ngx_http_upstream_hash_srv_conf_t *hcf; + ngx_http_upstream_hash_peer_data_t *hp; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get consistent hash peer, try: %ui", pc->tries); - ngx_http_upstream_rr_peers_wlock(hp->rrp.peers); + r = pc->ctx; - if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + hp = ngx_http_get_module_ctx(r, ngx_http_upstream_hash_module); + + ngx_http_upstream_rr_peers_wlock(rrp->peers); + + if (hp->tries > 20 || rrp->peers->single || hp->key.len == 0) { + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } pc->cached = 0; pc->connection = NULL; - if (hp->rrp.peers->number == 0) { - pc->name = hp->rrp.peers->name; - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + if (rrp->peers->number == 0) { + pc->name = rrp->peers->name; + ngx_http_upstream_rr_peers_unlock(rrp->peers); return NGX_BUSY; } #if (NGX_HTTP_UPSTREAM_ZONE) - if (hp->rrp.peers->generation - && hp->rrp.generation != *hp->rrp.peers->generation) + if (rrp->peers->generation + && rrp->generation != *rrp->peers->generation) { - pc->name = hp->rrp.peers->name; - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + pc->name = rrp->peers->name; + ngx_http_upstream_rr_peers_unlock(rrp->peers); return NGX_BUSY; } #endif now = ngx_time(); - hcf = hp->conf; - + hcf = ngx_http_conf_upstream_srv_conf(r->upstream->upstream, + ngx_http_upstream_hash_module); points = hcf->points; point = &points->point[0]; @@ -613,14 +624,14 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) best_i = 0; total = 0; - for (peer = hp->rrp.peers->peer, i = 0; + for (peer = rrp->peers->peer, i = 0; peer; peer = peer->next, i++) { n = i / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); - if (hp->rrp.tried[n] & m) { + if (rrp->tried[n] & m) { continue; } @@ -668,15 +679,15 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) hp->tries++; if (hp->tries > 20) { - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } } found: - hp->rrp.current = best; - ngx_http_upstream_rr_peer_ref(hp->rrp.peers, best); + rrp->current = best; + ngx_http_upstream_rr_peer_ref(rrp->peers, best); pc->sockaddr = best->sockaddr; pc->socklen = best->socklen; @@ -693,12 +704,12 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) best->stats.selected = now; #endif - ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + ngx_http_upstream_rr_peers_unlock(rrp->peers); n = best_i / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << best_i % (8 * sizeof(uintptr_t)); - hp->rrp.tried[n] |= m; + rrp->tried[n] |= m; return NGX_OK; } diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c index de89260c0..0c573b63e 100644 --- a/src/http/modules/ngx_http_upstream_ip_hash_module.c +++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c @@ -12,9 +12,6 @@ typedef struct { - /* the round robin data must be first */ - ngx_http_upstream_rr_peer_data_t rrp; - ngx_uint_t hash; u_char addrlen; @@ -109,7 +106,7 @@ ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r, return NGX_ERROR; } - r->upstream->peer.data = &iphp->rrp; + ngx_http_set_ctx(r, iphp, ngx_http_upstream_ip_hash_module); if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { return NGX_ERROR; @@ -149,32 +146,38 @@ ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r, static ngx_int_t ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) { - ngx_http_upstream_ip_hash_peer_data_t *iphp = data; - - time_t now; - ngx_int_t w; - uintptr_t m; - ngx_uint_t i, n, p, hash; - ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_rr_peer_data_t *rrp = data; + + time_t now; + ngx_int_t w; + uintptr_t m; + ngx_uint_t i, n, p, hash; + ngx_http_request_t *r; + ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_ip_hash_peer_data_t *iphp; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get ip hash peer, try: %ui", pc->tries); /* TODO: cached */ - ngx_http_upstream_rr_peers_rlock(iphp->rrp.peers); + r = pc->ctx; + + iphp = ngx_http_get_module_ctx(r, ngx_http_upstream_ip_hash_module); + + ngx_http_upstream_rr_peers_rlock(rrp->peers); - if (iphp->tries > 20 || iphp->rrp.peers->number < 2) { - ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers); - return iphp->get_rr_peer(pc, &iphp->rrp); + if (iphp->tries > 20 || rrp->peers->number < 2) { + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return iphp->get_rr_peer(pc, rrp); } #if (NGX_HTTP_UPSTREAM_ZONE) - if (iphp->rrp.peers->generation - && iphp->rrp.generation != *iphp->rrp.peers->generation) + if (rrp->peers->generation + && rrp->generation != *rrp->peers->generation) { - ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers); - return iphp->get_rr_peer(pc, &iphp->rrp); + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return iphp->get_rr_peer(pc, rrp); } #endif @@ -191,8 +194,8 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) hash = (hash * 113 + iphp->addr[i]) % 6271; } - w = hash % iphp->rrp.peers->total_weight; - peer = iphp->rrp.peers->peer; + w = hash % rrp->peers->total_weight; + peer = rrp->peers->peer; p = 0; while (w >= peer->weight) { @@ -204,17 +207,17 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) n = p / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t)); - if (iphp->rrp.tried[n] & m) { + if (rrp->tried[n] & m) { goto next; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get ip hash peer, hash: %ui %04XL", p, (uint64_t) m); - ngx_http_upstream_rr_peer_lock(iphp->rrp.peers, peer); + ngx_http_upstream_rr_peer_lock(rrp->peers, peer); if (peer->down) { - ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } @@ -222,12 +225,12 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) && peer->fails >= peer->max_fails && now - peer->checked <= peer->fail_timeout) { - ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } if (peer->max_conns && peer->conns >= peer->max_conns) { - ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } @@ -236,13 +239,13 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) next: if (++iphp->tries > 20) { - ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers); - return iphp->get_rr_peer(pc, &iphp->rrp); + ngx_http_upstream_rr_peers_unlock(rrp->peers); + return iphp->get_rr_peer(pc, rrp); } } - iphp->rrp.current = peer; - ngx_http_upstream_rr_peer_ref(iphp->rrp.peers, peer); + rrp->current = peer; + ngx_http_upstream_rr_peer_ref(rrp->peers, peer); pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; @@ -259,10 +262,10 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) peer->stats.selected = now; #endif - ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer); - ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers); + ngx_http_upstream_rr_peer_unlock(rrp->peers, peer); + ngx_http_upstream_rr_peers_unlock(rrp->peers); - iphp->rrp.tried[n] |= m; + rrp->tried[n] |= m; iphp->hash = hash; return NGX_OK; diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c index e5c0dbe6e..84ee4e2b8 100644 --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -43,20 +43,8 @@ typedef struct { typedef struct { - ngx_http_upstream_keepalive_srv_conf_t *conf; - - ngx_http_upstream_t *upstream; - - void *data; - ngx_event_get_peer_pt original_get_peer; ngx_event_free_peer_pt original_free_peer; - -#if (NGX_HTTP_SSL) - ngx_event_set_peer_session_pt original_set_session; - ngx_event_save_peer_session_pt original_save_session; -#endif - } ngx_http_upstream_keepalive_peer_data_t; @@ -71,13 +59,6 @@ static void ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev); static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev); static void ngx_http_upstream_keepalive_close(ngx_connection_t *c); -#if (NGX_HTTP_SSL) -static ngx_int_t ngx_http_upstream_keepalive_set_session( - ngx_peer_connection_t *pc, void *data); -static void ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, - void *data); -#endif - static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf); static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -216,23 +197,14 @@ ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r, return NGX_ERROR; } - kp->conf = kcf; - kp->upstream = r->upstream; - kp->data = r->upstream->peer.data; kp->original_get_peer = r->upstream->peer.get; kp->original_free_peer = r->upstream->peer.free; - r->upstream->peer.data = kp; + ngx_http_set_ctx(r, kp, ngx_http_upstream_keepalive_module); + r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer; r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer; -#if (NGX_HTTP_SSL) - kp->original_set_session = r->upstream->peer.set_session; - kp->original_save_session = r->upstream->peer.save_session; - r->upstream->peer.set_session = ngx_http_upstream_keepalive_set_session; - r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session; -#endif - return NGX_OK; } @@ -240,8 +212,10 @@ ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r, static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) { - ngx_http_upstream_keepalive_peer_data_t *kp = data; + ngx_http_request_t *r; ngx_http_upstream_keepalive_cache_t *item; + ngx_http_upstream_keepalive_srv_conf_t *kcf; + ngx_http_upstream_keepalive_peer_data_t *kp; ngx_int_t rc; ngx_queue_t *q, *cache; @@ -252,15 +226,22 @@ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) /* ask balancer */ - rc = kp->original_get_peer(pc, kp->data); + r = pc->ctx; + + kp = ngx_http_get_module_ctx(r, ngx_http_upstream_keepalive_module); + + rc = kp->original_get_peer(pc, data); if (rc != NGX_OK) { return rc; } + kcf = ngx_http_conf_upstream_srv_conf(r->upstream->upstream, + ngx_http_upstream_keepalive_module); + /* search cache for suitable connection */ - cache = &kp->conf->cache; + cache = &kcf->cache; for (q = ngx_queue_head(cache); q != ngx_queue_sentinel(cache); @@ -274,7 +255,7 @@ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) == 0) { ngx_queue_remove(q); - ngx_queue_insert_head(&kp->conf->free, q); + ngx_queue_insert_head(&kcf->free, q); #if (NGX_API) if (item->rr_peers) { @@ -317,8 +298,10 @@ static void ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, ngx_uint_t state) { - ngx_http_upstream_keepalive_peer_data_t *kp = data; + ngx_http_request_t *r; ngx_http_upstream_keepalive_cache_t *item; + ngx_http_upstream_keepalive_srv_conf_t *kcf; + ngx_http_upstream_keepalive_peer_data_t *kp; ngx_queue_t *q; ngx_connection_t *c; @@ -329,7 +312,14 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, /* cache valid connections */ - u = kp->upstream; + r = pc->ctx; + + u = r->upstream; + + kp = ngx_http_get_module_ctx(r, ngx_http_upstream_keepalive_module); + + kcf = ngx_http_conf_upstream_srv_conf(u->upstream, + ngx_http_upstream_keepalive_module); c = pc->connection; if (state & NGX_PEER_FAILED @@ -343,11 +333,11 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, goto invalid; } - if (c->requests >= kp->conf->requests) { + if (c->requests >= kcf->requests) { goto invalid; } - if (ngx_current_msec - c->start_time > kp->conf->time) { + if (ngx_current_msec - c->start_time > kcf->time) { goto invalid; } @@ -370,9 +360,9 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "free keepalive peer: saving connection %p", c); - if (ngx_queue_empty(&kp->conf->free)) { + if (ngx_queue_empty(&kcf->free)) { - q = ngx_queue_last(&kp->conf->cache); + q = ngx_queue_last(&kcf->cache); ngx_queue_remove(q); item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); @@ -386,13 +376,13 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, #endif } else { - q = ngx_queue_head(&kp->conf->free); + q = ngx_queue_head(&kcf->free); ngx_queue_remove(q); item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); } - ngx_queue_insert_head(&kp->conf->cache, q); + ngx_queue_insert_head(&kcf->cache, q); #if (NGX_API) if (u->upstream && (u->upstream->flags & NGX_HTTP_UPSTREAM_CONF)) { @@ -403,12 +393,12 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, item->connection = c; - kp->original_free_peer(pc, kp->data, state); + kp->original_free_peer(pc, data, state); pc->connection = NULL; c->read->delayed = 0; - ngx_add_timer(c->read, kp->conf->timeout); + ngx_add_timer(c->read, kcf->timeout); if (c->write->timer_set) { ngx_del_timer(c->write); @@ -435,7 +425,7 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, invalid: - kp->original_free_peer(pc, kp->data, state); + kp->original_free_peer(pc, data, state); } @@ -519,29 +509,6 @@ ngx_http_upstream_keepalive_close(ngx_connection_t *c) } -#if (NGX_HTTP_SSL) - -static ngx_int_t -ngx_http_upstream_keepalive_set_session(ngx_peer_connection_t *pc, void *data) -{ - ngx_http_upstream_keepalive_peer_data_t *kp = data; - - return kp->original_set_session(pc, kp->data); -} - - -static void -ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, void *data) -{ - ngx_http_upstream_keepalive_peer_data_t *kp = data; - - kp->original_save_session(pc, kp->data); - return; -} - -#endif - - static void * ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf) { diff --git a/src/http/modules/ngx_http_upstream_random_module.c b/src/http/modules/ngx_http_upstream_random_module.c index 1c2135b13..8da50409e 100644 --- a/src/http/modules/ngx_http_upstream_random_module.c +++ b/src/http/modules/ngx_http_upstream_random_module.c @@ -26,10 +26,6 @@ typedef struct { typedef struct { - /* the round robin data must be first */ - ngx_http_upstream_rr_peer_data_t rrp; - - ngx_http_upstream_random_srv_conf_t *conf; u_char tries; } ngx_http_upstream_random_peer_data_t; @@ -47,7 +43,7 @@ static ngx_int_t ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data); static ngx_uint_t ngx_http_upstream_peek_random_peer( ngx_http_upstream_rr_peers_t *peers, - ngx_http_upstream_random_peer_data_t *rp); + ngx_http_upstream_random_srv_conf_t *rcf); static void *ngx_http_upstream_random_create_conf(ngx_conf_t *cf); static char *ngx_http_upstream_random(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -163,6 +159,7 @@ static ngx_int_t ngx_http_upstream_init_random_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) { + ngx_http_upstream_rr_peer_data_t *rrp; ngx_http_upstream_random_srv_conf_t *rcf; ngx_http_upstream_random_peer_data_t *rp; @@ -176,7 +173,7 @@ ngx_http_upstream_init_random_peer(ngx_http_request_t *r, return NGX_ERROR; } - r->upstream->peer.data = &rp->rrp; + ngx_http_set_ctx(r, rp, ngx_http_upstream_random_module); if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { return NGX_ERROR; @@ -189,26 +186,27 @@ ngx_http_upstream_init_random_peer(ngx_http_request_t *r, r->upstream->peer.get = ngx_http_upstream_get_random_peer; } - rp->conf = rcf; rp->tries = 0; - ngx_http_upstream_rr_peers_rlock(rp->rrp.peers); + rrp = r->upstream->peer.data; + + ngx_http_upstream_rr_peers_rlock(rrp->peers); #if (NGX_HTTP_UPSTREAM_ZONE) - if (rp->rrp.peers->generation + if (rrp->peers->generation && (rcf->ranges == NULL - || rcf->generation != *rp->rrp.peers->generation)) + || rcf->generation != *rrp->peers->generation)) { if (ngx_http_upstream_update_random(NULL, us) != NGX_OK) { - ngx_http_upstream_rr_peers_unlock(rp->rrp.peers); + ngx_http_upstream_rr_peers_unlock(rrp->peers); return NGX_ERROR; } - rcf->generation = *rp->rrp.peers->generation; + rcf->generation = *rrp->peers->generation; } #endif - ngx_http_upstream_rr_peers_unlock(rp->rrp.peers); + ngx_http_upstream_rr_peers_unlock(rrp->peers); return NGX_OK; } @@ -217,19 +215,26 @@ ngx_http_upstream_init_random_peer(ngx_http_request_t *r, static ngx_int_t ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data) { - ngx_http_upstream_random_peer_data_t *rp = data; - - time_t now; - uintptr_t m; - ngx_uint_t i, n; - ngx_http_upstream_rr_peer_t *peer; - ngx_http_upstream_rr_peers_t *peers; - ngx_http_upstream_rr_peer_data_t *rrp; + ngx_http_upstream_rr_peer_data_t *rrp = data; + + time_t now; + uintptr_t m; + ngx_uint_t i, n; + ngx_http_request_t *r; + ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_rr_peers_t *peers; + ngx_http_upstream_random_srv_conf_t *rcf; + ngx_http_upstream_random_peer_data_t *rp; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get random peer, try: %ui", pc->tries); - rrp = &rp->rrp; + r = pc->ctx; + + rp = ngx_http_get_module_ctx(r, ngx_http_upstream_random_module); + + rcf = ngx_http_conf_upstream_srv_conf(r->upstream->upstream, + ngx_http_upstream_random_module); peers = rrp->peers; ngx_http_upstream_rr_peers_rlock(peers); @@ -253,9 +258,9 @@ ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data) for ( ;; ) { - i = ngx_http_upstream_peek_random_peer(peers, rp); + i = ngx_http_upstream_peek_random_peer(peers, rcf); - peer = rp->conf->ranges[i].peer; + peer = rcf->ranges[i].peer; n = i / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); @@ -324,19 +329,26 @@ ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data) static ngx_int_t ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data) { - ngx_http_upstream_random_peer_data_t *rp = data; - - time_t now; - uintptr_t m; - ngx_uint_t i, n, p; - ngx_http_upstream_rr_peer_t *peer, *prev; - ngx_http_upstream_rr_peers_t *peers; - ngx_http_upstream_rr_peer_data_t *rrp; + ngx_http_upstream_rr_peer_data_t *rrp = data; + + time_t now; + uintptr_t m; + ngx_uint_t i, n, p; + ngx_http_request_t *r; + ngx_http_upstream_rr_peer_t *peer, *prev; + ngx_http_upstream_rr_peers_t *peers; + ngx_http_upstream_random_srv_conf_t *rcf; + ngx_http_upstream_random_peer_data_t *rp; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get random2 peer, try: %ui", pc->tries); - rrp = &rp->rrp; + r = pc->ctx; + + rp = ngx_http_get_module_ctx(r, ngx_http_upstream_random_module); + + rcf = ngx_http_conf_upstream_srv_conf(r->upstream->upstream, + ngx_http_upstream_random_module); peers = rrp->peers; ngx_http_upstream_rr_peers_wlock(peers); @@ -366,9 +378,9 @@ ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data) for ( ;; ) { - i = ngx_http_upstream_peek_random_peer(peers, rp); + i = ngx_http_upstream_peek_random_peer(peers, rcf); - peer = rp->conf->ranges[i].peer; + peer = rcf->ranges[i].peer; if (peer == prev) { goto next; @@ -445,7 +457,7 @@ ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data) static ngx_uint_t ngx_http_upstream_peek_random_peer(ngx_http_upstream_rr_peers_t *peers, - ngx_http_upstream_random_peer_data_t *rp) + ngx_http_upstream_random_srv_conf_t *rcf) { ngx_uint_t i, j, k, x; @@ -457,7 +469,7 @@ ngx_http_upstream_peek_random_peer(ngx_http_upstream_rr_peers_t *peers, while (j - i > 1) { k = (i + j) / 2; - if (x < rp->conf->ranges[k].range) { + if (x < rcf->ranges[k].range) { j = k; } else { diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index e7e24bba5..257ecc774 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -434,6 +434,7 @@ ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r, } } + r->upstream->peer.ctx = r; r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer; r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer; r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers); @@ -553,6 +554,7 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, } } + r->upstream->peer.ctx = r; r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer; r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer; r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers); diff --git a/src/stream/ngx_stream_upstream_hash_module.c b/src/stream/ngx_stream_upstream_hash_module.c index b764fcbe0..c7552e05d 100644 --- a/src/stream/ngx_stream_upstream_hash_module.c +++ b/src/stream/ngx_stream_upstream_hash_module.c @@ -1,5 +1,6 @@ /* + * Copyright (C) 2023 Web Server LLC * Copyright (C) Roman Arutyunyan * Copyright (C) Nginx, Inc. */ @@ -29,9 +30,6 @@ typedef struct { typedef struct { - /* the round robin data must be first */ - ngx_stream_upstream_rr_peer_data_t rrp; - ngx_stream_upstream_hash_srv_conf_t *conf; ngx_str_t key; ngx_uint_t tries; ngx_uint_t rehash; @@ -131,7 +129,7 @@ ngx_stream_upstream_init_hash_peer(ngx_stream_session_t *s, return NGX_ERROR; } - s->upstream->peer.data = &hp->rrp; + ngx_stream_set_ctx(s, hp, ngx_stream_upstream_hash_module); if (ngx_stream_upstream_init_round_robin_peer(s, us) != NGX_OK) { return NGX_ERROR; @@ -149,7 +147,6 @@ ngx_stream_upstream_init_hash_peer(ngx_stream_session_t *s, ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "upstream hash key:\"%V\"", &hp->key); - hp->conf = hcf; hp->tries = 0; hp->rehash = 0; hp->hash = 0; @@ -162,25 +159,31 @@ ngx_stream_upstream_init_hash_peer(ngx_stream_session_t *s, static ngx_int_t ngx_stream_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) { - ngx_stream_upstream_hash_peer_data_t *hp = data; + ngx_stream_upstream_rr_peer_data_t *rrp = data; - time_t now; - u_char buf[NGX_INT_T_LEN]; - size_t size; - uint32_t hash; - ngx_int_t w; - uintptr_t m; - ngx_uint_t n, p; - ngx_stream_upstream_rr_peer_t *peer; + time_t now; + u_char buf[NGX_INT_T_LEN]; + size_t size; + uint32_t hash; + ngx_int_t w; + uintptr_t m; + ngx_uint_t n, p; + ngx_stream_session_t *s; + ngx_stream_upstream_rr_peer_t *peer; + ngx_stream_upstream_hash_peer_data_t *hp; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, "get hash peer, try: %ui", pc->tries); - ngx_stream_upstream_rr_peers_rlock(hp->rrp.peers); + s = pc->ctx; + + hp = ngx_stream_get_module_ctx(s, ngx_stream_upstream_hash_module); - if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { - ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + ngx_stream_upstream_rr_peers_rlock(rrp->peers); + + if (hp->tries > 20 || rrp->peers->single || hp->key.len == 0) { + ngx_stream_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } now = ngx_time(); @@ -210,8 +213,8 @@ ngx_stream_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) hp->hash += hash; hp->rehash++; - w = hp->hash % hp->rrp.peers->total_weight; - peer = hp->rrp.peers->peer; + w = hp->hash % rrp->peers->total_weight; + peer = rrp->peers->peer; p = 0; while (w >= peer->weight) { @@ -223,17 +226,17 @@ ngx_stream_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) n = p / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t)); - if (hp->rrp.tried[n] & m) { + if (rrp->tried[n] & m) { goto next; } - ngx_stream_upstream_rr_peer_lock(hp->rrp.peers, peer); + ngx_stream_upstream_rr_peer_lock(rrp->peers, peer); ngx_log_debug2(NGX_LOG_DEBUG_STREAM, pc->log, 0, "get hash peer, value:%uD, peer:%ui", hp->hash, p); if (peer->down) { - ngx_stream_upstream_rr_peer_unlock(hp->rrp.peers, peer); + ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } @@ -241,12 +244,12 @@ ngx_stream_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) && peer->fails >= peer->max_fails && now - peer->checked <= peer->fail_timeout) { - ngx_stream_upstream_rr_peer_unlock(hp->rrp.peers, peer); + ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } if (peer->max_conns && peer->conns >= peer->max_conns) { - ngx_stream_upstream_rr_peer_unlock(hp->rrp.peers, peer); + ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); goto next; } @@ -255,12 +258,12 @@ ngx_stream_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) next: if (++hp->tries > 20) { - ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } } - hp->rrp.current = peer; + rrp->current = peer; pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; @@ -272,10 +275,10 @@ ngx_stream_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) peer->checked = now; } - ngx_stream_upstream_rr_peer_unlock(hp->rrp.peers, peer); - ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); + ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); - hp->rrp.tried[n] |= m; + rrp->tried[n] |= m; return NGX_OK; } @@ -466,6 +469,7 @@ ngx_stream_upstream_init_chash_peer(ngx_stream_session_t *s, ngx_stream_upstream_srv_conf_t *us) { uint32_t hash; + ngx_stream_upstream_rr_peer_data_t *rrp; ngx_stream_upstream_hash_srv_conf_t *hcf; ngx_stream_upstream_hash_peer_data_t *hp; @@ -475,17 +479,19 @@ ngx_stream_upstream_init_chash_peer(ngx_stream_session_t *s, s->upstream->peer.get = ngx_stream_upstream_get_chash_peer; - hp = s->upstream->peer.data; + hp = ngx_stream_get_module_ctx(s, ngx_stream_upstream_hash_module); hcf = ngx_stream_conf_upstream_srv_conf(us, ngx_stream_upstream_hash_module); hash = ngx_crc32_long(hp->key.data, hp->key.len); - ngx_stream_upstream_rr_peers_rlock(hp->rrp.peers); + rrp = s->upstream->peer.data; + + ngx_stream_upstream_rr_peers_rlock(rrp->peers); hp->hash = ngx_stream_upstream_find_chash_point(hcf->points, hash); - ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); return NGX_OK; } @@ -494,33 +500,39 @@ ngx_stream_upstream_init_chash_peer(ngx_stream_session_t *s, static ngx_int_t ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) { - ngx_stream_upstream_hash_peer_data_t *hp = data; - - time_t now; - intptr_t m; - ngx_str_t *server; - ngx_int_t total; - ngx_uint_t i, n, best_i; - ngx_stream_upstream_rr_peer_t *peer, *best; - ngx_stream_upstream_chash_point_t *point; - ngx_stream_upstream_chash_points_t *points; - ngx_stream_upstream_hash_srv_conf_t *hcf; + ngx_stream_upstream_rr_peer_data_t *rrp = data; + + time_t now; + intptr_t m; + ngx_str_t *server; + ngx_int_t total; + ngx_uint_t i, n, best_i; + ngx_stream_session_t *s; + ngx_stream_upstream_rr_peer_t *peer, *best; + ngx_stream_upstream_chash_point_t *point; + ngx_stream_upstream_chash_points_t *points; + ngx_stream_upstream_hash_srv_conf_t *hcf; + ngx_stream_upstream_hash_peer_data_t *hp; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, "get consistent hash peer, try: %ui", pc->tries); - ngx_stream_upstream_rr_peers_wlock(hp->rrp.peers); + s = pc->ctx; - if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { - ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + hp = ngx_stream_get_module_ctx(s, ngx_stream_upstream_hash_module); + + ngx_stream_upstream_rr_peers_wlock(rrp->peers); + + if (hp->tries > 20 || rrp->peers->single || hp->key.len == 0) { + ngx_stream_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } pc->connection = NULL; now = ngx_time(); - hcf = hp->conf; - + hcf = ngx_stream_conf_upstream_srv_conf(s->upstream->upstream, + ngx_stream_upstream_hash_module); points = hcf->points; point = &points->point[0]; @@ -535,14 +547,14 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) best_i = 0; total = 0; - for (peer = hp->rrp.peers->peer, i = 0; + for (peer = rrp->peers->peer, i = 0; peer; peer = peer->next, i++) { n = i / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); - if (hp->rrp.tried[n] & m) { + if (rrp->tried[n] & m) { continue; } @@ -590,12 +602,12 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) hp->tries++; if (hp->tries > 20) { - ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); - return hp->get_rr_peer(pc, &hp->rrp); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); + return hp->get_rr_peer(pc, rrp); } } - hp->rrp.current = best; + rrp->current = best; pc->sockaddr = best->sockaddr; pc->socklen = best->socklen; @@ -607,12 +619,12 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) best->checked = now; } - ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); n = best_i / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << best_i % (8 * sizeof(uintptr_t)); - hp->rrp.tried[n] |= m; + rrp->tried[n] |= m; return NGX_OK; } diff --git a/src/stream/ngx_stream_upstream_random_module.c b/src/stream/ngx_stream_upstream_random_module.c index 402c1b298..5007b95be 100644 --- a/src/stream/ngx_stream_upstream_random_module.c +++ b/src/stream/ngx_stream_upstream_random_module.c @@ -1,5 +1,6 @@ /* + * Copyright (C) 2023 Web Server LLC * Copyright (C) Nginx, Inc. */ @@ -22,10 +23,6 @@ typedef struct { typedef struct { - /* the round robin data must be first */ - ngx_stream_upstream_rr_peer_data_t rrp; - - ngx_stream_upstream_random_srv_conf_t *conf; u_char tries; } ngx_stream_upstream_random_peer_data_t; @@ -43,7 +40,7 @@ static ngx_int_t ngx_stream_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data); static ngx_uint_t ngx_stream_upstream_peek_random_peer( ngx_stream_upstream_rr_peers_t *peers, - ngx_stream_upstream_random_peer_data_t *rp); + ngx_stream_upstream_random_srv_conf_t *rcf); static void *ngx_stream_upstream_random_create_conf(ngx_conf_t *cf); static char *ngx_stream_upstream_random(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -152,6 +149,7 @@ static ngx_int_t ngx_stream_upstream_init_random_peer(ngx_stream_session_t *s, ngx_stream_upstream_srv_conf_t *us) { + ngx_stream_upstream_rr_peer_data_t *rrp; ngx_stream_upstream_random_srv_conf_t *rcf; ngx_stream_upstream_random_peer_data_t *rp; @@ -167,7 +165,7 @@ ngx_stream_upstream_init_random_peer(ngx_stream_session_t *s, return NGX_ERROR; } - s->upstream->peer.data = &rp->rrp; + ngx_stream_set_ctx(s, rp, ngx_stream_upstream_random_module); if (ngx_stream_upstream_init_round_robin_peer(s, us) != NGX_OK) { return NGX_ERROR; @@ -180,21 +178,22 @@ ngx_stream_upstream_init_random_peer(ngx_stream_session_t *s, s->upstream->peer.get = ngx_stream_upstream_get_random_peer; } - rp->conf = rcf; rp->tries = 0; - ngx_stream_upstream_rr_peers_rlock(rp->rrp.peers); + rrp = s->upstream->peer.data; + + ngx_stream_upstream_rr_peers_rlock(rrp->peers); #if (NGX_STREAM_UPSTREAM_ZONE) - if (rp->rrp.peers->shpool && rcf->ranges == NULL) { + if (rrp->peers->shpool && rcf->ranges == NULL) { if (ngx_stream_upstream_update_random(NULL, us) != NGX_OK) { - ngx_stream_upstream_rr_peers_unlock(rp->rrp.peers); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); return NGX_ERROR; } } #endif - ngx_stream_upstream_rr_peers_unlock(rp->rrp.peers); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); return NGX_OK; } @@ -203,19 +202,26 @@ ngx_stream_upstream_init_random_peer(ngx_stream_session_t *s, static ngx_int_t ngx_stream_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data) { - ngx_stream_upstream_random_peer_data_t *rp = data; - - time_t now; - uintptr_t m; - ngx_uint_t i, n; - ngx_stream_upstream_rr_peer_t *peer; - ngx_stream_upstream_rr_peers_t *peers; - ngx_stream_upstream_rr_peer_data_t *rrp; + ngx_stream_upstream_rr_peer_data_t *rrp = data; + + time_t now; + uintptr_t m; + ngx_uint_t i, n; + ngx_stream_session_t *s; + ngx_stream_upstream_rr_peer_t *peer; + ngx_stream_upstream_rr_peers_t *peers; + ngx_stream_upstream_random_srv_conf_t *rcf; + ngx_stream_upstream_random_peer_data_t *rp; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, "get random peer, try: %ui", pc->tries); - rrp = &rp->rrp; + s = pc->ctx; + + rp = ngx_stream_get_module_ctx(s, ngx_stream_upstream_random_module); + + rcf = ngx_stream_conf_upstream_srv_conf(s->upstream->upstream, + ngx_stream_upstream_random_module); peers = rrp->peers; ngx_stream_upstream_rr_peers_rlock(peers); @@ -232,9 +238,9 @@ ngx_stream_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data) for ( ;; ) { - i = ngx_stream_upstream_peek_random_peer(peers, rp); + i = ngx_stream_upstream_peek_random_peer(peers, rcf); - peer = rp->conf->ranges[i].peer; + peer = rcf->ranges[i].peer; n = i / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); @@ -297,19 +303,26 @@ ngx_stream_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data) static ngx_int_t ngx_stream_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data) { - ngx_stream_upstream_random_peer_data_t *rp = data; - - time_t now; - uintptr_t m; - ngx_uint_t i, n, p; - ngx_stream_upstream_rr_peer_t *peer, *prev; - ngx_stream_upstream_rr_peers_t *peers; - ngx_stream_upstream_rr_peer_data_t *rrp; + ngx_stream_upstream_rr_peer_data_t *rrp = data; + + time_t now; + uintptr_t m; + ngx_uint_t i, n, p; + ngx_stream_session_t *s; + ngx_stream_upstream_rr_peer_t *peer, *prev; + ngx_stream_upstream_rr_peers_t *peers; + ngx_stream_upstream_random_srv_conf_t *rcf; + ngx_stream_upstream_random_peer_data_t *rp; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, "get random2 peer, try: %ui", pc->tries); - rrp = &rp->rrp; + s = pc->ctx; + + rp = ngx_stream_get_module_ctx(s, ngx_stream_upstream_random_module); + + rcf = ngx_stream_conf_upstream_srv_conf(s->upstream->upstream, + ngx_stream_upstream_random_module); peers = rrp->peers; ngx_stream_upstream_rr_peers_wlock(peers); @@ -332,9 +345,9 @@ ngx_stream_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data) for ( ;; ) { - i = ngx_stream_upstream_peek_random_peer(peers, rp); + i = ngx_stream_upstream_peek_random_peer(peers, rcf); - peer = rp->conf->ranges[i].peer; + peer = rcf->ranges[i].peer; if (peer == prev) { goto next; @@ -405,7 +418,7 @@ ngx_stream_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data) static ngx_uint_t ngx_stream_upstream_peek_random_peer(ngx_stream_upstream_rr_peers_t *peers, - ngx_stream_upstream_random_peer_data_t *rp) + ngx_stream_upstream_random_srv_conf_t *rcf) { ngx_uint_t i, j, k, x; @@ -417,7 +430,7 @@ ngx_stream_upstream_peek_random_peer(ngx_stream_upstream_rr_peers_t *peers, while (j - i > 1) { k = (i + j) / 2; - if (x < rp->conf->ranges[k].range) { + if (x < rcf->ranges[k].range) { j = k; } else { diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c index ae3bf37a6..352add875 100644 --- a/src/stream/ngx_stream_upstream_round_robin.c +++ b/src/stream/ngx_stream_upstream_round_robin.c @@ -1,5 +1,6 @@ /* + * Copyright (C) 2023 Web Server LLC * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ @@ -301,6 +302,7 @@ ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s, } } + s->upstream->peer.ctx = s; s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer; s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer; s->upstream->peer.notify = ngx_stream_upstream_notify_round_robin_peer; @@ -425,6 +427,7 @@ ngx_stream_upstream_create_round_robin_peer(ngx_stream_session_t *s, } } + s->upstream->peer.ctx = s; s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer; s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer; s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers);