Skip to content

Commit 7e581f9

Browse files
authored
Merge pull request #1360 from wangfakang/master
Bugfix: maybe caused traffic uneven when some peers are unavailable.
2 parents 4e90f0e + 691050f commit 7e581f9

File tree

2 files changed

+85
-55
lines changed

2 files changed

+85
-55
lines changed

modules/ngx_http_upstream_vnswrr_module/ngx_http_upstream_vnswrr_module.c

+63-54
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ static ngx_int_t ngx_http_upstream_get_rr_peer(ngx_http_upstream_rr_peers_t *pee
5757
ngx_http_upstream_rr_peer_t **rpeer);
5858
static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_vnswrr(
5959
ngx_http_upstream_vnswrr_peer_data_t *vnsp);
60+
static void ngx_http_upstream_init_virtual_peers(
61+
ngx_http_upstream_rr_peers_t *peers,
62+
ngx_http_upstream_vnswrr_srv_conf_t *uvnscf,
63+
ngx_uint_t s, ngx_uint_t e);
6064

6165

6266
static ngx_command_t ngx_http_upstream_vnswrr_commands[] = {
@@ -148,7 +152,9 @@ ngx_http_upstream_vnswrr(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
148152
|NGX_HTTP_UPSTREAM_BACKUP
149153
|NGX_HTTP_UPSTREAM_MAX_FAILS
150154
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
155+
#if defined(nginx_version) && nginx_version >= 1011005
151156
|NGX_HTTP_UPSTREAM_MAX_CONNS
157+
#endif
152158
|NGX_HTTP_UPSTREAM_DOWN;
153159

154160
return NGX_CONF_OK;
@@ -159,9 +165,6 @@ static ngx_int_t
159165
ngx_http_upstream_init_vnswrr(ngx_conf_t *cf,
160166
ngx_http_upstream_srv_conf_t *us)
161167
{
162-
ngx_uint_t i;
163-
ngx_int_t rindex;
164-
ngx_http_upstream_rr_peer_t *peer;
165168
ngx_http_upstream_rr_peers_t *peers, *backup;
166169
ngx_http_upstream_vnswrr_srv_conf_t *uvnscf, *ubvnscf;
167170

@@ -194,22 +197,8 @@ ngx_http_upstream_init_vnswrr(ngx_conf_t *cf,
194197
return NGX_ERROR;
195198
}
196199

197-
uvnscf->vnumber = peers->number;
198-
199-
for (i = 0; i < peers->number; i++) {
200-
rindex = ngx_http_upstream_get_rr_peer(peers, &peer);
201-
if (rindex == NGX_ERROR) {
202-
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
203-
"peers peer is null in upstream \"%V\" "
204-
"in %s:%ui",&us->host, us->file_name, us->line);
205-
if (i != 0) {
206-
i--;
207-
}
208-
continue;
209-
}
210-
uvnscf->vpeers[i].vpeer = peer;
211-
uvnscf->vpeers[i].rindex = rindex;
212-
}
200+
ngx_http_upstream_init_virtual_peers(peers, uvnscf, 0, peers->number);
201+
213202
}
214203

215204
/* backup peers */
@@ -238,23 +227,7 @@ ngx_http_upstream_init_vnswrr(ngx_conf_t *cf,
238227
return NGX_ERROR;
239228
}
240229

241-
ubvnscf->vnumber = backup->number;
242-
243-
for (i = 0; i < backup->number; i++) {
244-
rindex = ngx_http_upstream_get_rr_peer(backup, &peer);
245-
if (rindex == NGX_ERROR) {
246-
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
247-
"backup peer is null in upstream \"%V\" "
248-
"in %s:%ui", &us->host, us->file_name, us->line);
249-
if (i != 0) {
250-
i--;
251-
}
252-
continue;
253-
}
254-
255-
ubvnscf->vpeers[i].vpeer = peer;
256-
ubvnscf->vpeers[i].rindex = rindex;
257-
}
230+
ngx_http_upstream_init_virtual_peers(backup, ubvnscf, 0, backup->number);
258231
}
259232

260233
return NGX_OK;
@@ -318,9 +291,11 @@ ngx_http_upstream_get_vnswrr_peer(ngx_peer_connection_t *pc, void *data)
318291
goto failed;
319292
}
320293

294+
#if defined(nginx_version) && nginx_version >= 1011005
321295
if (peer->max_conns && peer->conns >= peer->max_conns) {
322296
goto failed;
323297
}
298+
#endif
324299

325300
#if (NGX_HTTP_UPSTREAM_CHECK)
326301
if (ngx_http_upstream_check_peer_down(peer->check_index)) {
@@ -427,7 +402,6 @@ ngx_http_upstream_get_vnswrr(ngx_http_upstream_vnswrr_peer_data_t *vnsp)
427402
{
428403
time_t now;
429404
uintptr_t m;
430-
ngx_int_t rindex;
431405
ngx_uint_t i, n, p, flag, begin_number;
432406
ngx_http_upstream_rr_peer_t *peer, *best;
433407
ngx_http_upstream_rr_peers_t *peers;
@@ -474,24 +448,9 @@ ngx_http_upstream_get_vnswrr(ngx_http_upstream_vnswrr_peer_data_t *vnsp)
474448
n = peers->number;
475449
}
476450

477-
for (i = uvnscf->vnumber; i < n + uvnscf->vnumber; i++) {
478-
rindex = ngx_http_upstream_get_rr_peer(peers, &peer);
479-
if (rindex == NGX_ERROR) {
480-
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
481-
"get rr peer is null in upstream \"%V\" ",
482-
peers->name);
483-
if (i != 0) {
484-
i--;
485-
}
486-
487-
continue;
488-
}
489-
490-
vpeers[i].vpeer = peer;
491-
vpeers[i].rindex = rindex;
492-
}
451+
ngx_http_upstream_init_virtual_peers(peers, uvnscf, uvnscf->vnumber,
452+
n + uvnscf->vnumber);
493453

