9
10
#include <ngx_http.h>
12
static ngx_int_t ngx_http_upstream_cmp_servers(const void *one,
15
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
13
static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
14
ngx_http_upstream_rr_peer_data_t *rrp);
18
static ngx_int_t ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc,
20
static void ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc,
39
48
n += server[i].naddrs;
49
w += server[i].naddrs * server[i].weight;
53
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
54
"no servers in upstream \"%V\" in %s:%ui",
55
&us->host, us->file_name, us->line);
42
59
peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
63
82
peers->peer[n].max_fails = server[i].max_fails;
64
83
peers->peer[n].fail_timeout = server[i].fail_timeout;
65
84
peers->peer[n].down = server[i].down;
66
peers->peer[n].weight = server[i].down ? 0 : server[i].weight;
67
peers->peer[n].current_weight = peers->peer[n].weight;
85
peers->peer[n].weight = server[i].weight;
86
peers->peer[n].effective_weight = server[i].weight;
87
peers->peer[n].current_weight = 0;
72
92
us->peer.data = peers;
74
ngx_sort(&peers->peer[0], (size_t) n,
75
sizeof(ngx_http_upstream_rr_peer_t),
76
ngx_http_upstream_cmp_servers);
78
94
/* backup servers */
82
99
for (i = 0; i < us->servers->nelts; i++) {
83
100
if (!server[i].backup) {
114
134
backup->peer[n].socklen = server[i].addrs[j].socklen;
115
135
backup->peer[n].name = server[i].addrs[j].name;
116
136
backup->peer[n].weight = server[i].weight;
117
backup->peer[n].current_weight = server[i].weight;
137
backup->peer[n].effective_weight = server[i].weight;
138
backup->peer[n].current_weight = 0;
118
139
backup->peer[n].max_fails = server[i].max_fails;
119
140
backup->peer[n].fail_timeout = server[i].fail_timeout;
120
141
backup->peer[n].down = server[i].down;
125
146
peers->next = backup;
127
ngx_sort(&backup->peer[0], (size_t) n,
128
sizeof(ngx_http_upstream_rr_peer_t),
129
ngx_http_upstream_cmp_servers);
135
152
/* an upstream implicitly defined by proxy_pass, etc. */
137
if (us->port == 0 && us->default_port == 0) {
138
155
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
139
156
"no port in upstream \"%V\" in %s:%ui",
140
157
&us->host, us->file_name, us->line);
173
192
peers->peer[i].socklen = u.addrs[i].socklen;
174
193
peers->peer[i].name = u.addrs[i].name;
175
194
peers->peer[i].weight = 1;
176
peers->peer[i].current_weight = 1;
195
peers->peer[i].effective_weight = 1;
196
peers->peer[i].current_weight = 0;
177
197
peers->peer[i].max_fails = 1;
178
198
peers->peer[i].fail_timeout = 10;
190
ngx_http_upstream_cmp_servers(const void *one, const void *two)
192
ngx_http_upstream_rr_peer_t *first, *second;
194
first = (ngx_http_upstream_rr_peer_t *) one;
195
second = (ngx_http_upstream_rr_peer_t *) two;
197
return (first->weight < second->weight);
202
210
ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
203
211
ngx_http_upstream_srv_conf_t *us)
219
227
rrp->peers = us->peer.data;
220
228
rrp->current = 0;
222
if (rrp->peers->number <= 8 * sizeof(uintptr_t)) {
230
n = rrp->peers->number;
232
if (rrp->peers->next && rrp->peers->next->number > n) {
233
n = rrp->peers->next->number;
236
if (n <= 8 * sizeof(uintptr_t)) {
223
237
rrp->tried = &rrp->data;
227
n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
228
/ (8 * sizeof(uintptr_t));
241
n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t));
230
243
rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
231
244
if (rrp->tried == NULL) {
279
292
peers->number = ur->naddrs;
280
293
peers->name = &ur->host;
282
for (i = 0; i < ur->naddrs; i++) {
284
len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
286
p = ngx_palloc(r->pool, len);
291
len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, INET_ADDRSTRLEN);
292
len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
294
sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
299
sin->sin_family = AF_INET;
300
sin->sin_port = htons(ur->port);
301
sin->sin_addr.s_addr = ur->addrs[i];
303
peers->peer[i].sockaddr = (struct sockaddr *) sin;
304
peers->peer[i].socklen = sizeof(struct sockaddr_in);
305
peers->peer[i].name.len = len;
306
peers->peer[i].name.data = p;
307
peers->peer[i].weight = 1;
308
peers->peer[i].current_weight = 1;
309
peers->peer[i].max_fails = 1;
310
peers->peer[i].fail_timeout = 10;
296
peers->peer[0].sockaddr = ur->sockaddr;
297
peers->peer[0].socklen = ur->socklen;
298
peers->peer[0].name = ur->host;
299
peers->peer[0].weight = 1;
300
peers->peer[0].effective_weight = 1;
301
peers->peer[0].current_weight = 0;
302
peers->peer[0].max_fails = 1;
303
peers->peer[0].fail_timeout = 10;
307
for (i = 0; i < ur->naddrs; i++) {
309
len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
311
p = ngx_pnalloc(r->pool, len);
316
len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, NGX_INET_ADDRSTRLEN);
317
len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
319
sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
324
sin->sin_family = AF_INET;
325
sin->sin_port = htons(ur->port);
326
sin->sin_addr.s_addr = ur->addrs[i];
328
peers->peer[i].sockaddr = (struct sockaddr *) sin;
329
peers->peer[i].socklen = sizeof(struct sockaddr_in);
330
peers->peer[i].name.len = len;
331
peers->peer[i].name.data = p;
332
peers->peer[i].weight = 1;
333
peers->peer[i].effective_weight = 1;
334
peers->peer[i].current_weight = 0;
335
peers->peer[i].max_fails = 1;
336
peers->peer[i].fail_timeout = 10;
313
340
rrp->peers = peers;
331
358
r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
332
359
r->upstream->peer.tries = rrp->peers->number;
333
360
#if (NGX_HTTP_SSL)
334
r->upstream->peer.set_session =
335
ngx_http_upstream_set_round_robin_peer_session;
336
r->upstream->peer.save_session =
337
ngx_http_upstream_save_round_robin_peer_session;
361
r->upstream->peer.set_session = ngx_http_upstream_empty_set_session;
362
r->upstream->peer.save_session = ngx_http_upstream_empty_save_session;
347
372
ngx_http_upstream_rr_peer_data_t *rrp = data;
354
376
ngx_http_upstream_rr_peer_t *peer;
355
377
ngx_http_upstream_rr_peers_t *peers;
357
379
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
358
380
"get rr peer, try: %ui", pc->tries);
362
382
/* ngx_lock_mutex(rrp->peers->mutex); */
364
if (rrp->peers->last_cached) {
366
/* cached connection */
368
c = rrp->peers->cached[rrp->peers->last_cached];
369
rrp->peers->last_cached--;
371
/* ngx_unlock_mutex(ppr->peers->mutex); */
374
c->read->lock = c->read->own_lock;
375
c->write->lock = c->write->own_lock;
385
385
pc->connection = NULL;
387
387
if (rrp->peers->single) {
388
388
peer = &rrp->peers->peer[0];
392
396
/* there are several peers */
394
if (pc->tries == rrp->peers->number) {
396
/* it's a first try - get a current peer */
401
rrp->current = ngx_http_upstream_get_peer(rrp->peers);
403
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
404
"get rr peer, current: %ui %i",
406
rrp->peers->peer[rrp->current].current_weight);
408
n = rrp->current / (8 * sizeof(uintptr_t));
409
m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
411
if (!(rrp->tried[n] & m)) {
412
peer = &rrp->peers->peer[rrp->current];
416
if (peer->max_fails == 0
417
|| peer->fails < peer->max_fails)
422
if (now - peer->accessed > peer->fail_timeout) {
427
peer->current_weight = 0;
436
if (pc->tries == 0) {
441
ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
442
"round robin upstream stuck on %ui tries",
448
peer->current_weight--;
455
n = rrp->current / (8 * sizeof(uintptr_t));
456
m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
458
if (!(rrp->tried[n] & m)) {
460
peer = &rrp->peers->peer[rrp->current];
464
if (peer->max_fails == 0
465
|| peer->fails < peer->max_fails)
470
if (now - peer->accessed > peer->fail_timeout) {
475
peer->current_weight = 0;
486
if (rrp->current >= rrp->peers->number) {
490
if (pc->tries == 0) {
495
ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
496
"round robin upstream stuck on %ui tries",
502
peer->current_weight--;
398
peer = ngx_http_upstream_get_peer(rrp);
404
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
405
"get rr peer, current: %ui %i",
406
rrp->current, peer->current_weight);
508
409
pc->sockaddr = peer->sockaddr;
567
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers)
464
static ngx_http_upstream_rr_peer_t *
465
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
570
ngx_http_upstream_rr_peer_t *peer;
572
peer = &peers->peer[0];
576
for (i = 0; i < peers->number; i++) {
578
if (peer[i].current_weight <= 0) {
584
while (i < peers->number - 1) {
588
if (peer[i].current_weight <= 0) {
592
if (peer[n].current_weight * 1000 / peer[i].current_weight
593
> peer[n].weight * 1000 / peer[i].weight)
601
if (peer[i].current_weight > 0) {
608
for (i = 0; i < peers->number; i++) {
609
peer[i].current_weight = peer[i].weight;
471
ngx_http_upstream_rr_peer_t *peer, *best;
478
for (i = 0; i < rrp->peers->number; i++) {
480
n = i / (8 * sizeof(uintptr_t));
481
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
483
if (rrp->tried[n] & m) {
487
peer = &rrp->peers->peer[i];
494
&& peer->fails >= peer->max_fails
495
&& now - peer->checked <= peer->fail_timeout)
500
peer->current_weight += peer->effective_weight;
501
total += peer->effective_weight;
503
if (peer->effective_weight < peer->weight) {
504
peer->effective_weight++;
507
if (best == NULL || peer->current_weight > best->current_weight) {
516
i = best - &rrp->peers->peer[0];
520
n = i / (8 * sizeof(uintptr_t));
521
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
525
best->current_weight -= total;
551
peer = &rrp->peers->peer[rrp->current];
638
553
if (state & NGX_PEER_FAILED) {
639
554
now = ngx_time();
641
peer = &rrp->peers->peer[rrp->current];
643
556
/* ngx_lock_mutex(rrp->peers->mutex); */
646
559
peer->accessed = now;
648
562
if (peer->max_fails) {
649
peer->current_weight -= peer->weight / peer->max_fails;
563
peer->effective_weight -= peer->weight / peer->max_fails;
652
566
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
653
567
"free rr peer failed: %ui %i",
654
rrp->current, peer->current_weight);
568
rrp->current, peer->effective_weight);
656
if (peer->current_weight < 0) {
657
peer->current_weight = 0;
570
if (peer->effective_weight < 0) {
571
peer->effective_weight = 0;
660
574
/* ngx_unlock_mutex(rrp->peers->mutex); */
665
if (rrp->current >= rrp->peers->number) {
578
/* mark peer live if check passed */
580
if (peer->accessed < peer->checked) {