Mercurial > hg > nginx-vendor-current
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) { |