Mercurial > hg > nginx
comparison src/event/ngx_event_accept.c @ 7992:e2d07e4ec636
Events: fixed balancing between workers with EPOLLEXCLUSIVE.
Linux with EPOLLEXCLUSIVE usually notifies only the process which was first
to add the listening socket to the epoll instance. As a result most of the
connections are handled by the first worker process (ticket #2285). To fix
this, we re-add the socket periodically, so other workers will get a chance
to accept connections.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 30 Dec 2021 01:08:46 +0300 |
parents | fdc3d40979b0 |
children |
comparison
equal
deleted
inserted
replaced
7991:57581198e51e | 7992:e2d07e4ec636 |
---|---|
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_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); | 13 static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); |
14 #if (NGX_HAVE_EPOLLEXCLUSIVE) | |
15 static void ngx_reorder_accept_events(ngx_listening_t *ls); | |
16 #endif | |
14 static void ngx_close_accepted_connection(ngx_connection_t *c); | 17 static void ngx_close_accepted_connection(ngx_connection_t *c); |
15 | 18 |
16 | 19 |
17 void | 20 void |
18 ngx_event_accept(ngx_event_t *ev) | 21 ngx_event_accept(ngx_event_t *ev) |
312 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { | 315 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { |
313 ev->available--; | 316 ev->available--; |
314 } | 317 } |
315 | 318 |
316 } while (ev->available); | 319 } while (ev->available); |
320 | |
321 #if (NGX_HAVE_EPOLLEXCLUSIVE) | |
322 ngx_reorder_accept_events(ls); | |
323 #endif | |
317 } | 324 } |
318 | 325 |
319 | 326 |
320 ngx_int_t | 327 ngx_int_t |
321 ngx_trylock_accept_mutex(ngx_cycle_t *cycle) | 328 ngx_trylock_accept_mutex(ngx_cycle_t *cycle) |
416 } | 423 } |
417 } | 424 } |
418 | 425 |
419 return NGX_OK; | 426 return NGX_OK; |
420 } | 427 } |
428 | |
429 | |
430 #if (NGX_HAVE_EPOLLEXCLUSIVE) | |
431 | |
432 static void | |
433 ngx_reorder_accept_events(ngx_listening_t *ls) | |
434 { | |
435 ngx_connection_t *c; | |
436 | |
437 /* | |
438 * Linux with EPOLLEXCLUSIVE usually notifies only the process which | |
439 * was first to add the listening socket to the epoll instance. As | |
440 * a result most of the connections are handled by the first worker | |
441 * process. To fix this, we re-add the socket periodically, so other | |
442 * workers will get a chance to accept connections. | |
443 */ | |
444 | |
445 if (!ngx_use_exclusive_accept) { | |
446 return; | |
447 } | |
448 | |
449 #if (NGX_HAVE_REUSEPORT) | |
450 | |
451 if (ls->reuseport) { | |
452 return; | |
453 } | |
454 | |
455 #endif | |
456 | |
457 c = ls->connection; | |
458 | |
459 if (c->requests++ % 16 != 0 | |
460 && ngx_accept_disabled <= 0) | |
461 { | |
462 return; | |
463 } | |
464 | |
465 if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT) | |
466 == NGX_ERROR) | |
467 { | |
468 return; | |
469 } | |
470 | |
471 if (ngx_add_event(c->read, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT) | |
472 == NGX_ERROR) | |
473 { | |
474 return; | |
475 } | |
476 } | |
477 | |
478 #endif | |
421 | 479 |
422 | 480 |
423 static void | 481 static void |
424 ngx_close_accepted_connection(ngx_connection_t *c) | 482 ngx_close_accepted_connection(ngx_connection_t *c) |
425 { | 483 { |