494-
uvnscf->vnumber = i;
495454
}
496455

497456
begin_number = (uvnscf->last_number + 1) % uvnscf->vnumber;
@@ -517,6 +476,15 @@ ngx_http_upstream_get_vnswrr(ngx_http_upstream_vnswrr_peer_data_t *vnsp)
517476

518477
flag = 0;
519478
if (peers->weighted) {
479+
480+
n = peers->total_weight - uvnscf->vnumber;
481+
if (n > peers->number) {
482+
n = peers->number;
483+
}
484+
485+
ngx_http_upstream_init_virtual_peers(peers, uvnscf, uvnscf->vnumber,
486+
n + uvnscf->vnumber);
487+
520488
n = vpeers[i].rindex / (8 * sizeof(uintptr_t));
521489
m = (uintptr_t) 1 << vpeers[i].rindex % (8 * sizeof(uintptr_t));
522490

@@ -540,9 +508,11 @@ ngx_http_upstream_get_vnswrr(ngx_http_upstream_vnswrr_peer_data_t *vnsp)
540508
continue;
541509
}
542510

511+
#if defined(nginx_version) && nginx_version >= 1011005
543512
if (peer->max_conns && peer->conns >= peer->max_conns) {
544513
continue;
545514
}
515+
#endif
546516

547517
#if (NGX_HTTP_UPSTREAM_CHECK)
548518
if (ngx_http_upstream_check_peer_down(peer->check_index)) {
@@ -580,3 +550,42 @@ ngx_http_upstream_get_vnswrr(ngx_http_upstream_vnswrr_peer_data_t *vnsp)
580550

581551
return best;
582552
}
553+
554+
555+
static void
556+
ngx_http_upstream_init_virtual_peers(ngx_http_upstream_rr_peers_t *peers,
557+
ngx_http_upstream_vnswrr_srv_conf_t *uvnscf,
558+
ngx_uint_t s, ngx_uint_t e)
559+
{
560+
ngx_uint_t i;
561+
ngx_int_t rindex;
562+
ngx_http_upstream_rr_peer_t *peer;
563+
ngx_http_upstream_rr_vpeers_t *vpeers;
564+
565+
if (uvnscf == NULL || peers == NULL) {
566+
return;
567+
}
568+
569+
vpeers = uvnscf->vpeers;
570+
571+
for (i = s; i < e; i++) {
572+
rindex = ngx_http_upstream_get_rr_peer(peers, &peer);
573+
if (rindex == NGX_ERROR) {
574+
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
575+
"get rr peer is null in upstream \"%V\" ",
576+
peers->name);
577+
if (i != 0) {
578+
i--;
579+
}
580+
581+
continue;
582+
}
583+
584+
vpeers[i].vpeer = peer;
585+
vpeers[i].rindex = rindex;
586+
}
587+
588+
uvnscf->vnumber = i;
589+
590+
return;
591+
}

tests/nginx-tests/tengine-tests/ngx_http_upstream_vnswrr.t

+22-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ http {
5858
server 127.0.0.1:8082 backup;
5959
}
6060
61+
upstream d {
62+
vnswrr;
63+
server 127.0.0.1:8081;
64+
server 127.0.0.1:8082;
65+
server 127.0.0.1:8083 weight=2;
66+
server 127.0.0.1:8084 down;
67+
}
68+
6169
server {
6270
listen 127.0.0.1:8081;
6371
listen 127.0.0.1:8082;
@@ -88,12 +96,16 @@ http {
8896
location /b {
8997
proxy_pass http://b;
9098
}
99+
100+
location /d {
101+
proxy_pass http://d;
102+
}
91103
}
92104
}
93105
94106
EOF
95107

96-
$t->try_run('no upstream vnswrr')->plan(7);
108+
$t->try_run('no upstream vnswrr')->plan(10);
97109

98110
###############################################################################
99111
my $r;
@@ -126,6 +138,15 @@ $list{http_get_body('/b')} += 1;
126138

127139
is($list{'8082'}, 1, 'vnswrr backup');
128140

141+
%list = ();
142+
$list{http_get_body('/d')} += 1;
143+
$list{http_get_body('/d')} += 1;
144+
$list{http_get_body('/d')} += 1;
145+
$list{http_get_body('/d')} += 1;
146+
147+
is($list{'8081'}, 1, 'weight 1');
148+
is($list{'8082'}, 1, 'weight 1');
149+
is($list{'8083'}, 2, 'weight 2');
129150
###############################################################################
130151

131152
sub http_get_body {

0 commit comments

Comments
 (0)