comparison src/http/ngx_http_upstream_round_robin.c @ 326:9fc4ab6673f9 NGINX_0_6_7

nginx 0.6.7 *) Change: now the paths specified in the "include", "auth_basic_user_file", "perl_modules", "ssl_certificate", "ssl_certificate_key", and "ssl_client_certificate" directives are relative to directory of nginx configuration file nginx.conf, but not to nginx prefix directory. *) Change: the --sysconfdir=PATH option in configure was canceled. *) Change: the special make target "upgrade1" was defined for online upgrade of 0.1.x versions. *) Feature: the "server_name" and "valid_referers" directives support regular expressions. *) Feature: the "server" directive in the "upstream" context supports the "backup" parameter. *) Feature: the ngx_http_perl_module supports the $r->discard_request_body. *) Feature: the "add_header Last-Modified ..." directive changes the "Last-Modified" response header line. *) Bugfix: if an response different than 200 was returned to an request with body and connection went to the keep-alive state after the request, then nginx returned 400 for the next request. *) Bugfix: a segmentation fault occurred in worker process if invalid address was set in the "auth_http" directive. *) Bugfix: now nginx uses default listen backlog value 511 on all platforms except FreeBSD. Thanks to Jiang Hong. *) Bugfix: a worker process may got caught in an endless loop, if an "server" inside "upstream" block was marked as "down"; bug appeared in 0.6.6. *) Bugfix: now Solaris sendfilev() is not used to transfer the client request body to FastCGI-server via the unix domain socket.
author Igor Sysoev <http://sysoev.ru>
date Wed, 15 Aug 2007 00:00:00 +0400
parents f7cd062ee035
children 5e3b425174f6
comparison
equal deleted inserted replaced
325:f395c7a4c8a8 326:9fc4ab6673f9
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_http.h> 9 #include <ngx_http.h>
10 10
11 11
12 static int ngx_http_upstream_cmp_servers(const void *one, const void *two);
12 static ngx_uint_t 13 static ngx_uint_t
13 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers); 14 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
14 15
15 16
16 ngx_int_t 17 ngx_int_t
18 ngx_http_upstream_srv_conf_t *us) 19 ngx_http_upstream_srv_conf_t *us)
19 { 20 {
20 ngx_url_t u; 21 ngx_url_t u;
21 ngx_uint_t i, j, n; 22 ngx_uint_t i, j, n;
22 ngx_http_upstream_server_t *server; 23 ngx_http_upstream_server_t *server;
23 ngx_http_upstream_rr_peers_t *peers; 24 ngx_http_upstream_rr_peers_t *peers, *backup;
24 25
25 us->peer.init = ngx_http_upstream_init_round_robin_peer; 26 us->peer.init = ngx_http_upstream_init_round_robin_peer;
26 27
27 if (us->servers) { 28 if (us->servers) {
29 server = us->servers->elts;
30
28 n = 0; 31 n = 0;
29 server = us->servers->elts;
30 32
31 for (i = 0; i < us->servers->nelts; i++) { 33 for (i = 0; i < us->servers->nelts; i++) {
34 if (server[i].backup) {
35 continue;
36 }
37
32 n += server[i].naddrs; 38 n += server[i].naddrs;
33 } 39 }
34 40
35 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) 41 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
36 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); 42 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
37 if (peers == NULL) { 43 if (peers == NULL) {
38 return NGX_ERROR; 44 return NGX_ERROR;
39 } 45 }
40 46
47 peers->single = (n == 1);
41 peers->number = n; 48 peers->number = n;
42 peers->name = &us->host; 49 peers->name = &us->host;
43 50
44 n = 0; 51 n = 0;
45 52
46 for (i = 0; i < us->servers->nelts; i++) { 53 for (i = 0; i < us->servers->nelts; i++) {
47 for (j = 0; j < server[i].naddrs; j++) { 54 for (j = 0; j < server[i].naddrs; j++) {
55 if (server[i].backup) {
56 continue;
57 }
58
48 peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; 59 peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
49 peers->peer[n].socklen = server[i].addrs[j].socklen; 60 peers->peer[n].socklen = server[i].addrs[j].socklen;
50 peers->peer[n].name = server[i].addrs[j].name; 61 peers->peer[n].name = server[i].addrs[j].name;
51 peers->peer[n].weight = server[i].weight;
52 peers->peer[n].current_weight = server[i].weight;
53 peers->peer[n].max_fails = server[i].max_fails; 62 peers->peer[n].max_fails = server[i].max_fails;
54 peers->peer[n].fail_timeout = server[i].fail_timeout; 63 peers->peer[n].fail_timeout = server[i].fail_timeout;
55 peers->peer[n].down = server[i].down; 64 peers->peer[n].down = server[i].down;
65 peers->peer[n].weight = server[i].down ? 0 : server[i].weight;
66 peers->peer[n].current_weight = peers->peer[n].weight;
56 n++; 67 n++;
57 } 68 }
58 } 69 }
59 70
60 us->peer.data = peers; 71 us->peer.data = peers;
72
73 ngx_sort(&peers->peer[0], (size_t) n,
74 sizeof(ngx_http_upstream_rr_peer_t),
75 ngx_http_upstream_cmp_servers);
76
77 /* backup servers */
78
79 n = 0;
80
81 for (i = 0; i < us->servers->nelts; i++) {
82 if (!server[i].backup) {
83 continue;
84 }
85
86 n += server[i].naddrs;
87 }
88
89 if (n == 0) {
90 return NGX_OK;
91 }
92
93 backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
94 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
95 if (backup == NULL) {
96 return NGX_ERROR;
97 }
98
99 peers->single = 0;
100 backup->single = 0;
101 backup->number = n;
102 backup->name = &us->host;
103
104 n = 0;
105
106 for (i = 0; i < us->servers->nelts; i++) {
107 for (j = 0; j < server[i].naddrs; j++) {
108 if (!server[i].backup) {
109 continue;
110 }
111
112 backup->peer[n].sockaddr = server[i].addrs[j].sockaddr;
113 backup->peer[n].socklen = server[i].addrs[j].socklen;
114 backup->peer[n].name = server[i].addrs[j].name;
115 backup->peer[n].weight = server[i].weight;
116 backup->peer[n].current_weight = server[i].weight;
117 backup->peer[n].max_fails = server[i].max_fails;
118 backup->peer[n].fail_timeout = server[i].fail_timeout;
119 backup->peer[n].down = server[i].down;
120 n++;
121 }
122 }
123
124 peers->next = backup;
125
126 ngx_sort(&backup->peer[0], (size_t) n,
127 sizeof(ngx_http_upstream_rr_peer_t),
128 ngx_http_upstream_cmp_servers);
61 129
62 return NGX_OK; 130 return NGX_OK;
63 } 131 }
64 132
65 133
93 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); 161 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
94 if (peers == NULL) { 162 if (peers == NULL) {
95 return NGX_ERROR; 163 return NGX_ERROR;
96 } 164 }
97 165
166 peers->single = (n == 1);
98 peers->number = n; 167 peers->number = n;
99 peers->name = &us->host; 168 peers->name = &us->host;
100 169
101 n = 0; 170 n = 0;
102 171
111 n++; 180 n++;
112 } 181 }
113 182
114 us->peer.data = peers; 183 us->peer.data = peers;
115 184
185 /* implicitly defined upstream has no backup servers */
186
116 return NGX_OK; 187 return NGX_OK;
188 }
189
190
191 static int
192 ngx_http_upstream_cmp_servers(const void *one, const void *two)
193 {
194 ngx_http_upstream_rr_peer_t *first, *second;
195
196 first = (ngx_http_upstream_rr_peer_t *) one;
197 second = (ngx_http_upstream_rr_peer_t *) two;
198
199 return (first->weight < second->weight);
117 } 200 }
118 201
119 202
120 ngx_int_t 203 ngx_int_t
121 ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r, 204 ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
169 ngx_int_t 252 ngx_int_t
170 ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) 253 ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
171 { 254 {
172 ngx_http_upstream_rr_peer_data_t *rrp = data; 255 ngx_http_upstream_rr_peer_data_t *rrp = data;
173 256
174 time_t now; 257 time_t now;
175 uintptr_t m; 258 uintptr_t m;
176 ngx_uint_t i, n; 259 ngx_int_t rc;
177 ngx_connection_t *c; 260 ngx_uint_t i, n;
178 ngx_http_upstream_rr_peer_t *peer; 261 ngx_connection_t *c;
262 ngx_http_upstream_rr_peer_t *peer;
263 ngx_http_upstream_rr_peers_t *peers;
179 264
180 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, 265 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
181 "get rr peer, try: %ui", pc->tries); 266 "get rr peer, try: %ui", pc->tries);
182 267
183 now = ngx_time(); 268 now = ngx_time();
205 } 290 }
206 291
207 pc->cached = 0; 292 pc->cached = 0;
208 pc->connection = NULL; 293 pc->connection = NULL;
209 294
210 if (rrp->peers->number == 1) { 295 if (rrp->peers->single) {
211 peer = &rrp->peers->peer[0]; 296 peer = &rrp->peers->peer[0];
212 297
213 } else { 298 } else {
214 299
215 /* there are several peers */ 300 /* there are several peers */
317 pc->socklen = peer->socklen; 402 pc->socklen = peer->socklen;
318 pc->name = &peer->name; 403 pc->name = &peer->name;
319 404
320 /* ngx_unlock_mutex(rrp->peers->mutex); */ 405 /* ngx_unlock_mutex(rrp->peers->mutex); */
321 406
407 if (pc->tries == 1 && rrp->peers->next) {
408 pc->tries += rrp->peers->next->number;
409
410 n = rrp->peers->next->number / (8 * sizeof(uintptr_t)) + 1;
411 for (i = 0; i < n; i++) {
412 rrp->tried[i] = 0;
413 }
414 }
415
322 return NGX_OK; 416 return NGX_OK;
323 417
324 failed: 418 failed:
325 419
420 peers = rrp->peers;
421
422 if (peers->next) {
423
424 /* ngx_unlock_mutex(peers->mutex); */
425
426 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers");
427
428 rrp->peers = peers->next;
429 pc->tries = rrp->peers->number;
430
431 n = rrp->peers->number / (8 * sizeof(uintptr_t)) + 1;
432 for (i = 0; i < n; i++) {
433 rrp->tried[i] = 0;
434 }
435
436 rc = ngx_http_upstream_get_round_robin_peer(pc, rrp);
437
438 if (rc != NGX_BUSY) {
439 return rc;
440 }
441
442 /* ngx_lock_mutex(peers->mutex); */
443 }
444
326 /* all peers failed, mark them as live for quick recovery */ 445 /* all peers failed, mark them as live for quick recovery */
327 446
328 for (i = 0; i < rrp->peers->number; i++) { 447 for (i = 0; i < peers->number; i++) {
329 rrp->peers->peer[i].fails = 0; 448 peers->peer[i].fails = 0;
330 } 449 }
331 450
332 /* ngx_unlock_mutex(rrp->peers->mutex); */ 451 /* ngx_unlock_mutex(peers->mutex); */
333 452
334 pc->name = rrp->peers->name; 453 pc->name = peers->name;
335 454
336 return NGX_BUSY; 455 return NGX_BUSY;
337 } 456 }
338 457
339 458
408 return; 527 return;
409 } 528 }
410 529
411 /* TODO: NGX_PEER_KEEPALIVE */ 530 /* TODO: NGX_PEER_KEEPALIVE */
412 531
413 if (rrp->peers->number == 1) { 532 if (rrp->peers->single) {
414 pc->tries = 0; 533 pc->tries = 0;
415 return; 534 return;
416 } 535 }
417 536
418 if (state & NGX_PEER_FAILED) { 537 if (state & NGX_PEER_FAILED) {