Mercurial > hg > nginx
comparison src/event/ngx_event_accept.c @ 6153:4f6efabcb09b
The "reuseport" option of the "listen" directive.
When configured, an individual listen socket on a given address is
created for each worker process. This allows to reduce in-kernel lock
contention on configurations with high accept rates, resulting in better
performance. As of now it works on Linux and DragonFly BSD.
Note that on Linux incoming connection requests are currently tied up
to a specific listen socket, and if some sockets are closed, connection
requests will be reset, see https://lwn.net/Articles/542629/. With
nginx, this may happen if the number of worker processes is reduced.
There is no such problem on DragonFly BSD.
Based on previous work by Sepherosa Ziehau and Yingqi Lu.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 20 May 2015 15:51:56 +0300 |
parents | adba26ff70b5 |
children | 8f038068f4bc |
comparison
equal
deleted
inserted
replaced
6152:3c344ea7d88b | 6153:4f6efabcb09b |
---|---|
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_event.h> | 10 #include <ngx_event.h> |
11 | 11 |
12 | 12 |
13 static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); | 13 static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); |
14 static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle); | 14 static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); |
15 static void ngx_close_accepted_connection(ngx_connection_t *c); | 15 static void ngx_close_accepted_connection(ngx_connection_t *c); |
16 | 16 |
17 | 17 |
18 void | 18 void |
19 ngx_event_accept(ngx_event_t *ev) | 19 ngx_event_accept(ngx_event_t *ev) |
107 continue; | 107 continue; |
108 } | 108 } |
109 } | 109 } |
110 | 110 |
111 if (err == NGX_EMFILE || err == NGX_ENFILE) { | 111 if (err == NGX_EMFILE || err == NGX_ENFILE) { |
112 if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle) | 112 if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle, 1) |
113 != NGX_OK) | 113 != NGX_OK) |
114 { | 114 { |
115 return; | 115 return; |
116 } | 116 } |
117 | 117 |
388 | 388 |
389 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 389 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
390 "accept mutex lock failed: %ui", ngx_accept_mutex_held); | 390 "accept mutex lock failed: %ui", ngx_accept_mutex_held); |
391 | 391 |
392 if (ngx_accept_mutex_held) { | 392 if (ngx_accept_mutex_held) { |
393 if (ngx_disable_accept_events(cycle) == NGX_ERROR) { | 393 if (ngx_disable_accept_events(cycle, 0) == NGX_ERROR) { |
394 return NGX_ERROR; | 394 return NGX_ERROR; |
395 } | 395 } |
396 | 396 |
397 ngx_accept_mutex_held = 0; | 397 ngx_accept_mutex_held = 0; |
398 } | 398 } |
411 ls = cycle->listening.elts; | 411 ls = cycle->listening.elts; |
412 for (i = 0; i < cycle->listening.nelts; i++) { | 412 for (i = 0; i < cycle->listening.nelts; i++) { |
413 | 413 |
414 c = ls[i].connection; | 414 c = ls[i].connection; |
415 | 415 |
416 if (c->read->active) { | 416 if (c == NULL || c->read->active) { |
417 continue; | 417 continue; |
418 } | 418 } |
419 | 419 |
420 if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) { | 420 if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) { |
421 return NGX_ERROR; | 421 return NGX_ERROR; |
425 return NGX_OK; | 425 return NGX_OK; |
426 } | 426 } |
427 | 427 |
428 | 428 |
429 static ngx_int_t | 429 static ngx_int_t |
430 ngx_disable_accept_events(ngx_cycle_t *cycle) | 430 ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all) |
431 { | 431 { |
432 ngx_uint_t i; | 432 ngx_uint_t i; |
433 ngx_listening_t *ls; | 433 ngx_listening_t *ls; |
434 ngx_connection_t *c; | 434 ngx_connection_t *c; |
435 | 435 |
436 ls = cycle->listening.elts; | 436 ls = cycle->listening.elts; |
437 for (i = 0; i < cycle->listening.nelts; i++) { | 437 for (i = 0; i < cycle->listening.nelts; i++) { |
438 | 438 |
439 c = ls[i].connection; | 439 c = ls[i].connection; |
440 | 440 |
441 if (!c->read->active) { | 441 if (c == NULL || !c->read->active) { |
442 continue; | 442 continue; |
443 } | 443 } |
444 | |
445 #if (NGX_HAVE_REUSEPORT) | |
446 | |
447 /* | |
448 * do not disable accept on worker's own sockets | |
449 * when disabling accept events due to accept mutex | |
450 */ | |
451 | |
452 if (ls[i].reuseport && !all) { | |
453 continue; | |
454 } | |
455 | |
456 #endif | |
444 | 457 |
445 if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT) | 458 if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT) |
446 == NGX_ERROR) | 459 == NGX_ERROR) |
447 { | 460 { |
448 return NGX_ERROR; | 461 return NGX_ERROR; |