Skip to content

Commit ef9ac4d

Browse files
setnickazhuizhuhaomeng
authored andcommitted
bugfix: balancer keepalive connections were never reused with proxy_bind.
When proxy_bind sets the local address and balancer_by_lua* enables keepalive without calling balancer.bind_to_local_addr(), pc->local holds the proxy_bind address while bp->local is NULL. free_peer hashed the saved connection with bp->local, but get_cached_item looks it up with pc->local, so the lookup never matched: every connection was saved, never reused, and closed when it idled out. Hash with pc->local, which is the address the connection was bound to and the one stored in item->local_sockaddr. Since nginx 1.29.7 the "keepalive" directive is enabled by default and its cache takes the connections before the Lua pool, so the test turns it off with "keepalive 0" on those versions.
1 parent 4f03161 commit ef9ac4d

2 files changed

Lines changed: 44 additions & 2 deletions

File tree

‎src/ngx_http_lua_balancer.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data,
660660
ngx_queue_insert_head(&lscf->balancer.cache, q);
661661
hash = ngx_http_lua_balancer_calc_hash(host,
662662
bp->sockaddr, bp->socklen,
663-
bp->local);
663+
pc->local);
664664
item->hash = hash;
665665
hash %= lscf->balancer.bucket_cnt;
666666
ngx_queue_insert_head(&lscf->balancer.buckets[hash], &item->hnode);

‎t/188-balancer_keepalive_pool_max_retry.t‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use Cwd qw(cwd);
66
log_level('info');
77
repeat_each(1);
88

9-
plan tests => repeat_each() * (blocks() * 6 - 1);
9+
plan tests => repeat_each() * (blocks() * 6 + 5);
1010

1111
my $pwd = cwd();
1212

@@ -214,3 +214,45 @@ qr/\A\Q$first\E(?:\Q$extra\E)?\z/
214214
--- no_error_log
215215
retry storm guard
216216
[alert]
217+
218+
219+
220+
=== TEST 3: reuse keepalive connections per proxy_bind address
221+
proxy_bind sets the local address of the upstream connection, while
222+
balancer.bind_to_local_addr() is not called.
223+
--- http_config eval
224+
# Since nginx version 1.29.7, the "keepalive" directive is enabled by
225+
# default and its cache takes the connections before the Lua pool sees them.
226+
my $keepalive = $Test::Nginx::Util::NginxVersion >= 1.029007 ?
227+
"keepalive 0;" : "";
228+
229+
qq{
230+
upstream backend {
231+
server 0.0.0.1;
232+
$keepalive
233+
balancer_by_lua_block {
234+
local b = require "ngx.balancer"
235+
assert(b.set_current_peer("127.0.0.1", \$TEST_NGINX_RAND_PORT_1))
236+
assert(b.enable_keepalive())
237+
}
238+
}
239+
240+
server {
241+
listen 127.0.0.1:\$TEST_NGINX_RAND_PORT_1;
242+
return 200 "\$remote_addr \$connection_requests";
243+
}
244+
}
245+
--- config
246+
location = /t {
247+
proxy_bind $arg_bind;
248+
proxy_pass http://backend;
249+
proxy_http_version 1.1;
250+
proxy_set_header Connection "";
251+
}
252+
--- request eval
253+
["GET /t?bind=127.0.0.1", "GET /t?bind=127.0.0.2",
254+
"GET /t?bind=127.0.0.1", "GET /t?bind=127.0.0.2"]
255+
--- response_body eval
256+
["127.0.0.1 1", "127.0.0.2 1", "127.0.0.1 2", "127.0.0.2 2"]
257+
--- no_error_log
258+
[error]

0 commit comments

Comments
 (0)