comparison src/http/ngx_http_upstream_round_robin.c @ 324:f7cd062ee035 NGINX_0_6_6

nginx 0.6.6 *) Feature: the --sysconfdir=PATH option in configure. *) Feature: named locations. *) Feature: the $args variable can be set with the "set" directive. *) Feature: the $is_args variable. *) Bugfix: fair big weight upstream balancer. *) Bugfix: if a client has closed connection to mail proxy then nginx might not close connection to backend. *) Bugfix: if the same host without specified port was used as backend for HTTP and HTTPS, then nginx used only one port - 80 or 443. *) Bugfix: fix building on Solaris/amd64 by Sun Studio 11 and early versions; bug appeared in 0.6.4.
author Igor Sysoev <http://sysoev.ru>
date Mon, 30 Jul 2007 00:00:00 +0400
parents fc223117327f
children 9fc4ab6673f9
comparison
equal deleted inserted replaced
323:7e977a664d91 324:f7cd062ee035
5 5
6 6
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
11
12 static ngx_uint_t
13 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
10 14
11 15
12 ngx_int_t 16 ngx_int_t
13 ngx_http_upstream_init_round_robin(ngx_conf_t *cf, 17 ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
14 ngx_http_upstream_srv_conf_t *us) 18 ngx_http_upstream_srv_conf_t *us)
213 if (pc->tries == rrp->peers->number) { 217 if (pc->tries == rrp->peers->number) {
214 218
215 /* it's a first try - get a current peer */ 219 /* it's a first try - get a current peer */
216 220
217 for ( ;; ) { 221 for ( ;; ) {
218 rrp->current = rrp->peers->current; 222 rrp->current = ngx_http_upstream_get_peer(rrp->peers);
223
224 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
225 "get rr peer, current: %ui %i",
226 rrp->current,
227 rrp->peers->peer[rrp->current].current_weight);
219 228
220 n = rrp->current / (8 * sizeof(uintptr_t)); 229 n = rrp->current / (8 * sizeof(uintptr_t));
221 m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t)); 230 m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
222 231
223 if (!(rrp->tried[n] & m)) { 232 if (!(rrp->tried[n] & m)) {
234 if (now - peer->accessed > peer->fail_timeout) { 243 if (now - peer->accessed > peer->fail_timeout) {
235 peer->fails = 0; 244 peer->fails = 0;
236 break; 245 break;
237 } 246 }
238 247
248 peer->current_weight = 0;
249
239 } else { 250 } else {
240 rrp->tried[n] |= m; 251 rrp->tried[n] |= m;
241 } 252 }
242 253
243 pc->tries--; 254 pc->tries--;
244 } 255 }
245 256
246 rrp->peers->current++;
247
248 if (rrp->peers->current >= rrp->peers->number) {
249 rrp->peers->current = 0;
250 }
251
252 if (pc->tries) { 257 if (pc->tries) {
253 continue; 258 continue;
254 } 259 }
255 260
256 goto failed; 261 goto failed;
257 } 262 }
258 263
259 peer->current_weight--; 264 peer->current_weight--;
260
261 if (peer->current_weight == 0) {
262 peer->current_weight = peer->weight;
263
264 rrp->peers->current++;
265
266 if (rrp->peers->current >= rrp->peers->number) {
267 rrp->peers->current = 0;
268 }
269 }
270 265
271 } else { 266 } else {
272 for ( ;; ) { 267 for ( ;; ) {
273 n = rrp->current / (8 * sizeof(uintptr_t)); 268 n = rrp->current / (8 * sizeof(uintptr_t));
274 m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t)); 269 m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
288 if (now - peer->accessed > peer->fail_timeout) { 283 if (now - peer->accessed > peer->fail_timeout) {
289 peer->fails = 0; 284 peer->fails = 0;
290 break; 285 break;
291 } 286 }
292 287
288 peer->current_weight = 0;
289
293 } else { 290 } else {
294 rrp->tried[n] |= m; 291 rrp->tried[n] |= m;
295 } 292 }
296 293
297 pc->tries--; 294 pc->tries--;
309 306
310 goto failed; 307 goto failed;
311 } 308 }
312 309
313 peer->current_weight--; 310 peer->current_weight--;
314
315 if (peer->current_weight == 0) {
316 peer->current_weight = peer->weight;
317
318 if (rrp->current == rrp->peers->current) {
319 rrp->peers->current++;
320
321 if (rrp->peers->current >= rrp->peers->number) {
322 rrp->peers->current = 0;
323 }
324 }
325 }
326 } 311 }
327 312
328 rrp->tried[n] |= m; 313 rrp->tried[n] |= m;
329 } 314 }
330 315
350 335
351 return NGX_BUSY; 336 return NGX_BUSY;
352 } 337 }
353 338
354 339
340 static ngx_uint_t
341 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers)
342 {
343 ngx_uint_t i, n;
344 ngx_http_upstream_rr_peer_t *peer;
345
346 peer = &peers->peer[0];
347
348 for ( ;; ) {
349
350 for (i = 0; i < peers->number; i++) {
351
352 if (peer[i].current_weight <= 0) {
353 continue;
354 }
355
356 n = i;
357
358 while (i < peers->number - 1) {
359
360 i++;
361
362 if (peer[i].current_weight <= 0) {
363 continue;
364 }
365
366 if (peer[n].current_weight * 1000 / peer[i].current_weight
367 >= peer[n].weight * 1000 / peer[i].weight)
368 {
369 return n;
370 }
371
372 n = i;
373 }
374
375 if (peer[i].current_weight > 0) {
376 n = i;
377 }
378
379 return n;
380 }
381
382 for (i = 0; i < peers->number; i++) {
383 if (peer[i].fails == 0) {
384 peer[i].current_weight += peer[i].weight;
385
386 } else {
387 /* 1 allows to go to quick recovery when all peers failed */
388 peer[i].current_weight = 1;
389 }
390 }
391 }
392 }
393
394
355 void 395 void
356 ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data, 396 ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
357 ngx_uint_t state) 397 ngx_uint_t state)
358 { 398 {
359 ngx_http_upstream_rr_peer_data_t *rrp = data; 399 ngx_http_upstream_rr_peer_data_t *rrp = data;
383 /* ngx_lock_mutex(rrp->peers->mutex); */ 423 /* ngx_lock_mutex(rrp->peers->mutex); */
384 424
385 peer->fails++; 425 peer->fails++;
386 peer->accessed = now; 426 peer->accessed = now;
387 427
388 if (peer->current_weight > 1) { 428 peer->current_weight -= peer->weight / peer->max_fails;
389 peer->current_weight /= 2; 429
430 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
431 "free rr peer failed: %ui %i",
432 rrp->current, peer->current_weight);
433
434 if (peer->current_weight < 0) {
435 peer->current_weight = 0;
390 } 436 }
391 437
392 /* ngx_unlock_mutex(rrp->peers->mutex); */ 438 /* ngx_unlock_mutex(rrp->peers->mutex); */
393 } 439 }
394 440