diff options
| author | Maxim Dounin <mdounin@mdounin.ru> | 2021-12-30 01:08:46 +0300 |
|---|---|---|
| committer | Maxim Dounin <mdounin@mdounin.ru> | 2021-12-30 01:08:46 +0300 |
| commit | 96c342e56035a9676180d03b4659d5b05b9c6b07 (patch) | |
| tree | b723bd96fa33a0aeb570cbbfd6121d0b94289193 /src/event/ngx_event_accept.c | |
| parent | 614726621797f1267c41f8a8e488eeefff8bdf7f (diff) | |
| download | nginx-96c342e56035a9676180d03b4659d5b05b9c6b07.tar.gz nginx-96c342e56035a9676180d03b4659d5b05b9c6b07.tar.bz2 | |
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.
Diffstat (limited to '')
| -rw-r--r-- | src/event/ngx_event_accept.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index b05666c76..27038799d 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -11,6 +11,9 @@ static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); +#if (NGX_HAVE_EPOLLEXCLUSIVE) +static void ngx_reorder_accept_events(ngx_listening_t *ls); +#endif static void ngx_close_accepted_connection(ngx_connection_t *c); @@ -314,6 +317,10 @@ ngx_event_accept(ngx_event_t *ev) } } while (ev->available); + +#if (NGX_HAVE_EPOLLEXCLUSIVE) + ngx_reorder_accept_events(ls); +#endif } @@ -420,6 +427,57 @@ ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all) } +#if (NGX_HAVE_EPOLLEXCLUSIVE) + +static void +ngx_reorder_accept_events(ngx_listening_t *ls) +{ + ngx_connection_t *c; + + /* + * 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. To fix this, we re-add the socket periodically, so other + * workers will get a chance to accept connections. + */ + + if (!ngx_use_exclusive_accept) { + return; + } + +#if (NGX_HAVE_REUSEPORT) + + if (ls->reuseport) { + return; + } + +#endif + + c = ls->connection; + + if (c->requests++ % 16 != 0 + && ngx_accept_disabled <= 0) + { + return; + } + + if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT) + == NGX_ERROR) + { + return; + } + + if (ngx_add_event(c->read, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT) + == NGX_ERROR) + { + return; + } +} + +#endif + + static void ngx_close_accepted_connection(ngx_connection_t *c) { |
