From xeioex at nginx.com Mon Feb 1 12:24:42 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 01 Feb 2021 12:24:42 +0000 Subject: [njs] HTTP: added js header filter. Message-ID: details: https://hg.nginx.org/njs/rev/c0c6539ae445 branches: changeset: 1597:c0c6539ae445 user: Dmitry Volyntsev date: Mon Feb 01 12:24:17 2021 +0000 description: HTTP: added js header filter. diffstat: nginx/config | 2 +- nginx/ngx_http_js_module.c | 69 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diffs (153 lines): diff -r 63147f56e418 -r c0c6539ae445 nginx/config --- a/nginx/config Tue Jan 26 12:52:17 2021 +0000 +++ b/nginx/config Mon Feb 01 12:24:17 2021 +0000 @@ -5,7 +5,7 @@ NJS_SRCS="$ngx_addon_dir/ngx_js.c \ $ngx_addon_dir/ngx_js_fetch.c" if [ $HTTP != NO ]; then - ngx_module_type=HTTP + ngx_module_type=HTTP_FILTER ngx_module_name=ngx_http_js_module ngx_module_incs="$ngx_addon_dir/../src $ngx_addon_dir/../build" ngx_module_deps="$ngx_addon_dir/../build/libnjs.a $NJS_DEPS" diff -r 63147f56e418 -r c0c6539ae445 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Jan 26 12:52:17 2021 +0000 +++ b/nginx/ngx_http_js_module.c Mon Feb 01 12:24:17 2021 +0000 @@ -24,6 +24,7 @@ typedef struct { typedef struct { ngx_str_t content; + ngx_str_t header_filter; } ngx_http_js_loc_conf_t; @@ -76,6 +77,7 @@ static void ngx_http_js_content_event_ha static void ngx_http_js_content_write_event_handler(ngx_http_request_t *r); static void ngx_http_js_content_finalize(ngx_http_request_t *r, ngx_http_js_ctx_t *ctx); +static ngx_int_t ngx_http_js_header_filter(ngx_http_request_t *r); static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_js_init_vm(ngx_http_request_t *r); @@ -189,6 +191,7 @@ static void ngx_http_js_handle_vm_event( static void ngx_http_js_handle_event(ngx_http_request_t *r, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); +static ngx_int_t ngx_http_js_init(ngx_conf_t *cf); static char *ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_js_import(ngx_conf_t *cf, ngx_command_t *cmd, @@ -240,13 +243,20 @@ static ngx_command_t ngx_http_js_comman 0, NULL }, + { ngx_string("js_header_filter"), + NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_js_loc_conf_t, header_filter), + NULL }, + ngx_null_command }; static ngx_http_module_t ngx_http_js_module_ctx = { NULL, /* preconfiguration */ - NULL, /* postconfiguration */ + ngx_http_js_init, /* postconfiguration */ ngx_http_js_create_main_conf, /* create main configuration */ ngx_http_js_init_main_conf, /* init main configuration */ @@ -275,6 +285,9 @@ ngx_module_t ngx_http_js_module = { }; +static ngx_http_output_header_filter_pt ngx_http_next_header_filter; + + static njs_external_t ngx_http_js_ext_request[] = { { @@ -737,6 +750,48 @@ ngx_http_js_content_finalize(ngx_http_re static ngx_int_t +ngx_http_js_header_filter(ngx_http_request_t *r) +{ + ngx_int_t rc; + njs_int_t pending; + ngx_http_js_ctx_t *ctx; + ngx_http_js_loc_conf_t *jlcf; + + jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); + + if (jlcf->header_filter.len == 0) { + return ngx_http_next_header_filter(r); + } + + rc = ngx_http_js_init_vm(r); + + if (rc == NGX_ERROR || rc == NGX_DECLINED) { + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + + pending = njs_vm_pending(ctx->vm); + + rc = ngx_js_call(ctx->vm, &jlcf->header_filter, &ctx->request, + r->connection->log); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (!pending && rc == NGX_AGAIN) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "async operation inside \"%V\" header filter", + &jlcf->header_filter); + return NGX_ERROR; + } + + return ngx_http_next_header_filter(r); +} + + +static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -3220,6 +3275,16 @@ ngx_http_js_init_main_conf(ngx_conf_t *c } +static ngx_int_t +ngx_http_js_init(ngx_conf_t *cf) +{ + ngx_http_next_header_filter = ngx_http_top_header_filter; + ngx_http_top_header_filter = ngx_http_js_header_filter; + + return NGX_OK; +} + + static char * ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -3444,6 +3509,7 @@ ngx_http_js_create_loc_conf(ngx_conf_t * * set by ngx_pcalloc(): * * conf->content = { 0, NULL }; + * conf->header_filter = { 0, NULL }; */ return conf; @@ -3457,6 +3523,7 @@ ngx_http_js_merge_loc_conf(ngx_conf_t *c ngx_http_js_loc_conf_t *conf = child; ngx_conf_merge_str_value(conf->content, prev->content, ""); + ngx_conf_merge_str_value(conf->header_filter, prev->header_filter, ""); return NGX_CONF_OK; } From xeioex at nginx.com Mon Feb 1 16:14:19 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 01 Feb 2021 16:14:19 +0000 Subject: [njs] HTTP: fixed module type introduced in c0c6539ae445. Message-ID: details: https://hg.nginx.org/njs/rev/8d4b7b3ae73d branches: changeset: 1598:8d4b7b3ae73d user: Dmitry Volyntsev date: Mon Feb 01 16:13:10 2021 +0000 description: HTTP: fixed module type introduced in c0c6539ae445. diffstat: nginx/config | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r c0c6539ae445 -r 8d4b7b3ae73d nginx/config --- a/nginx/config Mon Feb 01 12:24:17 2021 +0000 +++ b/nginx/config Mon Feb 01 16:13:10 2021 +0000 @@ -5,7 +5,7 @@ NJS_SRCS="$ngx_addon_dir/ngx_js.c \ $ngx_addon_dir/ngx_js_fetch.c" if [ $HTTP != NO ]; then - ngx_module_type=HTTP_FILTER + ngx_module_type=HTTP_AUX_FILTER ngx_module_name=ngx_http_js_module ngx_module_incs="$ngx_addon_dir/../src $ngx_addon_dir/../build" ngx_module_deps="$ngx_addon_dir/../build/libnjs.a $NJS_DEPS" From ru at nginx.com Tue Feb 2 12:20:43 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 02 Feb 2021 12:20:43 +0000 Subject: [nginx] HTTP/2: lingering close changed to handle NGX_AGAIN. Message-ID: details: https://hg.nginx.org/nginx/rev/519b55453c45 branches: changeset: 7765:519b55453c45 user: Ruslan Ermilov date: Mon Feb 01 16:42:50 2021 +0300 description: HTTP/2: lingering close changed to handle NGX_AGAIN. This part somehow slipped away from c5840ca2063d. While it is not expected to be needed in case of lingering close, it is good to keep it for correctness (see 2b5528023f6b). diffstat: src/http/v2/ngx_http_v2.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff -r ecc0ae881a25 -r 519b55453c45 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Tue Jan 26 12:39:28 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Mon Feb 01 16:42:50 2021 +0300 @@ -807,6 +807,10 @@ ngx_http_v2_lingering_close_handler(ngx_ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n); + if (n == NGX_AGAIN) { + break; + } + if (n == NGX_ERROR || n == 0) { ngx_http_close_connection(c); return; From goodlord at gmail.com Tue Feb 2 13:22:14 2021 From: goodlord at gmail.com (Surinder Sund) Date: Tue, 2 Feb 2021 18:52:14 +0530 Subject: NGINX-QUIC: OPENSSL_internal:NO_SUPPORTED_VERSIONS_ENABLED In-Reply-To: References: Message-ID: No no. UDP is open. Anyway, I've given up trying to get it working. On Tue, Dec 22, 2020 at 10:34 PM Jonny Barnes wrote: > Do you have a firewall setup on the server to only allow traffic on 443 if > it?s tcp traffic? > > Rule needs to be added for udp as well > > On Tue, 22 Dec 2020 at 13:08, Surinder Sund wrote: > >> Thank You Johny. >> >> I fixed that (In fact, I'd fixed it in the trial machine earlier, but >> when I restored a backup, it came back in). >> >> Unfortunately, the error still remains. >> >> Pls see the picture below. I can confirm that the traffic is hitting >> 443/UDP, but nothing is being returned. >> >> >> https://drive.google.com/file/d/1knHKb_jUcjdY71wCz-w1TG4QupxH9CN3/view?usp=sharing >> >> [image: image.png] >> >> Looks like no cigar for me yet. >> >> >> >> >> >> On Mon, Dec 21, 2020 at 10:24 PM Jonny Barnes >> wrote: >> >>> I think your Alt Svc header should be pointing to port 443, not 8443 >>> >>> On Mon, 21 Dec 2020 at 14:41, Surinder Sund wrote: >>> >>>> forgot to add that this affects only http3 requests [I've tested from >>>> more than one machine and multiple clients, including cURL and FF] >>>> >>>> http2 request work fine with no change in configuration. >>>> >>>> On Mon, Dec 21, 2020 at 7:16 PM Surinder Sund >>>> wrote: >>>> >>>>> I'm trying to get NGINX QUIC to work on a fresh install of Ubuntu >>>>> 20.04. >>>>> >>>>> But I'm getting this error: >>>>> >>>>> **1 SSL_do_handshake() failed (SSL: error:10000118:SSL >>>>> routines:OPENSSL_internal:NO_SUPPORTED_VERSIONS_ENABLED)* >>>>> >>>>> Looks like some issue with the way Boringssl is set up, or being used >>>>> by Nginx? >>>>> >>>>> >>>>> HOW I BUILT BORINGSSL >>>>> >>>>> cd boringssl; mkdir build ; cd build ; cmake -GNinja .. >>>>> ninja >>>>> >>>>> NGINX DETAILS >>>>> >>>>> *~/nginx-quic# nginx -V* >>>>> >>>>> nginx version: nginx/1.19.6 >>>>> built by gcc 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) >>>>> built with OpenSSL 1.1.1 (compatible; BoringSSL) (running with >>>>> BoringSSL) >>>>> TLS SNI support enabled >>>>> configure arguments: --with-debug --with-http_v3_module >>>>> --with-cc-opt=-I../boringssl/include >>>>> --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' >>>>> --with-http_quic_module --with-stream_quic_module >>>>> --with-http_image_filter_module --with-http_sub_module --with-stream >>>>> --add-module=/usr/local/src/ngx_brotli --prefix=/etc/nginx >>>>> --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules >>>>> --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log >>>>> --pid-path=/var/run/nginx.pid >>>>> >>>>> >>>>> HOW I BUILT NGINX QUIC: >>>>> >>>>> cd ~/nginx-quic ; >>>>> ./auto/configure --with-debug --with-http_v3_module \ >>>>> --with-cc-opt="-I../boringssl/include" \ >>>>> --with-ld-opt="-L../boringssl/build/ssl \ >>>>> -L../boringssl/build/crypto" \ >>>>> --with-http_quic_module --with-stream_quic_module >>>>> --with-http_image_filter_module --with-http_sub_module --with-stream >>>>> --add-module=/usr/local/src/ngx_brotli --prefix=/etc/nginx >>>>> --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules >>>>> --conf-path=/etc/nginx/nginx.conf >>>>> --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid >>>>> >>>>> >>>>> MY NGINX BUILD CONFIGURATION SUMMARY: >>>>> >>>>> Configuration summary >>>>> + using system PCRE library >>>>> + using system OpenSSL library >>>>> + using system zlib library >>>>> >>>>> nginx path prefix: "/etc/nginx" >>>>> nginx binary file: "/usr/sbin/nginx" >>>>> nginx modules path: "/usr/lib/nginx/modules" >>>>> nginx configuration prefix: "/etc/nginx" >>>>> nginx configuration file: "/etc/nginx/nginx.conf" >>>>> nginx pid file: "/var/run/nginx.pid" >>>>> nginx error log file: "/var/log/nginx/error.log" >>>>> nginx http access log file: "/etc/nginx/logs/access.log" >>>>> nginx http client request body temporary files: "client_body_temp" >>>>> nginx http proxy temporary files: "proxy_temp" >>>>> nginx http fastcgi temporary files: "fastcgi_temp" >>>>> nginx http uwsgi temporary files: "uwsgi_temp" >>>>> nginx http scgi temporary files: "scgi_temp" >>>>> >>>>> >>>>> >>>>> >>>>> MY SITE CONFIGURATION >>>>> >>>>> >>>>> listen 80; >>>>> listen [::]:80; >>>>> listen 443 ssl http2 fastopen=150; >>>>> listen [::]:443 ipv6only=on ssl fastopen=150; >>>>> include snippets/ssl-params.conf; >>>>> server_name blah.blah; >>>>> root /var/wordpress; >>>>> index index.html index.htm index.php; >>>>> access_log /var/log/nginx/xx.log; >>>>> error_log /var/log/nginx/xx-error_log; >>>>> ssl_early_data on; >>>>> listen 443 http3 reuseport; >>>>> listen [::]:443 http3 reuseport; >>>>> add_header Alt-Svc '$http3=":8443"; ma=86400'; >>>>> >>>>> >>>>> *in nginx.conf I've added this:* >>>>> >>>>> ssl_protocols TLSv1.3; #disabled 1.1 & 1.2 >>>>> >>>>> >>>>> UDP is open on port 441, I've double checked this from the outside. So >>>>> it's not a port issue. >>>>> >>>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 34331 bytes Desc: not available URL: From andrey at apporto.com Tue Feb 2 14:30:04 2021 From: andrey at apporto.com (Andrey Khramov) Date: Tue, 2 Feb 2021 14:30:04 +0000 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo Message-ID: Hello, there I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. But I couldn't test HTTP/3 (QUIC). I built the quic branch of nginx-quic repo according to README of that repo. The configuration options follows as below: $ ./auto/configure --prefix=/etc/nginx \ --sbin-path=/usr/sbin/nginx \ --conf-path=/etc/nginx/nginx.conf \ --pid-path=/var/run/nginx.pid \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-debug \ --with-http_v2_module --with-http_ssl_module \ --with-http_v3_module --with-http_quic_module \ --with-stream_quic_module \ --with-cc-opt="-I../boringssl/include" \ --with-ld-opt="-L../boringssl/build/ssl \ -L../boringssl/build/crypto" $ make To install the nginx-quic, I installed the nginx 1.19.6 package on Ubuntu 18.04 and replaced the nginx binary with the nginx-quic: $ sudo cp objs/nginx /usr/sbin/ I configured that the nginx-quic works as load-balancer of HTTPS: HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat (8080 port) The configuration file (nginx.conf) follows as below: user nginx; worker_processes auto; events { worker_connections 1024; } http { log_format quic '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" "$quic" "$http3"'; access_log /var/log/nginx/access.log quic; error_log /var/log/nginx/error.log debug; server { listen 7443 http3 reuseport; # Enable HTTP/3. listen 7443 ssl; # Enable HTTP/1.1 (optional). ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; ssl_certificate_key /etc/ssl/private/example.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; location / { add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise that QUIC is available add_header QUIC-Status $quic; # Sent when QUIC was used proxy_pass http://backend1; } } server { listen 8443 ssl http2; ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; ssl_certificate_key /etc/ssl/private/example.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; location / { proxy_pass http://backend2; } } upstream backend1 { ip_hash; server localhost max_fails=3 fail_timeout=30s; } upstream backend2 { ip_hash; server localhost max_fails=3 fail_timeout=30s; } } I opened UDP 7443 port on the cloud server (AWS). I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) and the browsers (Firefox 85 and Chrome 88) according to https://quic.nginx.org/readme.html. I got the right result with the client tools, but I didn't get the right result with the browsers. When connecting 7443 port with the browsers, I get the HTTP/1.1 now. When connecting 8443 port with the browsers, I get the HTTP/2 now. I hope any suggestions and help. Thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Tue Feb 2 14:46:32 2021 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 2 Feb 2021 17:46:32 +0300 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo In-Reply-To: References: Message-ID: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> Hi Andrey, > On 2 Feb 2021, at 17:30, Andrey Khramov wrote: > > Hello, there > > I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. > But I couldn't test HTTP/3 (QUIC). > > I built the quic branch of nginx-quic repo according to README of that repo. > The configuration options follows as below: > $ ./auto/configure --prefix=/etc/nginx \ > --sbin-path=/usr/sbin/nginx \ > --conf-path=/etc/nginx/nginx.conf \ > --pid-path=/var/run/nginx.pid \ > --error-log-path=/var/log/nginx/error.log \ > --http-log-path=/var/log/nginx/access.log \ > --with-debug \ > --with-http_v2_module --with-http_ssl_module \ > --with-http_v3_module --with-http_quic_module \ > --with-stream_quic_module \ > --with-cc-opt="-I../boringssl/include" \ > --with-ld-opt="-L../boringssl/build/ssl \ > -L../boringssl/build/crypto" > $ make > > To install the nginx-quic, I installed the nginx 1.19.6 package on Ubuntu 18.04 and replaced the nginx binary with the nginx-quic: > $ sudo cp objs/nginx /usr/sbin/ > > I configured that the nginx-quic works as load-balancer of HTTPS: > HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat (8080 port) > > The configuration file (nginx.conf) follows as below: > > user nginx; > worker_processes auto; > > events { > worker_connections 1024; > } > > http { > log_format quic '$remote_addr - $remote_user [$time_local] ' > '"$request" $status $body_bytes_sent ' > '"$http_referer" "$http_user_agent" "$quic" "$http3"'; > > access_log /var/log/nginx/access.log quic; > error_log /var/log/nginx/error.log debug; > > server { > > listen 7443 http3 reuseport; # Enable HTTP/3. > listen 7443 ssl; # Enable HTTP/1.1 (optional). > > ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; > ssl_certificate_key /etc/ssl/private/example.key; > ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; > > location / { > add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise that QUIC is available > add_header QUIC-Status $quic; # Sent when QUIC was used > > proxy_pass http://backend1 ; > } > } > > server { > listen 8443 ssl http2; > > ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; > ssl_certificate_key /etc/ssl/private/example.key; > ssl_protocols TLSv1 TLSv1.1 TLSv1.2; > > location / { > proxy_pass http://backend2 ; > } > } > > upstream backend1 { > ip_hash; > server localhost max_fails=3 fail_timeout=30s; > } > > upstream backend2 { > ip_hash; > server localhost max_fails=3 fail_timeout=30s; > } > } > > I opened UDP 7443 port on the cloud server (AWS). > > I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) and the browsers (Firefox 85 and Chrome 88) according to https://quic.nginx.org/readme.html . > I got the right result with the client tools, but I didn't get the right result with the browsers. > > When connecting 7443 port with the browsers, I get the HTTP/1.1 now. > When connecting 8443 port with the browsers, I get the HTTP/2 now. The first request goes over HTTP/1, but then it?s supposed to switch to HTTP/3 if everything is right. Does https://quic.nginx.org/ detect QUIC support in your browsers? If yes, please follow the ?QUIC TEST? link at the top and run the test. Also, make sure QUIC/HTTP/3 is enabled in the browser. In Firefox open the about:config page make sure http.http3.enabled parameter is ?true?. > I hope any suggestions and help. > Thanks. > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel ? Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Tue Feb 2 15:21:09 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 02 Feb 2021 15:21:09 +0000 Subject: [njs] Fixed safe mode bypass in Function constructor. Message-ID: details: https://hg.nginx.org/njs/rev/a41cd80e2f3a branches: changeset: 1599:a41cd80e2f3a user: Dmitry Volyntsev date: Mon Feb 01 02:16:51 2021 +0100 description: Fixed safe mode bypass in Function constructor. This closes #367 pull request on Github. Thanks bux.patryk at gmail.com for prodding it. diffstat: src/njs_function.c | 82 ++++++++++++++++++++++++++++------------------- src/test/njs_unit_test.c | 25 ++++++++++++++ 2 files changed, 74 insertions(+), 33 deletions(-) diffs (150 lines): diff -r 8d4b7b3ae73d -r a41cd80e2f3a src/njs_function.c --- a/src/njs_function.c Mon Feb 01 16:13:10 2021 +0000 +++ b/src/njs_function.c Mon Feb 01 02:16:51 2021 +0100 @@ -869,41 +869,31 @@ static njs_int_t njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_chb_t chain; - njs_int_t ret; - njs_str_t str, file; - njs_uint_t i; - njs_value_t *body; - njs_lexer_t lexer; - njs_parser_t *parser; - njs_vm_code_t *code; - njs_function_t *function; - njs_generator_t generator; - njs_parser_scope_t *scope; - njs_function_lambda_t *lambda; + njs_chb_t chain; + njs_int_t ret; + njs_str_t str, file; + njs_uint_t i; + njs_lexer_t lexer; + njs_parser_t *parser; + njs_vm_code_t *code; + njs_function_t *function; + njs_generator_t generator; + njs_parser_node_t *node; + njs_parser_scope_t *scope; + njs_function_lambda_t *lambda; + const njs_token_type_t *type; - if (!vm->options.unsafe) { - body = njs_argument(args, nargs - 1); - ret = njs_value_to_string(vm, body, body); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - njs_string_get(body, &str); + static const njs_token_type_t safe_ast[] = { + NJS_TOKEN_END, + NJS_TOKEN_FUNCTION_EXPRESSION, + NJS_TOKEN_STATEMENT, + NJS_TOKEN_RETURN, + NJS_TOKEN_THIS, + NJS_TOKEN_ILLEGAL + }; - /* - * Safe mode exception: - * "(new Function('return this'))" is often used to get - * the global object in a portable way. - */ - - if (str.length != njs_length("return this") - || memcmp(str.start, "return this", 11) != 0) - { - njs_type_error(vm, "function constructor is disabled" - " in \"safe\" mode"); - return NJS_ERROR; - } + if (!vm->options.unsafe && nargs != 2) { + goto fail; } njs_chb_init(&chain, vm->mem_pool); @@ -960,6 +950,27 @@ njs_function_constructor(njs_vm_t *vm, n return ret; } + if (!vm->options.unsafe) { + /* + * Safe mode exception: + * "(new Function('return this'))" is often used to get + * the global object in a portable way. + */ + + node = parser->node; + type = &safe_ast[0]; + + for (; *type != NJS_TOKEN_ILLEGAL; type++, node = node->right) { + if (node == NULL || node->left != NULL) { + goto fail; + } + + if (node->token_type != *type) { + goto fail; + } + } + } + scope = parser->scope; ret = njs_variables_copy(vm, &scope->variables, vm->variables_hash); @@ -998,6 +1009,11 @@ njs_function_constructor(njs_vm_t *vm, n njs_set_function(&vm->retval, function); return NJS_OK; + +fail: + + njs_type_error(vm, "function constructor is disabled in \"safe\" mode"); + return NJS_ERROR; } diff -r 8d4b7b3ae73d -r a41cd80e2f3a src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Feb 01 16:13:10 2021 +0000 +++ b/src/test/njs_unit_test.c Mon Feb 01 02:16:51 2021 +0100 @@ -19518,6 +19518,25 @@ static njs_unit_test_t njs_test[] = }; +static njs_unit_test_t njs_safe_test[] = +{ + { njs_str("(new Function('return this'))() === globalThis"), + njs_str("true") }, + + { njs_str("(new Function('return this;'))() === globalThis"), + njs_str("true") }, + + { njs_str("(new Function('return this '))() === globalThis"), + njs_str("true") }, + + { njs_str("(new Function('return thi'))()"), + njs_str("TypeError: function constructor is disabled in \"safe\" mode") }, + + { njs_str("(new Function('){return 1337})//', 'return this'))()"), + njs_str("TypeError: function constructor is disabled in \"safe\" mode") }, +}; + + static njs_unit_test_t njs_denormals_test[] = { { njs_str("2.2250738585072014e-308"), @@ -21777,6 +21796,12 @@ static njs_test_suite_t njs_suites[] = njs_nitems(njs_test), njs_unit_test }, + { njs_str("safe script"), + { .repeat = 1}, + njs_safe_test, + njs_nitems(njs_safe_test), + njs_unit_test }, + { njs_str("denormals"), { .repeat = 1, .unsafe = 1 }, njs_denormals_test, From andrey at apporto.com Tue Feb 2 15:52:06 2021 From: andrey at apporto.com (Andrey Khramov) Date: Tue, 2 Feb 2021 15:52:06 +0000 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo In-Reply-To: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> References: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> Message-ID: Hello,Roman Thanks for your reply. I already enabled HTTP/3 (QUIC) in those the browsers (Firefox 85, Chrome 88) accroding to ttps://quic.nginx.org/readme.html.. The https://quic.nginx.org website detects HTTP/3 (QUIC) support in the browsers. Thanks. Regards On Tue, Feb 2, 2021 at 2:47 PM Roman Arutyunyan wrote: > Hi Andrey, > > On 2 Feb 2021, at 17:30, Andrey Khramov wrote: > > Hello, there > > I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. > But I couldn't test HTTP/3 (QUIC). > > I built the quic branch of nginx-quic repo according to README of that > repo. > The configuration options follows as below: > $ ./auto/configure --prefix=/etc/nginx \ > --sbin-path=/usr/sbin/nginx \ > --conf-path=/etc/nginx/nginx.conf \ > --pid-path=/var/run/nginx.pid \ > --error-log-path=/var/log/nginx/error.log \ > --http-log-path=/var/log/nginx/access.log \ > --with-debug \ > --with-http_v2_module --with-http_ssl_module \ > --with-http_v3_module --with-http_quic_module \ > --with-stream_quic_module \ > --with-cc-opt="-I../boringssl/include" \ > --with-ld-opt="-L../boringssl/build/ssl \ > -L../boringssl/build/crypto" > $ make > > To install the nginx-quic, I installed the nginx 1.19.6 package on Ubuntu > 18.04 and replaced the nginx binary with the nginx-quic: > $ sudo cp objs/nginx /usr/sbin/ > > I configured that the nginx-quic works as load-balancer of HTTPS: > HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat > (8080 port) > > The configuration file (nginx.conf) follows as below: > > user nginx; > worker_processes auto; > > events { > worker_connections 1024; > } > > http { > log_format quic '$remote_addr - $remote_user [$time_local] ' > '"$request" $status $body_bytes_sent ' > '"$http_referer" "$http_user_agent" "$quic" "$http3"'; > > access_log /var/log/nginx/access.log quic; > error_log /var/log/nginx/error.log debug; > > server { > > listen 7443 http3 reuseport; # Enable HTTP/3. > listen 7443 ssl; # Enable HTTP/1.1 (optional). > > ssl_certificate > /home/ubuntu/andrey/http3/example-fullchain.pem; > ssl_certificate_key /etc/ssl/private/example.key; > ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; > > location / { > add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise > that QUIC is available > add_header QUIC-Status $quic; # Sent when QUIC was used > > proxy_pass http://backend1; > } > } > > server { > listen 8443 ssl http2; > > ssl_certificate > /home/ubuntu/andrey/http3/example-fullchain.pem; > ssl_certificate_key /etc/ssl/private/example.key; > ssl_protocols TLSv1 TLSv1.1 TLSv1.2; > > location / { > proxy_pass http://backend2; > } > } > > upstream backend1 { > ip_hash; > server localhost max_fails=3 fail_timeout=30s; > } > > upstream backend2 { > ip_hash; > server localhost max_fails=3 fail_timeout=30s; > } > } > > I opened UDP 7443 port on the cloud server (AWS). > > I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) and > the browsers (Firefox 85 and Chrome 88) according to > https://quic.nginx.org/readme.html. > I got the right result with the client tools, but I didn't get the right > result with the browsers. > > When connecting 7443 port with the browsers, I get the HTTP/1.1 now. > When connecting 8443 port with the browsers, I get the HTTP/2 now. > > > The first request goes over HTTP/1, but then it?s supposed to switch to > HTTP/3 if everything is right. > > Does https://quic.nginx.org/ detect QUIC support in your browsers? > If yes, please follow the ?QUIC TEST? link at the top and run the test. > > Also, make sure QUIC/HTTP/3 is enabled in the browser. > In Firefox open the about:config page make sure http.http3.enabled > parameter is ?true?. > > I hope any suggestions and help. > Thanks. > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > ? > Roman Arutyunyan > arut at nginx.com > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Tue Feb 2 16:18:05 2021 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 2 Feb 2021 19:18:05 +0300 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo In-Reply-To: References: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> Message-ID: <50956BCF-E751-4473-A6E1-569D08CFBF76@nginx.com> Hi Andrey, > On 2 Feb 2021, at 18:52, Andrey Khramov wrote: > > Hello,Roman > > Thanks for your reply. > > I already enabled HTTP/3 (QUIC) in those the browsers (Firefox 85, Chrome 88) accroding to ttps://quic.nginx.org/readme.html .. > The https://quic.nginx.org website detects HTTP/3 (QUIC) support in the browsers. Try cleaning browser cache. Also check if there are lines with the word ?quic? in the debug log when you open the page. > Thanks. Regards > > > On Tue, Feb 2, 2021 at 2:47 PM Roman Arutyunyan > wrote: > Hi Andrey, > >> On 2 Feb 2021, at 17:30, Andrey Khramov > wrote: >> >> Hello, there >> >> I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. >> But I couldn't test HTTP/3 (QUIC). >> >> I built the quic branch of nginx-quic repo according to README of that repo. >> The configuration options follows as below: >> $ ./auto/configure --prefix=/etc/nginx \ >> --sbin-path=/usr/sbin/nginx \ >> --conf-path=/etc/nginx/nginx.conf \ >> --pid-path=/var/run/nginx.pid \ >> --error-log-path=/var/log/nginx/error.log \ >> --http-log-path=/var/log/nginx/access.log \ >> --with-debug \ >> --with-http_v2_module --with-http_ssl_module \ >> --with-http_v3_module --with-http_quic_module \ >> --with-stream_quic_module \ >> --with-cc-opt="-I../boringssl/include" \ >> --with-ld-opt="-L../boringssl/build/ssl \ >> -L../boringssl/build/crypto" >> $ make >> >> To install the nginx-quic, I installed the nginx 1.19.6 package on Ubuntu 18.04 and replaced the nginx binary with the nginx-quic: >> $ sudo cp objs/nginx /usr/sbin/ >> >> I configured that the nginx-quic works as load-balancer of HTTPS: >> HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat (8080 port) >> >> The configuration file (nginx.conf) follows as below: >> >> user nginx; >> worker_processes auto; >> >> events { >> worker_connections 1024; >> } >> >> http { >> log_format quic '$remote_addr - $remote_user [$time_local] ' >> '"$request" $status $body_bytes_sent ' >> '"$http_referer" "$http_user_agent" "$quic" "$http3"'; >> >> access_log /var/log/nginx/access.log quic; >> error_log /var/log/nginx/error.log debug; >> >> server { >> >> listen 7443 http3 reuseport; # Enable HTTP/3. >> listen 7443 ssl; # Enable HTTP/1.1 (optional). >> >> ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; >> ssl_certificate_key /etc/ssl/private/example.key; >> ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; >> >> location / { >> add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise that QUIC is available >> add_header QUIC-Status $quic; # Sent when QUIC was used >> >> proxy_pass http://backend1 ; >> } >> } >> >> server { >> listen 8443 ssl http2; >> >> ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; >> ssl_certificate_key /etc/ssl/private/example.key; >> ssl_protocols TLSv1 TLSv1.1 TLSv1.2; >> >> location / { >> proxy_pass http://backend2 ; >> } >> } >> >> upstream backend1 { >> ip_hash; >> server localhost max_fails=3 fail_timeout=30s; >> } >> >> upstream backend2 { >> ip_hash; >> server localhost max_fails=3 fail_timeout=30s; >> } >> } >> >> I opened UDP 7443 port on the cloud server (AWS). >> >> I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) and the browsers (Firefox 85 and Chrome 88) according to https://quic.nginx.org/readme.html . >> I got the right result with the client tools, but I didn't get the right result with the browsers. >> >> When connecting 7443 port with the browsers, I get the HTTP/1.1 now. >> When connecting 8443 port with the browsers, I get the HTTP/2 now. > > The first request goes over HTTP/1, but then it?s supposed to switch to HTTP/3 if everything is right. > > Does https://quic.nginx.org/ detect QUIC support in your browsers? > If yes, please follow the ?QUIC TEST? link at the top and run the test. > > Also, make sure QUIC/HTTP/3 is enabled in the browser. > In Firefox open the about:config <> page make sure http.http3.enabled parameter is ?true?. > >> I hope any suggestions and help. >> Thanks. >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > ? > Roman Arutyunyan > arut at nginx.com > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel ? Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From andrey at apporto.com Tue Feb 2 21:01:20 2021 From: andrey at apporto.com (Andrey Khramov) Date: Tue, 2 Feb 2021 21:01:20 +0000 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo In-Reply-To: <50956BCF-E751-4473-A6E1-569D08CFBF76@nginx.com> References: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> <50956BCF-E751-4473-A6E1-569D08CFBF76@nginx.com> Message-ID: Hello, Roman Thanks for your reply. I checked HTTP/3 (QUIC) in the Firefox browser. But I didn't check it in the Chrome browser. The version of the Chrome is 88.0.4324.104 (64bit). I run the Chrome browser with the following command: chrome --enable-quic --quic-version=h3-29 --origin-to-force-quic-on= apporto.com:7443 Also, I enabled "Experimental QUIC protocol" flag in chrome://flags. I can't get any log related to "quic" in error.log. I hope your suggestion and advice. Thanks. Regards On Tue, Feb 2, 2021 at 4:18 PM Roman Arutyunyan wrote: > Hi Andrey, > > On 2 Feb 2021, at 18:52, Andrey Khramov wrote: > > Hello,Roman > > Thanks for your reply. > > I already enabled HTTP/3 (QUIC) in those the browsers (Firefox 85, Chrome > 88) accroding to ttps://quic.nginx.org/readme.html.. > The https://quic.nginx.org website detects HTTP/3 (QUIC) support in the > browsers. > > > Try cleaning browser cache. > > Also check if there are lines with the word ?quic? in the debug log when > you open the page. > > Thanks. Regards > > > On Tue, Feb 2, 2021 at 2:47 PM Roman Arutyunyan wrote: > >> Hi Andrey, >> >> On 2 Feb 2021, at 17:30, Andrey Khramov wrote: >> >> Hello, there >> >> I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. >> But I couldn't test HTTP/3 (QUIC). >> >> I built the quic branch of nginx-quic repo according to README of that >> repo. >> The configuration options follows as below: >> $ ./auto/configure --prefix=/etc/nginx \ >> --sbin-path=/usr/sbin/nginx \ >> --conf-path=/etc/nginx/nginx.conf \ >> --pid-path=/var/run/nginx.pid \ >> --error-log-path=/var/log/nginx/error.log \ >> --http-log-path=/var/log/nginx/access.log \ >> --with-debug \ >> --with-http_v2_module --with-http_ssl_module \ >> --with-http_v3_module --with-http_quic_module \ >> --with-stream_quic_module \ >> --with-cc-opt="-I../boringssl/include" \ >> --with-ld-opt="-L../boringssl/build/ssl \ >> -L../boringssl/build/crypto" >> $ make >> >> To install the nginx-quic, I installed the nginx 1.19.6 package on Ubuntu >> 18.04 and replaced the nginx binary with the nginx-quic: >> $ sudo cp objs/nginx /usr/sbin/ >> >> I configured that the nginx-quic works as load-balancer of HTTPS: >> HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat >> (8080 port) >> >> The configuration file (nginx.conf) follows as below: >> >> user nginx; >> worker_processes auto; >> >> events { >> worker_connections 1024; >> } >> >> http { >> log_format quic '$remote_addr - $remote_user [$time_local] ' >> '"$request" $status $body_bytes_sent ' >> '"$http_referer" "$http_user_agent" "$quic" "$http3"'; >> >> access_log /var/log/nginx/access.log quic; >> error_log /var/log/nginx/error.log debug; >> >> server { >> >> listen 7443 http3 reuseport; # Enable HTTP/3. >> listen 7443 ssl; # Enable HTTP/1.1 (optional). >> >> ssl_certificate >> /home/ubuntu/andrey/http3/example-fullchain.pem; >> ssl_certificate_key /etc/ssl/private/example.key; >> ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; >> >> location / { >> add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise >> that QUIC is available >> add_header QUIC-Status $quic; # Sent when QUIC was used >> >> proxy_pass http://backend1; >> } >> } >> >> server { >> listen 8443 ssl http2; >> >> ssl_certificate >> /home/ubuntu/andrey/http3/example-fullchain.pem; >> ssl_certificate_key /etc/ssl/private/example.key; >> ssl_protocols TLSv1 TLSv1.1 TLSv1.2; >> >> location / { >> proxy_pass http://backend2; >> } >> } >> >> upstream backend1 { >> ip_hash; >> server localhost max_fails=3 fail_timeout=30s; >> } >> >> upstream backend2 { >> ip_hash; >> server localhost max_fails=3 fail_timeout=30s; >> } >> } >> >> I opened UDP 7443 port on the cloud server (AWS). >> >> I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) >> and the browsers (Firefox 85 and Chrome 88) according to >> https://quic.nginx.org/readme.html. >> I got the right result with the client tools, but I didn't get the right >> result with the browsers. >> >> When connecting 7443 port with the browsers, I get the HTTP/1.1 now. >> When connecting 8443 port with the browsers, I get the HTTP/2 now. >> >> >> The first request goes over HTTP/1, but then it?s supposed to switch to >> HTTP/3 if everything is right. >> >> Does https://quic.nginx.org/ detect QUIC support in your browsers? >> If yes, please follow the ?QUIC TEST? link at the top and run the test. >> >> Also, make sure QUIC/HTTP/3 is enabled in the browser. >> In Firefox open the about:config page make sure http.http3.enabled >> parameter is ?true?. >> >> I hope any suggestions and help. >> Thanks. >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> >> ? >> Roman Arutyunyan >> arut at nginx.com >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > ? > Roman Arutyunyan > arut at nginx.com > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From andrey at apporto.com Tue Feb 2 21:26:13 2021 From: andrey at apporto.com (Andrey Khramov) Date: Tue, 2 Feb 2021 21:26:13 +0000 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo In-Reply-To: References: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> <50956BCF-E751-4473-A6E1-569D08CFBF76@nginx.com> Message-ID: Hello, Roman Sorry. I got the error log related to "quic" when connecting in the Chrome browser. I attached the log file. Please check it. Thank you. Regards. On Tue, Feb 2, 2021 at 9:01 PM Andrey Khramov wrote: > Hello, Roman > > Thanks for your reply. > I checked HTTP/3 (QUIC) in the Firefox browser. > But I didn't check it in the Chrome browser. > The version of the Chrome is 88.0.4324.104 (64bit). > I run the Chrome browser with the following command: > chrome --enable-quic --quic-version=h3-29 --origin-to-force-quic-on= > apporto.com:7443 > > Also, I enabled "Experimental QUIC protocol" flag in chrome://flags. > I can't get any log related to "quic" in error.log. > > I hope your suggestion and advice. > Thanks. Regards > > On Tue, Feb 2, 2021 at 4:18 PM Roman Arutyunyan wrote: > >> Hi Andrey, >> >> On 2 Feb 2021, at 18:52, Andrey Khramov wrote: >> >> Hello,Roman >> >> Thanks for your reply. >> >> I already enabled HTTP/3 (QUIC) in those the browsers (Firefox 85, Chrome >> 88) accroding to ttps://quic.nginx.org/readme.html.. >> The https://quic.nginx.org website detects HTTP/3 (QUIC) support in the >> browsers. >> >> >> Try cleaning browser cache. >> >> Also check if there are lines with the word ?quic? in the debug log when >> you open the page. >> >> Thanks. Regards >> >> >> On Tue, Feb 2, 2021 at 2:47 PM Roman Arutyunyan wrote: >> >>> Hi Andrey, >>> >>> On 2 Feb 2021, at 17:30, Andrey Khramov wrote: >>> >>> Hello, there >>> >>> I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. >>> But I couldn't test HTTP/3 (QUIC). >>> >>> I built the quic branch of nginx-quic repo according to README of that >>> repo. >>> The configuration options follows as below: >>> $ ./auto/configure --prefix=/etc/nginx \ >>> --sbin-path=/usr/sbin/nginx \ >>> --conf-path=/etc/nginx/nginx.conf \ >>> --pid-path=/var/run/nginx.pid \ >>> --error-log-path=/var/log/nginx/error.log \ >>> --http-log-path=/var/log/nginx/access.log \ >>> --with-debug \ >>> --with-http_v2_module --with-http_ssl_module \ >>> --with-http_v3_module --with-http_quic_module \ >>> --with-stream_quic_module \ >>> --with-cc-opt="-I../boringssl/include" \ >>> --with-ld-opt="-L../boringssl/build/ssl \ >>> -L../boringssl/build/crypto" >>> $ make >>> >>> To install the nginx-quic, I installed the nginx 1.19.6 package on >>> Ubuntu 18.04 and replaced the nginx binary with the nginx-quic: >>> $ sudo cp objs/nginx /usr/sbin/ >>> >>> I configured that the nginx-quic works as load-balancer of HTTPS: >>> HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat >>> (8080 port) >>> >>> The configuration file (nginx.conf) follows as below: >>> >>> user nginx; >>> worker_processes auto; >>> >>> events { >>> worker_connections 1024; >>> } >>> >>> http { >>> log_format quic '$remote_addr - $remote_user [$time_local] ' >>> '"$request" $status $body_bytes_sent ' >>> '"$http_referer" "$http_user_agent" "$quic" >>> "$http3"'; >>> >>> access_log /var/log/nginx/access.log quic; >>> error_log /var/log/nginx/error.log debug; >>> >>> server { >>> >>> listen 7443 http3 reuseport; # Enable HTTP/3. >>> listen 7443 ssl; # Enable HTTP/1.1 (optional). >>> >>> ssl_certificate >>> /home/ubuntu/andrey/http3/example-fullchain.pem; >>> ssl_certificate_key /etc/ssl/private/example.key; >>> ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; >>> >>> location / { >>> add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise >>> that QUIC is available >>> add_header QUIC-Status $quic; # Sent when QUIC was used >>> >>> proxy_pass http://backend1; >>> } >>> } >>> >>> server { >>> listen 8443 ssl http2; >>> >>> ssl_certificate >>> /home/ubuntu/andrey/http3/example-fullchain.pem; >>> ssl_certificate_key /etc/ssl/private/example.key; >>> ssl_protocols TLSv1 TLSv1.1 TLSv1.2; >>> >>> location / { >>> proxy_pass http://backend2; >>> } >>> } >>> >>> upstream backend1 { >>> ip_hash; >>> server localhost max_fails=3 fail_timeout=30s; >>> } >>> >>> upstream backend2 { >>> ip_hash; >>> server localhost max_fails=3 fail_timeout=30s; >>> } >>> } >>> >>> I opened UDP 7443 port on the cloud server (AWS). >>> >>> I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) >>> and the browsers (Firefox 85 and Chrome 88) according to >>> https://quic.nginx.org/readme.html. >>> I got the right result with the client tools, but I didn't get the right >>> result with the browsers. >>> >>> When connecting 7443 port with the browsers, I get the HTTP/1.1 now. >>> When connecting 8443 port with the browsers, I get the HTTP/2 now. >>> >>> >>> The first request goes over HTTP/1, but then it?s supposed to switch to >>> HTTP/3 if everything is right. >>> >>> Does https://quic.nginx.org/ detect QUIC support in your browsers? >>> If yes, please follow the ?QUIC TEST? link at the top and run the test. >>> >>> Also, make sure QUIC/HTTP/3 is enabled in the browser. >>> In Firefox open the about:config page make sure http.http3.enabled >>> parameter is ?true?. >>> >>> I hope any suggestions and help. >>> Thanks. >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >>> >>> ? >>> Roman Arutyunyan >>> arut at nginx.com >>> >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> >> ? >> Roman Arutyunyan >> arut at nginx.com >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: error-chrome.log Type: application/octet-stream Size: 42344 bytes Desc: not available URL: From arut at nginx.com Tue Feb 2 22:40:52 2021 From: arut at nginx.com (Roman Arutyunyan) Date: Wed, 3 Feb 2021 01:40:52 +0300 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo In-Reply-To: References: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> <50956BCF-E751-4473-A6E1-569D08CFBF76@nginx.com> Message-ID: <15523240-A7C9-4209-9123-615A9B8C0B9D@nginx.com> Hi Andrey, Here?s the error: 2021/02/02 21:17:21 [debug] 18359#0: *4 quic frame rx init CONNECTION_CLOSE_APP err:10 28:TLS handshake failure (ENCRYPTION_HANDSHAKE) 46: certificate unknown ft:6 Looks like your server certificate is not trusted by the browser. > On 3 Feb 2021, at 00:26, Andrey Khramov wrote: > > Hello, Roman > > Sorry. > I got the error log related to "quic" when connecting in the Chrome browser. > I attached the log file. > Please check it. > > Thank you. Regards. > > On Tue, Feb 2, 2021 at 9:01 PM Andrey Khramov > wrote: > Hello, Roman > > Thanks for your reply. > I checked HTTP/3 (QUIC) in the Firefox browser. > But I didn't check it in the Chrome browser. > The version of the Chrome is 88.0.4324.104 (64bit). > I run the Chrome browser with the following command: > chrome --enable-quic --quic-version=h3-29 --origin-to-force-quic-on=apporto.com:7443 > > Also, I enabled "Experimental QUIC protocol" flag in chrome://flags. > I can't get any log related to "quic" in error.log. > > I hope your suggestion and advice. > Thanks. Regards > > On Tue, Feb 2, 2021 at 4:18 PM Roman Arutyunyan > wrote: > Hi Andrey, > >> On 2 Feb 2021, at 18:52, Andrey Khramov > wrote: >> >> Hello,Roman >> >> Thanks for your reply. >> >> I already enabled HTTP/3 (QUIC) in those the browsers (Firefox 85, Chrome 88) accroding to ttps://quic.nginx.org/readme.html .. >> The https://quic.nginx.org website detects HTTP/3 (QUIC) support in the browsers. > > Try cleaning browser cache. > > Also check if there are lines with the word ?quic? in the debug log when you open the page. > >> Thanks. Regards >> >> >> On Tue, Feb 2, 2021 at 2:47 PM Roman Arutyunyan > wrote: >> Hi Andrey, >> >>> On 2 Feb 2021, at 17:30, Andrey Khramov > wrote: >>> >>> Hello, there >>> >>> I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. >>> But I couldn't test HTTP/3 (QUIC). >>> >>> I built the quic branch of nginx-quic repo according to README of that repo. >>> The configuration options follows as below: >>> $ ./auto/configure --prefix=/etc/nginx \ >>> --sbin-path=/usr/sbin/nginx \ >>> --conf-path=/etc/nginx/nginx.conf \ >>> --pid-path=/var/run/nginx.pid \ >>> --error-log-path=/var/log/nginx/error.log \ >>> --http-log-path=/var/log/nginx/access.log \ >>> --with-debug \ >>> --with-http_v2_module --with-http_ssl_module \ >>> --with-http_v3_module --with-http_quic_module \ >>> --with-stream_quic_module \ >>> --with-cc-opt="-I../boringssl/include" \ >>> --with-ld-opt="-L../boringssl/build/ssl \ >>> -L../boringssl/build/crypto" >>> $ make >>> >>> To install the nginx-quic, I installed the nginx 1.19.6 package on Ubuntu 18.04 and replaced the nginx binary with the nginx-quic: >>> $ sudo cp objs/nginx /usr/sbin/ >>> >>> I configured that the nginx-quic works as load-balancer of HTTPS: >>> HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat (8080 port) >>> >>> The configuration file (nginx.conf) follows as below: >>> >>> user nginx; >>> worker_processes auto; >>> >>> events { >>> worker_connections 1024; >>> } >>> >>> http { >>> log_format quic '$remote_addr - $remote_user [$time_local] ' >>> '"$request" $status $body_bytes_sent ' >>> '"$http_referer" "$http_user_agent" "$quic" "$http3"'; >>> >>> access_log /var/log/nginx/access.log quic; >>> error_log /var/log/nginx/error.log debug; >>> >>> server { >>> >>> listen 7443 http3 reuseport; # Enable HTTP/3. >>> listen 7443 ssl; # Enable HTTP/1.1 (optional). >>> >>> ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; >>> ssl_certificate_key /etc/ssl/private/example.key; >>> ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; >>> >>> location / { >>> add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise that QUIC is available >>> add_header QUIC-Status $quic; # Sent when QUIC was used >>> >>> proxy_pass http://backend1 ; >>> } >>> } >>> >>> server { >>> listen 8443 ssl http2; >>> >>> ssl_certificate /home/ubuntu/andrey/http3/example-fullchain.pem; >>> ssl_certificate_key /etc/ssl/private/example.key; >>> ssl_protocols TLSv1 TLSv1.1 TLSv1.2; >>> >>> location / { >>> proxy_pass http://backend2 ; >>> } >>> } >>> >>> upstream backend1 { >>> ip_hash; >>> server localhost max_fails=3 fail_timeout=30s; >>> } >>> >>> upstream backend2 { >>> ip_hash; >>> server localhost max_fails=3 fail_timeout=30s; >>> } >>> } >>> >>> I opened UDP 7443 port on the cloud server (AWS). >>> >>> I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) and the browsers (Firefox 85 and Chrome 88) according to https://quic.nginx.org/readme.html . >>> I got the right result with the client tools, but I didn't get the right result with the browsers. >>> >>> When connecting 7443 port with the browsers, I get the HTTP/1.1 now. >>> When connecting 8443 port with the browsers, I get the HTTP/2 now. >> >> The first request goes over HTTP/1, but then it?s supposed to switch to HTTP/3 if everything is right. >> >> Does https://quic.nginx.org/ detect QUIC support in your browsers? >> If yes, please follow the ?QUIC TEST? link at the top and run the test. >> >> Also, make sure QUIC/HTTP/3 is enabled in the browser. >> In Firefox open the about:config <> page make sure http.http3.enabled parameter is ?true?. >> >>> I hope any suggestions and help. >>> Thanks. >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> ? >> Roman Arutyunyan >> arut at nginx.com >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > ? > Roman Arutyunyan > arut at nginx.com > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel ? Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From mikhail.isachenkov at nginx.com Wed Feb 3 14:11:25 2021 From: mikhail.isachenkov at nginx.com (Mikhail Isachenkov) Date: Wed, 3 Feb 2021 17:11:25 +0300 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> Message-ID: <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Hi Ping Zhao, When I try to repeat this test, I've got a huge number of these errors: 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read "/usr/local/html/64746" failed (11: Resource temporarily unavailable) while sending response to client, client: 127.0.0.1, server: localhost, request: "GET /64746 HTTP/1.1", host: "localhost" I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? 25.01.2021 11:24, Zhao, Ping ?????: > Hello, add a small update to correct the length when part of request already received in previous. > This case may happen when using io_uring and throughput increased. > > # HG changeset patch > # User Ping Zhao > # Date 1611566408 18000 > # Mon Jan 25 04:20:08 2021 -0500 > # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 > # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 > Correct length calculation when part of request received. > > diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c > --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 > +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 > @@ -531,6 +531,14 @@ > > size = ngx_buf_size(src); > size = ngx_min(size, dst->end - dst->pos); > +#if (NGX_HAVE_FILE_IOURING) > + /* > + * check if already received part of the request in previous, > + * calculate the remain length > + */ > + if(dst->last > dst->pos && size > (dst->last - dst->pos)) > + size = size - (dst->last - dst->pos); > +#endif > > sendfile = ctx->sendfile && !ctx->directio; > > -----Original Message----- > From: nginx-devel On Behalf Of Zhao, Ping > Sent: Thursday, January 21, 2021 9:44 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Vladimir, > > No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: > > user nobody; > daemon off; > worker_processes 1; > error_log error.log ; > events { > worker_connections 65535; > use epoll; > } > > http { > include mime.types; > default_type application/octet-stream; > access_log on; > aio on; > sendfile off; > directio 2k; > > # Cache Configurations > proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... > > > To better measure the disk io performance data, I do the following steps: > 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) > echo 2G > memory.limit_in_bytes > use ' cgexec -g memory:nginx' to start Nginx. > > 2. use wrk -t 100 -c 1000, with random 25000 http requests. > My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. > > 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. > > 4. Rerun the test, this time Nginx will use ngx_file_aio_read to extract the cache files in nvme cache disk. Use iostat to track the io data. The data should be align with NIC bw since all data should be from cache disk.(need exclude memory as cache storage impact) > > Following is the test result: > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > > So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Vladimir Homutov > Sent: Wednesday, January 20, 2021 12:43 AM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >> It depends on if disk io is the performance hot spot or not. If yes, >> io_uring shows improvement than libaio. With 4KB/100KB length 1 Nginx >> thread it's hard to see performance difference because iostat is only >> around ~10MB/100MB per second. Disk io is not the performance bottle >> neck, both libaio and io_uring have the same performance. If you >> increase request size or Nginx threads number, for example 1MB length >> or Nginx thread number 4. In this case, disk io became the performance >> bottle neck, you will see io_uring performance improvement. > > Can you please provide full test results with specific nginx configuration? > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From andrey at apporto.com Wed Feb 3 14:49:03 2021 From: andrey at apporto.com (Andrey Khramov) Date: Wed, 3 Feb 2021 14:49:03 +0000 Subject: [nginx-quic] HTTP/3(QUIC): I can't test HTTP/3 with nginx-quic repo In-Reply-To: <15523240-A7C9-4209-9123-615A9B8C0B9D@nginx.com> References: <5634BE01-1CD3-4800-8810-5CEBBF65C549@nginx.com> <50956BCF-E751-4473-A6E1-569D08CFBF76@nginx.com> <15523240-A7C9-4209-9123-615A9B8C0B9D@nginx.com> Message-ID: Hi Roman, Thanks for your reply. I can't know why the SSL certificate isn't trusted by the Chrome browser because there is no problem related to the SSL certificate in the Firefox browser. I moved the SSL certificate from apache2 to nginx: apache2 nginx SSLCertificateFile ssl_certificate SSLCertificateKeyFile ssl_certificate_key SSLCACertificateFile ssl_trusted_certificate Could you tell me what I'm missing? Thanks. Regards. On Tue, Feb 2, 2021 at 10:41 PM Roman Arutyunyan wrote: > Hi Andrey, > > Here?s the error: > > 2021/02/02 21:17:21 [debug] 18359#0: *4 quic frame rx init > CONNECTION_CLOSE_APP err:10 28:TLS handshake failure (ENCRYPTION_HANDSHAKE) > 46: certificate unknown ft:6 > > Looks like your server certificate is not trusted by the browser. > > On 3 Feb 2021, at 00:26, Andrey Khramov wrote: > > Hello, Roman > > Sorry. > I got the error log related to "quic" when connecting in the Chrome > browser. > I attached the log file. > Please check it. > > Thank you. Regards. > > On Tue, Feb 2, 2021 at 9:01 PM Andrey Khramov wrote: > >> Hello, Roman >> >> Thanks for your reply. >> I checked HTTP/3 (QUIC) in the Firefox browser. >> But I didn't check it in the Chrome browser. >> The version of the Chrome is 88.0.4324.104 (64bit). >> I run the Chrome browser with the following command: >> chrome --enable-quic --quic-version=h3-29 --origin-to-force-quic-on= >> apporto.com:7443 >> >> Also, I enabled "Experimental QUIC protocol" flag in chrome://flags. >> I can't get any log related to "quic" in error.log. >> >> I hope your suggestion and advice. >> Thanks. Regards >> >> On Tue, Feb 2, 2021 at 4:18 PM Roman Arutyunyan wrote: >> >>> Hi Andrey, >>> >>> On 2 Feb 2021, at 18:52, Andrey Khramov wrote: >>> >>> Hello,Roman >>> >>> Thanks for your reply. >>> >>> I already enabled HTTP/3 (QUIC) in those the browsers (Firefox 85, >>> Chrome 88) accroding to ttps://quic.nginx.org/readme.html.. >>> The https://quic.nginx.org website detects HTTP/3 (QUIC) support in the >>> browsers. >>> >>> >>> Try cleaning browser cache. >>> >>> Also check if there are lines with the word ?quic? in the debug log when >>> you open the page. >>> >>> Thanks. Regards >>> >>> >>> On Tue, Feb 2, 2021 at 2:47 PM Roman Arutyunyan wrote: >>> >>>> Hi Andrey, >>>> >>>> On 2 Feb 2021, at 17:30, Andrey Khramov wrote: >>>> >>>> Hello, there >>>> >>>> I tried to test the HTTP/3 (QUIC) with nginx-quic in several days. >>>> But I couldn't test HTTP/3 (QUIC). >>>> >>>> I built the quic branch of nginx-quic repo according to README of that >>>> repo. >>>> The configuration options follows as below: >>>> $ ./auto/configure --prefix=/etc/nginx \ >>>> --sbin-path=/usr/sbin/nginx \ >>>> --conf-path=/etc/nginx/nginx.conf \ >>>> --pid-path=/var/run/nginx.pid \ >>>> --error-log-path=/var/log/nginx/error.log \ >>>> --http-log-path=/var/log/nginx/access.log \ >>>> --with-debug \ >>>> --with-http_v2_module --with-http_ssl_module \ >>>> --with-http_v3_module --with-http_quic_module \ >>>> --with-stream_quic_module \ >>>> --with-cc-opt="-I../boringssl/include" \ >>>> --with-ld-opt="-L../boringssl/build/ssl \ >>>> -L../boringssl/build/crypto" >>>> $ make >>>> >>>> To install the nginx-quic, I installed the nginx 1.19.6 package on >>>> Ubuntu 18.04 and replaced the nginx binary with the nginx-quic: >>>> $ sudo cp objs/nginx /usr/sbin/ >>>> >>>> I configured that the nginx-quic works as load-balancer of HTTPS: >>>> HTTPS -> nginx-quic (7443 port) -> Apache2 (80 port) -> Apache Tomcat >>>> (8080 port) >>>> >>>> The configuration file (nginx.conf) follows as below: >>>> >>>> user nginx; >>>> worker_processes auto; >>>> >>>> events { >>>> worker_connections 1024; >>>> } >>>> >>>> http { >>>> log_format quic '$remote_addr - $remote_user [$time_local] ' >>>> '"$request" $status $body_bytes_sent ' >>>> '"$http_referer" "$http_user_agent" "$quic" >>>> "$http3"'; >>>> >>>> access_log /var/log/nginx/access.log quic; >>>> error_log /var/log/nginx/error.log debug; >>>> >>>> server { >>>> >>>> listen 7443 http3 reuseport; # Enable HTTP/3. >>>> listen 7443 ssl; # Enable HTTP/1.1 (optional). >>>> >>>> ssl_certificate >>>> /home/ubuntu/andrey/http3/example-fullchain.pem; >>>> ssl_certificate_key /etc/ssl/private/example.key; >>>> ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; >>>> >>>> location / { >>>> add_header alt-svc '$http3=":7443"; ma=86400'; # Advertise >>>> that QUIC is available >>>> add_header QUIC-Status $quic; # Sent when QUIC was used >>>> >>>> proxy_pass http://backend1; >>>> } >>>> } >>>> >>>> server { >>>> listen 8443 ssl http2; >>>> >>>> ssl_certificate >>>> /home/ubuntu/andrey/http3/example-fullchain.pem; >>>> ssl_certificate_key /etc/ssl/private/example.key; >>>> ssl_protocols TLSv1 TLSv1.1 TLSv1.2; >>>> >>>> location / { >>>> proxy_pass http://backend2; >>>> } >>>> } >>>> >>>> upstream backend1 { >>>> ip_hash; >>>> server localhost max_fails=3 fail_timeout=30s; >>>> } >>>> >>>> upstream backend2 { >>>> ip_hash; >>>> server localhost max_fails=3 fail_timeout=30s; >>>> } >>>> } >>>> >>>> I opened UDP 7443 port on the cloud server (AWS). >>>> >>>> I tested HTTP/3 (QUIC) with the client tools (neqo-client, curl-http3) >>>> and the browsers (Firefox 85 and Chrome 88) according to >>>> https://quic.nginx.org/readme.html. >>>> I got the right result with the client tools, but I didn't get the >>>> right result with the browsers. >>>> >>>> When connecting 7443 port with the browsers, I get the HTTP/1.1 now. >>>> When connecting 8443 port with the browsers, I get the HTTP/2 now. >>>> >>>> >>>> The first request goes over HTTP/1, but then it?s supposed to switch to >>>> HTTP/3 if everything is right. >>>> >>>> Does https://quic.nginx.org/ detect QUIC support in your browsers? >>>> If yes, please follow the ?QUIC TEST? link at the top and run the test. >>>> >>>> Also, make sure QUIC/HTTP/3 is enabled in the browser. >>>> In Firefox open the about:config page make sure http.http3.enabled >>>> parameter is ?true?. >>>> >>>> I hope any suggestions and help. >>>> Thanks. >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>>> >>>> ? >>>> Roman Arutyunyan >>>> arut at nginx.com >>>> >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >>> >>> ? >>> Roman Arutyunyan >>> arut at nginx.com >>> >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > ? > Roman Arutyunyan > arut at nginx.com > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From hongyi.zhao at gmail.com Thu Feb 4 01:17:47 2021 From: hongyi.zhao at gmail.com (Hongyi Zhao) Date: Thu, 4 Feb 2021 09:17:47 +0800 Subject: Failed to publish a HLS stream via the nginx HTTPS server with ffmpeg. Message-ID: Hi, On Ubuntu 20.04, I've built the docker image based my project located at . The SSL relative configuration has been enabled in the nginx.conf file used by the above docker image, see for the detailed info. I then tried to stream the camera using HLS, as described below. Publish the stream: $ docker run -it -p 1935:1935 -p 8000:80 --rm nginx-rtmp $ ffmpeg -f pulse -i default -f v4l2 -r 30 -s 1920x1080 -i /dev/video0 -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 3000k -vf "scale=1280:-1,format=yuv420p" -g 60 -c:a aac -b:a 128k -ar 44100 -force_key_frames "expr:gte(t,n_forced*4)" -f flv "rtmp://localhost:1935/stream/surveillance" As for watching the stream, I tried to use ffplay with http and https protocal respectively, but the former can successfully play the stream, the latter failed. The used commands are shown below: $ ffplay http://localhost:8000/live/surveillance.m3u8 $ ffplay https://localhost:8000/live/surveillance.m3u8 ffplay version N-100814-g911ba8417e Copyright (c) 2003-2021 the FFmpeg developers built with gcc 9 (Ubuntu 9.3.0-17ubuntu1~20.04) configuration: --enable-gpl --enable-nonfree --enable-version3 --enable-debug --enable-ffplay --enable-indev=sndio --enable-outdev=sndio --enable-fontconfig --enable-frei0r --enable-openssl --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg --enable-rpath --enable-shared --enable-avisynth --enable-chromaprint --enable-gcrypt --enable-ladspa --enable-libaribb24 --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcelt --enable-libcdio --enable-libcodec2 --enable-libdc1394 --enable-libfdk-aac --enable-libflite --enable-libfontconfig --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libklvanc --enable-liblensfun --enable-libmodplug --enable-libopenh264 --enable-libopenmpt --enable-libpulse --enable-librabbitmq --enable-librsvg --enable-librtmp --enable-libshine --enable-libsnappy --enable-libssh --enable-libtesseract --enable-libtwolame --enable-libv4l2 --enable-libxavs2 --enable-libdavs2 --enable-libxcb --enable-libxcb-shm --enable-libxcb-xfixes --enable-libxcb-shape --enable-libzmq --enable-lv2 --enable-libmysofa --enable-openal --enable-opencl --enable-opengl --enable-pocketsphinx --enable-vulkan --enable-libdrm --enable-libmfx --enable-pic --enable-lto --enable-hardcoded-tables --enable-memory-poisoning --enable-ftrapv --enable-linux-perf --enable-libsvtav1 libavutil 56. 63.101 / 56. 63.101 libavcodec 58.119.100 / 58.119.100 libavformat 58. 65.101 / 58. 65.101 libavdevice 58. 11.103 / 58. 11.103 libavfilter 7. 97.100 / 7. 97.100 libswscale 5. 8.100 / 5. 8.100 libswresample 3. 8.100 / 3. 8.100 libpostproc 55. 8.100 / 55. 8.100 [tls @ 0x7f04f0004680] error:1408F10B:SSL routines:ssl3_get_record:wrong version number https://localhost:8000/live/surveillance.m3u8: Input/output error Any hints/notes/comments for solving this problem are highly appreciated. Regards -- Assoc. Prof. Hongyi Zhao Theory and Simulation of Materials Hebei Polytechnic University of Science and Technology engineering NO. 552 North Gangtie Road, Xingtai, China From mdounin at mdounin.ru Thu Feb 4 02:00:30 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 4 Feb 2021 05:00:30 +0300 Subject: Failed to publish a HLS stream via the nginx HTTPS server with ffmpeg. In-Reply-To: References: Message-ID: <20210204020030.GA77619@mdounin.ru> Hello! On Thu, Feb 04, 2021 at 09:17:47AM +0800, Hongyi Zhao wrote: > Hi, > > On Ubuntu 20.04, I've built the docker image based my project located at > . The SSL relative > configuration has been enabled in the nginx.conf file used by the > above docker image, > see > for the detailed info. I then tried to > stream the camera using HLS, as described below. [...] The nginx-devel@ mailing list is a mailing list for nginx developers, it is intended for questions about nginx development. Please avoid posting questions about using nginx here, use the nginx@ mailing list for such questions instead. Also, please avoid cross-posting between mailing lists. Thank you for cooperation. -- Maxim Dounin http://mdounin.ru/ From ping.zhao at intel.com Thu Feb 4 02:32:52 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Thu, 4 Feb 2021 02:32:52 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Message-ID: Hi Mikhail, I didn't see this error in my log. Following is my OS/Kernel: CentOS: 8.1.1911 Kernel: 5.7.19 Liburing: liburing-1.0.7-3.el8.x86_64, liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. My nginx reported this error before: 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" Which is fixed by my 2nd patch(Jan 25) already. BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Wednesday, February 3, 2021 10:11 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Ping Zhao, When I try to repeat this test, I've got a huge number of these errors: 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read "/usr/local/html/64746" failed (11: Resource temporarily unavailable) while sending response to client, client: 127.0.0.1, server: localhost, request: "GET /64746 HTTP/1.1", host: "localhost" I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? 25.01.2021 11:24, Zhao, Ping ?????: > Hello, add a small update to correct the length when part of request already received in previous. > This case may happen when using io_uring and throughput increased. > > # HG changeset patch > # User Ping Zhao # Date 1611566408 18000 > # Mon Jan 25 04:20:08 2021 -0500 > # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 > # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 > Correct length calculation when part of request received. > > diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c > --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 > +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 > @@ -531,6 +531,14 @@ > > size = ngx_buf_size(src); > size = ngx_min(size, dst->end - dst->pos); > +#if (NGX_HAVE_FILE_IOURING) > + /* > + * check if already received part of the request in previous, > + * calculate the remain length > + */ > + if(dst->last > dst->pos && size > (dst->last - dst->pos)) > + size = size - (dst->last - dst->pos); #endif > > sendfile = ctx->sendfile && !ctx->directio; > > -----Original Message----- > From: nginx-devel On Behalf Of Zhao, > Ping > Sent: Thursday, January 21, 2021 9:44 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Vladimir, > > No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: > > user nobody; > daemon off; > worker_processes 1; > error_log error.log ; > events { > worker_connections 65535; > use epoll; > } > > http { > include mime.types; > default_type application/octet-stream; > access_log on; > aio on; > sendfile off; > directio 2k; > > # Cache Configurations > proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... > > > To better measure the disk io performance data, I do the following steps: > 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) > echo 2G > memory.limit_in_bytes > use ' cgexec -g memory:nginx' to start Nginx. > > 2. use wrk -t 100 -c 1000, with random 25000 http requests. > My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. > > 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. > > 4. Rerun the test, this time Nginx will use ngx_file_aio_read to > extract the cache files in nvme cache disk. Use iostat to track the io > data. The data should be align with NIC bw since all data should be > from cache disk.(need exclude memory as cache storage impact) > > Following is the test result: > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > > So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of > Vladimir Homutov > Sent: Wednesday, January 20, 2021 12:43 AM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >> It depends on if disk io is the performance hot spot or not. If yes, >> io_uring shows improvement than libaio. With 4KB/100KB length 1 Nginx >> thread it's hard to see performance difference because iostat is only >> around ~10MB/100MB per second. Disk io is not the performance bottle >> neck, both libaio and io_uring have the same performance. If you >> increase request size or Nginx threads number, for example 1MB length >> or Nginx thread number 4. In this case, disk io became the >> performance bottle neck, you will see io_uring performance improvement. > > Can you please provide full test results with specific nginx configuration? > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From ping.zhao at intel.com Thu Feb 4 07:08:30 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Thu, 4 Feb 2021 07:08:30 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Message-ID: Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. -----Original Message----- From: Zhao, Ping Sent: Thursday, February 4, 2021 10:33 AM To: nginx-devel at nginx.org Subject: RE: [PATCH] Add io_uring support in AIO(async io) module Hi Mikhail, I didn't see this error in my log. Following is my OS/Kernel: CentOS: 8.1.1911 Kernel: 5.7.19 Liburing: liburing-1.0.7-3.el8.x86_64, liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. My nginx reported this error before: 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" Which is fixed by my 2nd patch(Jan 25) already. BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Wednesday, February 3, 2021 10:11 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Ping Zhao, When I try to repeat this test, I've got a huge number of these errors: 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read "/usr/local/html/64746" failed (11: Resource temporarily unavailable) while sending response to client, client: 127.0.0.1, server: localhost, request: "GET /64746 HTTP/1.1", host: "localhost" I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? 25.01.2021 11:24, Zhao, Ping ?????: > Hello, add a small update to correct the length when part of request already received in previous. > This case may happen when using io_uring and throughput increased. > > # HG changeset patch > # User Ping Zhao # Date 1611566408 18000 > # Mon Jan 25 04:20:08 2021 -0500 > # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 > # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 > Correct length calculation when part of request received. > > diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c > --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 > +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 > @@ -531,6 +531,14 @@ > > size = ngx_buf_size(src); > size = ngx_min(size, dst->end - dst->pos); > +#if (NGX_HAVE_FILE_IOURING) > + /* > + * check if already received part of the request in previous, > + * calculate the remain length > + */ > + if(dst->last > dst->pos && size > (dst->last - dst->pos)) > + size = size - (dst->last - dst->pos); #endif > > sendfile = ctx->sendfile && !ctx->directio; > > -----Original Message----- > From: nginx-devel On Behalf Of Zhao, > Ping > Sent: Thursday, January 21, 2021 9:44 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Vladimir, > > No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: > > user nobody; > daemon off; > worker_processes 1; > error_log error.log ; > events { > worker_connections 65535; > use epoll; > } > > http { > include mime.types; > default_type application/octet-stream; > access_log on; > aio on; > sendfile off; > directio 2k; > > # Cache Configurations > proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... > > > To better measure the disk io performance data, I do the following steps: > 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) > echo 2G > memory.limit_in_bytes > use ' cgexec -g memory:nginx' to start Nginx. > > 2. use wrk -t 100 -c 1000, with random 25000 http requests. > My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. > > 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. > > 4. Rerun the test, this time Nginx will use ngx_file_aio_read to > extract the cache files in nvme cache disk. Use iostat to track the io > data. The data should be align with NIC bw since all data should be > from cache disk.(need exclude memory as cache storage impact) > > Following is the test result: > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > > So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of > Vladimir Homutov > Sent: Wednesday, January 20, 2021 12:43 AM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >> It depends on if disk io is the performance hot spot or not. If yes, >> io_uring shows improvement than libaio. With 4KB/100KB length 1 Nginx >> thread it's hard to see performance difference because iostat is only >> around ~10MB/100MB per second. Disk io is not the performance bottle >> neck, both libaio and io_uring have the same performance. If you >> increase request size or Nginx threads number, for example 1MB length >> or Nginx thread number 4. In this case, disk io became the >> performance bottle neck, you will see io_uring performance improvement. > > Can you please provide full test results with specific nginx configuration? > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From mikhail.isachenkov at nginx.com Thu Feb 4 08:55:21 2021 From: mikhail.isachenkov at nginx.com (Mikhail Isachenkov) Date: Thu, 4 Feb 2021 11:55:21 +0300 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Message-ID: Hi Zhao Ping, My test is much simpler than yours. I created /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. These files does not change during test. I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? Thanks in advance! 04.02.2021 10:08, Zhao, Ping ?????: > Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. > > -----Original Message----- > From: Zhao, Ping > Sent: Thursday, February 4, 2021 10:33 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Mikhail, > > I didn't see this error in my log. Following is my OS/Kernel: > CentOS: 8.1.1911 > Kernel: 5.7.19 > Liburing: liburing-1.0.7-3.el8.x86_64, liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) > > Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. > > My nginx reported this error before: > 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" > Which is fixed by my 2nd patch(Jan 25) already. > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail Isachenkov > Sent: Wednesday, February 3, 2021 10:11 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Ping Zhao, > > When I try to repeat this test, I've got a huge number of these errors: > > 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read "/usr/local/html/64746" failed (11: Resource temporarily unavailable) while sending response to client, client: 127.0.0.1, server: localhost, > request: "GET /64746 HTTP/1.1", host: "localhost" > > I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. > > Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? > > 25.01.2021 11:24, Zhao, Ping ?????: >> Hello, add a small update to correct the length when part of request already received in previous. >> This case may happen when using io_uring and throughput increased. >> >> # HG changeset patch >> # User Ping Zhao # Date 1611566408 18000 >> # Mon Jan 25 04:20:08 2021 -0500 >> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >> Correct length calculation when part of request received. >> >> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >> @@ -531,6 +531,14 @@ >> >> size = ngx_buf_size(src); >> size = ngx_min(size, dst->end - dst->pos); >> +#if (NGX_HAVE_FILE_IOURING) >> + /* >> + * check if already received part of the request in previous, >> + * calculate the remain length >> + */ >> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >> + size = size - (dst->last - dst->pos); #endif >> >> sendfile = ctx->sendfile && !ctx->directio; >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Zhao, >> Ping >> Sent: Thursday, January 21, 2021 9:44 AM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Vladimir, >> >> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >> >> user nobody; >> daemon off; >> worker_processes 1; >> error_log error.log ; >> events { >> worker_connections 65535; >> use epoll; >> } >> >> http { >> include mime.types; >> default_type application/octet-stream; >> access_log on; >> aio on; >> sendfile off; >> directio 2k; >> >> # Cache Configurations >> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >> >> >> To better measure the disk io performance data, I do the following steps: >> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >> echo 2G > memory.limit_in_bytes >> use ' cgexec -g memory:nginx' to start Nginx. >> >> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >> >> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >> >> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >> extract the cache files in nvme cache disk. Use iostat to track the io >> data. The data should be align with NIC bw since all data should be >> from cache disk.(need exclude memory as cache storage impact) >> >> Following is the test result: >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> >> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Vladimir Homutov >> Sent: Wednesday, January 20, 2021 12:43 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>> It depends on if disk io is the performance hot spot or not. If yes, >>> io_uring shows improvement than libaio. With 4KB/100KB length 1 Nginx >>> thread it's hard to see performance difference because iostat is only >>> around ~10MB/100MB per second. Disk io is not the performance bottle >>> neck, both libaio and io_uring have the same performance. If you >>> increase request size or Nginx threads number, for example 1MB length >>> or Nginx thread number 4. In this case, disk io became the >>> performance bottle neck, you will see io_uring performance improvement. >> >> Can you please provide full test results with specific nginx configuration? >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From thib at stammed.net Thu Feb 4 23:48:50 2021 From: thib at stammed.net (Thibault =?ISO-8859-1?Q?N=E9lis?=) Date: Fri, 5 Feb 2021 00:48:50 +0100 Subject: [PATCH] Define phony make targets as such. Message-ID: <8c7fd0395e69fc54e31b6062ec2c72708a523a7d.camel@stammed.net> Hello, I just spent more time than I care to admit troubleshooting a make issue after naively using `./configure --builddir=build` (make target inadvertently matches this directory name). Not sure if taking a dep on POSIX sed in the build system is kosher or not, but if it is I figure this patch could save the next one some time ;). Quickly tested on top of default tip as of this writing (7765:519b55453c45). Best regards, --- a/auto/init +++ b/auto/init @@ -44,6 +44,8 @@ fi ? ?cat << END > Makefile ? +.PHONY: default clean + ?default:???????build ? ?clean: --- a/auto/install +++ b/auto/install @@ -196,6 +196,8 @@ done ? ?# create Makefile ? +sed -i "/^\.PHONY/s/$/ build install modules upgrade/" Makefile + ?cat << END >> Makefile ? ?build: From ping.zhao at intel.com Fri Feb 5 00:54:50 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Fri, 5 Feb 2021 00:54:50 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Message-ID: Hi Mikhail, I think it could be the kernel difference. I'll try to repro with your kernel. I directly build the kernel from kernel org. This is the commit id I used: commit 6b9830fecd4a87d7ebb4d93484fef00f46d0fa0f (HEAD -> linux-5.7.y, tag: v5.7.19, origin/linux-5.7.y) Author: Greg Kroah-Hartman Date: Thu Aug 27 09:30:50 2020 +0200 Linux 5.7.19 Also I'll send another mail later with 'sendfile on' and 'aio off' test result. Maybe I can do this first. BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Thursday, February 4, 2021 4:55 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, My test is much simpler than yours. I created /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. These files does not change during test. I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? Thanks in advance! 04.02.2021 10:08, Zhao, Ping ?????: > Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. > > -----Original Message----- > From: Zhao, Ping > Sent: Thursday, February 4, 2021 10:33 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Mikhail, > > I didn't see this error in my log. Following is my OS/Kernel: > CentOS: 8.1.1911 > Kernel: 5.7.19 > Liburing: liburing-1.0.7-3.el8.x86_64, > liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) > > Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. > > My nginx reported this error before: > 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" > Which is fixed by my 2nd patch(Jan 25) already. > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Wednesday, February 3, 2021 10:11 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Ping Zhao, > > When I try to repeat this test, I've got a huge number of these errors: > > 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read > "/usr/local/html/64746" failed (11: Resource temporarily unavailable) > while sending response to client, client: 127.0.0.1, server: > localhost, > request: "GET /64746 HTTP/1.1", host: "localhost" > > I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. > > Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? > > 25.01.2021 11:24, Zhao, Ping ?????: >> Hello, add a small update to correct the length when part of request already received in previous. >> This case may happen when using io_uring and throughput increased. >> >> # HG changeset patch >> # User Ping Zhao # Date 1611566408 18000 >> # Mon Jan 25 04:20:08 2021 -0500 >> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >> Correct length calculation when part of request received. >> >> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >> @@ -531,6 +531,14 @@ >> >> size = ngx_buf_size(src); >> size = ngx_min(size, dst->end - dst->pos); >> +#if (NGX_HAVE_FILE_IOURING) >> + /* >> + * check if already received part of the request in previous, >> + * calculate the remain length >> + */ >> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >> + size = size - (dst->last - dst->pos); #endif >> >> sendfile = ctx->sendfile && !ctx->directio; >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Zhao, >> Ping >> Sent: Thursday, January 21, 2021 9:44 AM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Vladimir, >> >> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >> >> user nobody; >> daemon off; >> worker_processes 1; >> error_log error.log ; >> events { >> worker_connections 65535; >> use epoll; >> } >> >> http { >> include mime.types; >> default_type application/octet-stream; >> access_log on; >> aio on; >> sendfile off; >> directio 2k; >> >> # Cache Configurations >> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >> >> >> To better measure the disk io performance data, I do the following steps: >> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >> echo 2G > memory.limit_in_bytes >> use ' cgexec -g memory:nginx' to start Nginx. >> >> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >> >> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >> >> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >> extract the cache files in nvme cache disk. Use iostat to track the >> io data. The data should be align with NIC bw since all data should >> be from cache disk.(need exclude memory as cache storage impact) >> >> Following is the test result: >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> >> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Vladimir Homutov >> Sent: Wednesday, January 20, 2021 12:43 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>> It depends on if disk io is the performance hot spot or not. If yes, >>> io_uring shows improvement than libaio. With 4KB/100KB length 1 >>> Nginx thread it's hard to see performance difference because iostat >>> is only around ~10MB/100MB per second. Disk io is not the >>> performance bottle neck, both libaio and io_uring have the same >>> performance. If you increase request size or Nginx threads number, >>> for example 1MB length or Nginx thread number 4. In this case, disk >>> io became the performance bottle neck, you will see io_uring performance improvement. >> >> Can you please provide full test results with specific nginx configuration? >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From ping.zhao at intel.com Fri Feb 5 06:42:34 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Fri, 5 Feb 2021 06:42:34 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Message-ID: Hi Mikhail, Added 'sendfile on' & 'aio off' test result with previous table: Following is the test result with 100KB and 1MB: (4KB to be test) Nginx worker_processes 1: 4k 100k 1M Io_uring 220MB/s 1GB/s 1.3GB/s Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) sendfile tbt 260MB/s 700MB/s Nginx worker_processes 4: 4k 100k 1M Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) libaio 250MB/s 900MB/s 2.0GB/s sendfile tbt 900MB/s 1.6GB/s Regards, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Thursday, February 4, 2021 4:55 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, My test is much simpler than yours. I created /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. These files does not change during test. I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? Thanks in advance! 04.02.2021 10:08, Zhao, Ping ?????: > Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. > > -----Original Message----- > From: Zhao, Ping > Sent: Thursday, February 4, 2021 10:33 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Mikhail, > > I didn't see this error in my log. Following is my OS/Kernel: > CentOS: 8.1.1911 > Kernel: 5.7.19 > Liburing: liburing-1.0.7-3.el8.x86_64, > liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) > > Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. > > My nginx reported this error before: > 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" > Which is fixed by my 2nd patch(Jan 25) already. > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Wednesday, February 3, 2021 10:11 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Ping Zhao, > > When I try to repeat this test, I've got a huge number of these errors: > > 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read > "/usr/local/html/64746" failed (11: Resource temporarily unavailable) > while sending response to client, client: 127.0.0.1, server: > localhost, > request: "GET /64746 HTTP/1.1", host: "localhost" > > I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. > > Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? > > 25.01.2021 11:24, Zhao, Ping ?????: >> Hello, add a small update to correct the length when part of request already received in previous. >> This case may happen when using io_uring and throughput increased. >> >> # HG changeset patch >> # User Ping Zhao # Date 1611566408 18000 >> # Mon Jan 25 04:20:08 2021 -0500 >> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >> Correct length calculation when part of request received. >> >> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >> @@ -531,6 +531,14 @@ >> >> size = ngx_buf_size(src); >> size = ngx_min(size, dst->end - dst->pos); >> +#if (NGX_HAVE_FILE_IOURING) >> + /* >> + * check if already received part of the request in previous, >> + * calculate the remain length >> + */ >> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >> + size = size - (dst->last - dst->pos); #endif >> >> sendfile = ctx->sendfile && !ctx->directio; >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Zhao, >> Ping >> Sent: Thursday, January 21, 2021 9:44 AM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Vladimir, >> >> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >> >> user nobody; >> daemon off; >> worker_processes 1; >> error_log error.log ; >> events { >> worker_connections 65535; >> use epoll; >> } >> >> http { >> include mime.types; >> default_type application/octet-stream; >> access_log on; >> aio on; >> sendfile off; >> directio 2k; >> >> # Cache Configurations >> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >> >> >> To better measure the disk io performance data, I do the following steps: >> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >> echo 2G > memory.limit_in_bytes >> use ' cgexec -g memory:nginx' to start Nginx. >> >> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >> >> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >> >> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >> extract the cache files in nvme cache disk. Use iostat to track the >> io data. The data should be align with NIC bw since all data should >> be from cache disk.(need exclude memory as cache storage impact) >> >> Following is the test result: >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> >> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Vladimir Homutov >> Sent: Wednesday, January 20, 2021 12:43 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>> It depends on if disk io is the performance hot spot or not. If yes, >>> io_uring shows improvement than libaio. With 4KB/100KB length 1 >>> Nginx thread it's hard to see performance difference because iostat >>> is only around ~10MB/100MB per second. Disk io is not the >>> performance bottle neck, both libaio and io_uring have the same >>> performance. If you increase request size or Nginx threads number, >>> for example 1MB length or Nginx thread number 4. In this case, disk >>> io became the performance bottle neck, you will see io_uring performance improvement. >> >> Can you please provide full test results with specific nginx configuration? >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From ping.zhao at intel.com Sun Feb 7 02:16:47 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Sun, 7 Feb 2021 02:16:47 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Message-ID: Hi Mikhail, I reproduced your problem with kernel 5.8.0-1010-aws. And I tried kernel 5.8.0 which doesn't has this problem. I can confirm there's a regression of aws patch(linux-aws_5.8.0-1010.10.diff) Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: Nginx worker_processes 1: 4k 100k 1M Io_uring 220MB/s 1GB/s 1.3GB/s Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) sendfile 70MB/s 260MB/s 700MB/s Nginx worker_processes 4: 4k 100k 1M Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) libaio 250MB/s 900MB/s 2.0GB/s sendfile 250MB/s 900MB/s 1.6GB/s BR, Ping -----Original Message----- From: Zhao, Ping Sent: Friday, February 5, 2021 2:43 PM To: nginx-devel at nginx.org Subject: RE: [PATCH] Add io_uring support in AIO(async io) module Hi Mikhail, Added 'sendfile on' & 'aio off' test result with previous table: Following is the test result with 100KB and 1MB: (4KB to be test) Nginx worker_processes 1: 4k 100k 1M Io_uring 220MB/s 1GB/s 1.3GB/s Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) sendfile tbt 260MB/s 700MB/s Nginx worker_processes 4: 4k 100k 1M Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) libaio 250MB/s 900MB/s 2.0GB/s sendfile tbt 900MB/s 1.6GB/s Regards, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Thursday, February 4, 2021 4:55 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, My test is much simpler than yours. I created /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. These files does not change during test. I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? Thanks in advance! 04.02.2021 10:08, Zhao, Ping ?????: > Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. > > -----Original Message----- > From: Zhao, Ping > Sent: Thursday, February 4, 2021 10:33 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Mikhail, > > I didn't see this error in my log. Following is my OS/Kernel: > CentOS: 8.1.1911 > Kernel: 5.7.19 > Liburing: liburing-1.0.7-3.el8.x86_64, > liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) > > Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. > > My nginx reported this error before: > 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" > Which is fixed by my 2nd patch(Jan 25) already. > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Wednesday, February 3, 2021 10:11 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Ping Zhao, > > When I try to repeat this test, I've got a huge number of these errors: > > 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read > "/usr/local/html/64746" failed (11: Resource temporarily unavailable) > while sending response to client, client: 127.0.0.1, server: > localhost, > request: "GET /64746 HTTP/1.1", host: "localhost" > > I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. > > Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? > > 25.01.2021 11:24, Zhao, Ping ?????: >> Hello, add a small update to correct the length when part of request already received in previous. >> This case may happen when using io_uring and throughput increased. >> >> # HG changeset patch >> # User Ping Zhao # Date 1611566408 18000 >> # Mon Jan 25 04:20:08 2021 -0500 >> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >> Correct length calculation when part of request received. >> >> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >> @@ -531,6 +531,14 @@ >> >> size = ngx_buf_size(src); >> size = ngx_min(size, dst->end - dst->pos); >> +#if (NGX_HAVE_FILE_IOURING) >> + /* >> + * check if already received part of the request in previous, >> + * calculate the remain length >> + */ >> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >> + size = size - (dst->last - dst->pos); #endif >> >> sendfile = ctx->sendfile && !ctx->directio; >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Zhao, >> Ping >> Sent: Thursday, January 21, 2021 9:44 AM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Vladimir, >> >> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >> >> user nobody; >> daemon off; >> worker_processes 1; >> error_log error.log ; >> events { >> worker_connections 65535; >> use epoll; >> } >> >> http { >> include mime.types; >> default_type application/octet-stream; >> access_log on; >> aio on; >> sendfile off; >> directio 2k; >> >> # Cache Configurations >> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >> >> >> To better measure the disk io performance data, I do the following steps: >> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >> echo 2G > memory.limit_in_bytes >> use ' cgexec -g memory:nginx' to start Nginx. >> >> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >> >> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >> >> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >> extract the cache files in nvme cache disk. Use iostat to track the >> io data. The data should be align with NIC bw since all data should >> be from cache disk.(need exclude memory as cache storage impact) >> >> Following is the test result: >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> >> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Vladimir Homutov >> Sent: Wednesday, January 20, 2021 12:43 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>> It depends on if disk io is the performance hot spot or not. If yes, >>> io_uring shows improvement than libaio. With 4KB/100KB length 1 >>> Nginx thread it's hard to see performance difference because iostat >>> is only around ~10MB/100MB per second. Disk io is not the >>> performance bottle neck, both libaio and io_uring have the same >>> performance. If you increase request size or Nginx threads number, >>> for example 1MB length or Nginx thread number 4. In this case, disk >>> io became the performance bottle neck, you will see io_uring performance improvement. >> >> Can you please provide full test results with specific nginx configuration? >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From maxim at nginx.com Mon Feb 8 14:33:01 2021 From: maxim at nginx.com (Maxim Konovalov) Date: Mon, 8 Feb 2021 17:33:01 +0300 Subject: [PATCH] Define phony make targets as such. In-Reply-To: <8c7fd0395e69fc54e31b6062ec2c72708a523a7d.camel@stammed.net> References: <8c7fd0395e69fc54e31b6062ec2c72708a523a7d.camel@stammed.net> Message-ID: <6b64318e-68fe-105f-2fe9-eb8ca5bc097f@nginx.com> Hi Thibault, On 05.02.2021 02:48, Thibault N?lis wrote: > Hello, > > I just spent more time than I care to admit troubleshooting a make > issue after naively using `./configure --builddir=build` (make target > inadvertently matches this directory name). > > Not sure if taking a dep on POSIX sed in the build system is kosher or > not, but if it is I figure this patch could save the next one some time > ;). > > Quickly tested on top of default tip as of this writing > (7765:519b55453c45). > [...] Thanks for your patch. Ruslan Ermilov is looking at it. He will come with his comments in next several days. Maxim -- Maxim Konovalov From mikhail.isachenkov at nginx.com Mon Feb 8 17:17:27 2021 From: mikhail.isachenkov at nginx.com (Mikhail Isachenkov) Date: Mon, 8 Feb 2021 20:17:27 +0300 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> Message-ID: <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> Hi Zhao Ping, First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. Thanks in advance! 07.02.2021 05:16, Zhao, Ping ?????: > Hi Mikhail, > > I reproduced your problem with kernel 5.8.0-1010-aws. And I tried kernel 5.8.0 which doesn't has this problem. I can confirm there's a regression of aws patch(linux-aws_5.8.0-1010.10.diff) > > Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > sendfile 70MB/s 260MB/s 700MB/s > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > sendfile 250MB/s 900MB/s 1.6GB/s > > BR, > Ping > > -----Original Message----- > From: Zhao, Ping > Sent: Friday, February 5, 2021 2:43 PM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Mikhail, > > Added 'sendfile on' & 'aio off' test result with previous table: > > Following is the test result with 100KB and 1MB: (4KB to be test) > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > sendfile tbt 260MB/s 700MB/s > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > sendfile tbt 900MB/s 1.6GB/s > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail Isachenkov > Sent: Thursday, February 4, 2021 4:55 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > My test is much simpler than yours. I created > /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. > These files does not change during test. > > I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? > > Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? > > Thanks in advance! > > 04.02.2021 10:08, Zhao, Ping ?????: >> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >> >> -----Original Message----- >> From: Zhao, Ping >> Sent: Thursday, February 4, 2021 10:33 AM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Mikhail, >> >> I didn't see this error in my log. Following is my OS/Kernel: >> CentOS: 8.1.1911 >> Kernel: 5.7.19 >> Liburing: liburing-1.0.7-3.el8.x86_64, >> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >> >> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >> >> My nginx reported this error before: >> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >> Which is fixed by my 2nd patch(Jan 25) already. >> >> BR, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Mikhail >> Isachenkov >> Sent: Wednesday, February 3, 2021 10:11 PM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Ping Zhao, >> >> When I try to repeat this test, I've got a huge number of these errors: >> >> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >> "/usr/local/html/64746" failed (11: Resource temporarily unavailable) >> while sending response to client, client: 127.0.0.1, server: >> localhost, >> request: "GET /64746 HTTP/1.1", host: "localhost" >> >> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >> >> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >> >> 25.01.2021 11:24, Zhao, Ping ?????: >>> Hello, add a small update to correct the length when part of request already received in previous. >>> This case may happen when using io_uring and throughput increased. >>> >>> # HG changeset patch >>> # User Ping Zhao # Date 1611566408 18000 >>> # Mon Jan 25 04:20:08 2021 -0500 >>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>> Correct length calculation when part of request received. >>> >>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>> @@ -531,6 +531,14 @@ >>> >>> size = ngx_buf_size(src); >>> size = ngx_min(size, dst->end - dst->pos); >>> +#if (NGX_HAVE_FILE_IOURING) >>> + /* >>> + * check if already received part of the request in previous, >>> + * calculate the remain length >>> + */ >>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>> + size = size - (dst->last - dst->pos); #endif >>> >>> sendfile = ctx->sendfile && !ctx->directio; >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of Zhao, >>> Ping >>> Sent: Thursday, January 21, 2021 9:44 AM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Vladimir, >>> >>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>> >>> user nobody; >>> daemon off; >>> worker_processes 1; >>> error_log error.log ; >>> events { >>> worker_connections 65535; >>> use epoll; >>> } >>> >>> http { >>> include mime.types; >>> default_type application/octet-stream; >>> access_log on; >>> aio on; >>> sendfile off; >>> directio 2k; >>> >>> # Cache Configurations >>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>> >>> >>> To better measure the disk io performance data, I do the following steps: >>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>> echo 2G > memory.limit_in_bytes >>> use ' cgexec -g memory:nginx' to start Nginx. >>> >>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>> >>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>> >>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>> extract the cache files in nvme cache disk. Use iostat to track the >>> io data. The data should be align with NIC bw since all data should >>> be from cache disk.(need exclude memory as cache storage impact) >>> >>> Following is the test result: >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> >>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>> >>> Regards, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Vladimir Homutov >>> Sent: Wednesday, January 20, 2021 12:43 AM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>> It depends on if disk io is the performance hot spot or not. If yes, >>>> io_uring shows improvement than libaio. With 4KB/100KB length 1 >>>> Nginx thread it's hard to see performance difference because iostat >>>> is only around ~10MB/100MB per second. Disk io is not the >>>> performance bottle neck, both libaio and io_uring have the same >>>> performance. If you increase request size or Nginx threads number, >>>> for example 1MB length or Nginx thread number 4. In this case, disk >>>> io became the performance bottle neck, you will see io_uring performance improvement. >>> >>> Can you please provide full test results with specific nginx configuration? >>> >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From thib at stammed.net Mon Feb 8 18:56:09 2021 From: thib at stammed.net (Thibault =?ISO-8859-1?Q?N=E9lis?=) Date: Mon, 8 Feb 2021 19:56:09 +0100 Subject: [PATCH] Define phony make targets as such. In-Reply-To: <6b64318e-68fe-105f-2fe9-eb8ca5bc097f@nginx.com> References: <8c7fd0395e69fc54e31b6062ec2c72708a523a7d.camel@stammed.net> <6b64318e-68fe-105f-2fe9-eb8ca5bc097f@nginx.com> Message-ID: On Mon, 2021-02-08 at 17:33 +0300, Maxim Konovalov wrote: > Ruslan Ermilov is looking at it.? He will come with his comments in > next several days. All good; feel free to prioritize as low priority internally. Ruslan, I just realized I should have used single quotes for the sed expression. Technically everything is fine even with the $/ sequence because / is not a valid shell variable identifier and is thus not substituted (as intended), but anyone reading this (as I did now and as I should have before sending) might have an unnecessary think about this. Feel free to change the double quotes into single quotes if you prefer. $ echo "$foo" $ echo '$foo' $foo $ echo "$/" $/ $ $SHELL --version | head --lines=1 GNU bash, version 5.0.17(1)-release (x86_64-redhat-linux-gnu) From ping.zhao at intel.com Tue Feb 9 08:36:58 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Tue, 9 Feb 2021 08:36:58 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> Message-ID: Hi Mikhail, The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. memory free -lh total used free shared buff/cache available Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi libaio: ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai stl| read writ| recv send| in out | int csw 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 Io_uring: ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai stl| read writ| recv send| in out | int csw 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. Memory: free -lh total used free shared buff/cache available Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi Libaio: ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai stl| read writ| recv send| in out | int csw 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k Io_uring: ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai stl| read writ| recv send| in out | int csw 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Tuesday, February 9, 2021 1:17 AM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. Thanks in advance! 07.02.2021 05:16, Zhao, Ping ?????: > Hi Mikhail, > > I reproduced your problem with kernel 5.8.0-1010-aws. And I tried > kernel 5.8.0 which doesn't has this problem. I can confirm there's a > regression of aws patch(linux-aws_5.8.0-1010.10.diff) > > Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > sendfile 70MB/s 260MB/s 700MB/s > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > sendfile 250MB/s 900MB/s 1.6GB/s > > BR, > Ping > > -----Original Message----- > From: Zhao, Ping > Sent: Friday, February 5, 2021 2:43 PM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Mikhail, > > Added 'sendfile on' & 'aio off' test result with previous table: > > Following is the test result with 100KB and 1MB: (4KB to be test) > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > sendfile tbt 260MB/s 700MB/s > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > sendfile tbt 900MB/s 1.6GB/s > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Thursday, February 4, 2021 4:55 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > My test is much simpler than yours. I created > /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. > These files does not change during test. > > I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? > > Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? > > Thanks in advance! > > 04.02.2021 10:08, Zhao, Ping ?????: >> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >> >> -----Original Message----- >> From: Zhao, Ping >> Sent: Thursday, February 4, 2021 10:33 AM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Mikhail, >> >> I didn't see this error in my log. Following is my OS/Kernel: >> CentOS: 8.1.1911 >> Kernel: 5.7.19 >> Liburing: liburing-1.0.7-3.el8.x86_64, >> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >> >> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >> >> My nginx reported this error before: >> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >> Which is fixed by my 2nd patch(Jan 25) already. >> >> BR, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Mikhail Isachenkov >> Sent: Wednesday, February 3, 2021 10:11 PM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Ping Zhao, >> >> When I try to repeat this test, I've got a huge number of these errors: >> >> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >> "/usr/local/html/64746" failed (11: Resource temporarily unavailable) >> while sending response to client, client: 127.0.0.1, server: >> localhost, >> request: "GET /64746 HTTP/1.1", host: "localhost" >> >> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >> >> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >> >> 25.01.2021 11:24, Zhao, Ping ?????: >>> Hello, add a small update to correct the length when part of request already received in previous. >>> This case may happen when using io_uring and throughput increased. >>> >>> # HG changeset patch >>> # User Ping Zhao # Date 1611566408 18000 >>> # Mon Jan 25 04:20:08 2021 -0500 >>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>> Correct length calculation when part of request received. >>> >>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>> @@ -531,6 +531,14 @@ >>> >>> size = ngx_buf_size(src); >>> size = ngx_min(size, dst->end - dst->pos); >>> +#if (NGX_HAVE_FILE_IOURING) >>> + /* >>> + * check if already received part of the request in previous, >>> + * calculate the remain length >>> + */ >>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>> + size = size - (dst->last - dst->pos); #endif >>> >>> sendfile = ctx->sendfile && !ctx->directio; >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of Zhao, >>> Ping >>> Sent: Thursday, January 21, 2021 9:44 AM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Vladimir, >>> >>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>> >>> user nobody; >>> daemon off; >>> worker_processes 1; >>> error_log error.log ; >>> events { >>> worker_connections 65535; >>> use epoll; >>> } >>> >>> http { >>> include mime.types; >>> default_type application/octet-stream; >>> access_log on; >>> aio on; >>> sendfile off; >>> directio 2k; >>> >>> # Cache Configurations >>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>> >>> >>> To better measure the disk io performance data, I do the following steps: >>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>> echo 2G > memory.limit_in_bytes >>> use ' cgexec -g memory:nginx' to start Nginx. >>> >>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>> >>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>> >>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>> extract the cache files in nvme cache disk. Use iostat to track the >>> io data. The data should be align with NIC bw since all data should >>> be from cache disk.(need exclude memory as cache storage impact) >>> >>> Following is the test result: >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> >>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>> >>> Regards, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Vladimir Homutov >>> Sent: Wednesday, January 20, 2021 12:43 AM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>> It depends on if disk io is the performance hot spot or not. If >>>> yes, io_uring shows improvement than libaio. With 4KB/100KB length >>>> 1 Nginx thread it's hard to see performance difference because >>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>> performance bottle neck, both libaio and io_uring have the same >>>> performance. If you increase request size or Nginx threads number, >>>> for example 1MB length or Nginx thread number 4. In this case, disk >>>> io became the performance bottle neck, you will see io_uring performance improvement. >>> >>> Can you please provide full test results with specific nginx configuration? >>> >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From mikhail.isachenkov at nginx.com Tue Feb 9 13:30:46 2021 From: mikhail.isachenkov at nginx.com (Mikhail Isachenkov) Date: Tue, 9 Feb 2021 16:30:46 +0300 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> Message-ID: <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> Hi Zhao Ping, Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx 3. Limit memory to 80 Mb, for example: echo 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. For example, with 100kb files and 1 worker process: free -lh total used free shared buff/cache available Mem: 15Gi 212Mi 14Gi 13Mi 318Mi 14Gi dstat/libaio 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 dstat/io_uring 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 As you can see, libaio even faster a bit. 09.02.2021 11:36, Zhao, Ping ?????: > Hi Mikhail, > > The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. > > If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. > > memory > free -lh > total used free shared buff/cache available > Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi > > libaio: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 > 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 > 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 > 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 > 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 > 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 > 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 > 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 > > Io_uring: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 > 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 > 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 > 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 > 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 > > I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. > > Memory: > free -lh > total used free shared buff/cache available > Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi > > Libaio: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k > 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k > > Io_uring: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k > 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k > 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k > 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k > 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k > 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k > 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k > > Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail Isachenkov > Sent: Tuesday, February 9, 2021 1:17 AM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. > > I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. > > As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: > > a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. > > b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). > > I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? > > Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. > > Thanks in advance! > > 07.02.2021 05:16, Zhao, Ping ?????: >> Hi Mikhail, >> >> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >> >> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> sendfile 70MB/s 260MB/s 700MB/s >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> sendfile 250MB/s 900MB/s 1.6GB/s >> >> BR, >> Ping >> >> -----Original Message----- >> From: Zhao, Ping >> Sent: Friday, February 5, 2021 2:43 PM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Mikhail, >> >> Added 'sendfile on' & 'aio off' test result with previous table: >> >> Following is the test result with 100KB and 1MB: (4KB to be test) >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> sendfile tbt 260MB/s 700MB/s >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> sendfile tbt 900MB/s 1.6GB/s >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Mikhail >> Isachenkov >> Sent: Thursday, February 4, 2021 4:55 PM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> My test is much simpler than yours. I created >> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >> These files does not change during test. >> >> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >> >> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >> >> Thanks in advance! >> >> 04.02.2021 10:08, Zhao, Ping ?????: >>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>> >>> -----Original Message----- >>> From: Zhao, Ping >>> Sent: Thursday, February 4, 2021 10:33 AM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Mikhail, >>> >>> I didn't see this error in my log. Following is my OS/Kernel: >>> CentOS: 8.1.1911 >>> Kernel: 5.7.19 >>> Liburing: liburing-1.0.7-3.el8.x86_64, >>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>> >>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>> >>> My nginx reported this error before: >>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>> Which is fixed by my 2nd patch(Jan 25) already. >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Wednesday, February 3, 2021 10:11 PM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Ping Zhao, >>> >>> When I try to repeat this test, I've got a huge number of these errors: >>> >>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>> "/usr/local/html/64746" failed (11: Resource temporarily unavailable) >>> while sending response to client, client: 127.0.0.1, server: >>> localhost, >>> request: "GET /64746 HTTP/1.1", host: "localhost" >>> >>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>> >>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>> >>> 25.01.2021 11:24, Zhao, Ping ?????: >>>> Hello, add a small update to correct the length when part of request already received in previous. >>>> This case may happen when using io_uring and throughput increased. >>>> >>>> # HG changeset patch >>>> # User Ping Zhao # Date 1611566408 18000 >>>> # Mon Jan 25 04:20:08 2021 -0500 >>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>> Correct length calculation when part of request received. >>>> >>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>> @@ -531,6 +531,14 @@ >>>> >>>> size = ngx_buf_size(src); >>>> size = ngx_min(size, dst->end - dst->pos); >>>> +#if (NGX_HAVE_FILE_IOURING) >>>> + /* >>>> + * check if already received part of the request in previous, >>>> + * calculate the remain length >>>> + */ >>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>> + size = size - (dst->last - dst->pos); #endif >>>> >>>> sendfile = ctx->sendfile && !ctx->directio; >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of Zhao, >>>> Ping >>>> Sent: Thursday, January 21, 2021 9:44 AM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Vladimir, >>>> >>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>> >>>> user nobody; >>>> daemon off; >>>> worker_processes 1; >>>> error_log error.log ; >>>> events { >>>> worker_connections 65535; >>>> use epoll; >>>> } >>>> >>>> http { >>>> include mime.types; >>>> default_type application/octet-stream; >>>> access_log on; >>>> aio on; >>>> sendfile off; >>>> directio 2k; >>>> >>>> # Cache Configurations >>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>> >>>> >>>> To better measure the disk io performance data, I do the following steps: >>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>> echo 2G > memory.limit_in_bytes >>>> use ' cgexec -g memory:nginx' to start Nginx. >>>> >>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>> >>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>> >>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>> extract the cache files in nvme cache disk. Use iostat to track the >>>> io data. The data should be align with NIC bw since all data should >>>> be from cache disk.(need exclude memory as cache storage impact) >>>> >>>> Following is the test result: >>>> >>>> Nginx worker_processes 1: >>>> 4k 100k 1M >>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>> >>>> >>>> Nginx worker_processes 4: >>>> 4k 100k 1M >>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>> libaio 250MB/s 900MB/s 2.0GB/s >>>> >>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>> >>>> Regards, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Vladimir Homutov >>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>> It depends on if disk io is the performance hot spot or not. If >>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB length >>>>> 1 Nginx thread it's hard to see performance difference because >>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>> performance bottle neck, both libaio and io_uring have the same >>>>> performance. If you increase request size or Nginx threads number, >>>>> for example 1MB length or Nginx thread number 4. In this case, disk >>>>> io became the performance bottle neck, you will see io_uring performance improvement. >>>> >>>> Can you please provide full test results with specific nginx configuration? >>>> >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services -------------- next part -------------- user nobody; worker_processes 1; pid /run/nginx.pid; worker_rlimit_nofile 65536; events { worker_connections 65536; } http { sendfile on; aio off; #sendfile off; #aio on; #directio 2k; error_log /var/log/nginx/error.log; log_format upstream '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent $request_time $upstream_addr $upstream_response_time $upstream_status ' '"$http_referer" "$http_user_agent" "$upstream_cache_status"'; #access_log /var/log/nginx/access.log upstream buffer=128k; access_log off; proxy_cache_path /usr/local/html/cache levels=1:2 keys_zone=one:10m; proxy_set_header Host $host; proxy_set_header Connection ''; proxy_http_version 1.1; upstream d { zone d 64k; keepalive 64; server 127.0.0.1:8002; } server { location / { proxy_pass http://d; proxy_cache_key $uri; proxy_cache one; proxy_cache_valid 1d; } } server { listen 8002; root /usr/local/html; } } -------------- next part -------------- A non-text attachment was scrubbed... Name: add_random.lua Type: text/x-lua Size: 635 bytes Desc: not available URL: From mdounin at mdounin.ru Tue Feb 9 14:15:27 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Feb 2021 17:15:27 +0300 Subject: [PATCH] Define phony make targets as such. In-Reply-To: References: <8c7fd0395e69fc54e31b6062ec2c72708a523a7d.camel@stammed.net> <6b64318e-68fe-105f-2fe9-eb8ca5bc097f@nginx.com> Message-ID: <20210209141527.GH77619@mdounin.ru> Hello! On Mon, Feb 08, 2021 at 07:56:09PM +0100, Thibault N?lis wrote: > On Mon, 2021-02-08 at 17:33 +0300, Maxim Konovalov wrote: > > Ruslan Ermilov is looking at it.? He will come with his comments in > > next several days. > > All good; feel free to prioritize as low priority internally. > > Ruslan, I just realized I should have used single quotes for the sed > expression. Technically everything is fine even with the $/ sequence > because / is not a valid shell variable identifier and is thus not > substituted (as intended), but anyone reading this (as I did now and as > I should have before sending) might have an unnecessary think about > this. Feel free to change the double quotes into single quotes if you > prefer. Certainly there is no need to use sed at all. And using .PHONY as the first target is going to break badly on make's without .PHONY support, such as nmake on Windows. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Wed Feb 10 14:03:57 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 10 Feb 2021 14:03:57 +0000 Subject: [njs] Stream: fixed processing buffered data in body filter. Message-ID: details: https://hg.nginx.org/njs/rev/0d15daffba9e branches: changeset: 1600:0d15daffba9e user: Dmitry Volyntsev date: Wed Feb 10 14:03:11 2021 +0000 description: Stream: fixed processing buffered data in body filter. Previously, when data was proxied to upstream, it may be partially written and is left in upstream connection buffer. Later, when writing becomes possible again, the body filter is called but it fails to call the next filter in the chain. This resulted in hanging connection. The fix is to take the buffered data in upstream connection into account. This fixes #368 issue on Github. diffstat: nginx/ngx_stream_js_module.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diffs (28 lines): diff -r a41cd80e2f3a -r 0d15daffba9e nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Feb 01 02:16:51 2021 +0100 +++ b/nginx/ngx_stream_js_module.c Wed Feb 10 14:03:11 2021 +0000 @@ -506,7 +506,7 @@ ngx_stream_js_body_filter(ngx_stream_ses njs_int_t ret; ngx_int_t rc; ngx_chain_t *out, *cl; - ngx_connection_t *c; + ngx_connection_t *c, *dst; ngx_stream_js_ev_t *event; ngx_stream_js_ctx_t *ctx; ngx_stream_js_srv_conf_t *jscf; @@ -580,7 +580,14 @@ ngx_stream_js_body_filter(ngx_stream_ses *ctx->last_out = NULL; - if (out != NULL || c->buffered) { + if (from_upstream) { + dst = c; + + } else { + dst = s->upstream ? s->upstream->peer.connection : NULL; + } + + if (out != NULL || dst == NULL || dst->buffered) { rc = ngx_stream_next_filter(s, out, from_upstream); ngx_chain_update_chains(c->pool, &ctx->free, &ctx->busy, &out, From serg.brester at sebres.de Wed Feb 10 17:30:45 2021 From: serg.brester at sebres.de (Dipl. Ing. Sergey Brester) Date: Wed, 10 Feb 2021 18:30:45 +0100 Subject: "detach" upstream from request (or allow send from keepalive saved connection) / FastCGI multiplexing Message-ID: Hi, I have a question: how an upstream could be properly "detached" from request in case it gets closed by client? Some time ago I have implemented a FastCGI multiplexing for nginx, which would work pretty well, excepting the case if a request gets closed by client side. In such a case _ngx_http_upstream_finalize_request_ would close the upstream connection. This may not be worse for a single connect per request, but very annoying in case of multiplexing, since closing of such upstream connect means a simultaneous close for N requests not involved by the client, but serving through the same upstream pipe. So I was trying to implement abortive "close", using send of ABORT_REQUEST (2) packet, corresponding FastCGI protocol. Since _upstream->abort_request_ handler is not yet implemented in nginx, my first attempt was just to extend _ngx_http_fastcgi_finalize_request_ in order to create new send buffer there and restore _r->upstream->keepalive _so that _u->peer.free _in _ngx_http_upstream_finalize_request_ would retain the upstream connect. So I see "free keepalive peer: saving connection" logged (and connect is not closed), but probably because _ngx_http_upstream_free_keepalive_peer_ moved it to cached queue, it does not send ABORT_REQUEST packet to the fastcgi side. Is there some proper way to retain an upstream connection (able to send) which is detached from request by close or before close, so such an abortive "disconnect" can be handled through upstream pipe? With other words avoid an upstream close or saving keepalive connection in _ngx_http_fastcgi_finalize_request_. Regards, Sergey. -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevin at meter.com Thu Feb 11 01:02:54 2021 From: kevin at meter.com (Kevin Burke) Date: Wed, 10 Feb 2021 17:02:54 -0800 Subject: Adding a second TLS implementation Message-ID: Hi, There has been a recent push by some members of the security community to try to make more critical code run in memory safe languages, because of the high prevalence of security issues related to memory safety, for example, use-after-free, double-free or heap buffer vulnerabilities. In that light, I was wondering if you'd be open to adding a second TLS implementation that could be used in place of OpenSSL. Ideally, the target would be a TLS implementation in a memory safe language, for example, rustls, available at https://github.com/ctz/rustls. Curl just merged a patch to support the rustls backend. This would require a lot of changes to make the TLS implementation portable so before investigating it I figured I would see if you're open to it at all. Kevin -------------- next part -------------- An HTML attachment was scrubbed... URL: From mat999 at gmail.com Thu Feb 11 02:28:29 2021 From: mat999 at gmail.com (Mathew Heard) Date: Thu, 11 Feb 2021 13:28:29 +1100 Subject: Adding a second TLS implementation In-Reply-To: References: Message-ID: Kevin, BoringSSL is already for the most part supported (in code, if not officially) if I am not mistaken On Thu, 11 Feb 2021 at 12:02, Kevin Burke wrote: > Hi, > There has been a recent push by some members of the security community to > try to make more critical code run in memory safe languages, because of the > high prevalence of security issues related to memory safety, for example, > use-after-free, double-free or heap buffer vulnerabilities. > > In that light, I was wondering if you'd be open to adding a second TLS > implementation that could be used in place of OpenSSL. Ideally, the target > would be a TLS implementation in a memory safe language, for example, > rustls, available at https://github.com/ctz/rustls. Curl just merged a > patch to support the rustls backend. > > This would require a lot of changes to make the TLS implementation > portable so before investigating it I figured I would see if you're open to > it at all. > > Kevin > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Feb 11 02:38:25 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 05:38:25 +0300 Subject: Adding a second TLS implementation In-Reply-To: References: Message-ID: <20210211023825.GN77619@mdounin.ru> Hello! On Wed, Feb 10, 2021 at 05:02:54PM -0800, Kevin Burke wrote: > Hi, > There has been a recent push by some members of the security community to > try to make more critical code run in memory safe languages, because of the > high prevalence of security issues related to memory safety, for example, > use-after-free, double-free or heap buffer vulnerabilities. > > In that light, I was wondering if you'd be open to adding a second TLS > implementation that could be used in place of OpenSSL. Ideally, the target > would be a TLS implementation in a memory safe language, for example, > rustls, available at https://github.com/ctz/rustls. Curl just merged a > patch to support the rustls backend. > > This would require a lot of changes to make the TLS implementation portable > so before investigating it I figured I would see if you're open to it at > all. We already support three distinct SSL libraries: OpenSSL, LibreSSL, and BoringSSL. It is unlikely that support for other libraries will be considered: that's already way more than it's comfortable to support. We are, however, open for patches to improve portability of the SSL code, such as providing ngx_ssl_*() wrapper functions in (very few, actually) places where SSL library interfaces are used directly rather than via appropriate ngx_ssl_*() wrappers. -- Maxim Dounin http://mdounin.ru/ From kevin at meter.com Thu Feb 11 04:07:46 2021 From: kevin at meter.com (Kevin Burke) Date: Wed, 10 Feb 2021 20:07:46 -0800 Subject: Adding a second TLS implementation In-Reply-To: <20210211023825.GN77619@mdounin.ru> References: <20210211023825.GN77619@mdounin.ru> Message-ID: Thanks for the prompt reply. We are, however, open for patches to improve portability of the > SSL code, such as providing ngx_ssl_*() wrapper functions in (very > few, actually) places where SSL library interfaces are used > directly rather than via appropriate ngx_ssl_*() wrappers. If implemented, would the additional wrapper functions make it possible to compile in a memory safe TLS integration as a third party module? On Wed, Feb 10, 2021 at 6:38 PM Maxim Dounin wrote: > Hello! > > On Wed, Feb 10, 2021 at 05:02:54PM -0800, Kevin Burke wrote: > > > Hi, > > There has been a recent push by some members of the security community to > > try to make more critical code run in memory safe languages, because of > the > > high prevalence of security issues related to memory safety, for example, > > use-after-free, double-free or heap buffer vulnerabilities. > > > > In that light, I was wondering if you'd be open to adding a second TLS > > implementation that could be used in place of OpenSSL. Ideally, the > target > > would be a TLS implementation in a memory safe language, for example, > > rustls, available at https://github.com/ctz/rustls. Curl just merged a > > patch to support the rustls backend. > > > > This would require a lot of changes to make the TLS implementation > portable > > so before investigating it I figured I would see if you're open to it at > > all. > > We already support three distinct SSL libraries: OpenSSL, > LibreSSL, and BoringSSL. It is unlikely that support for other > libraries will be considered: that's already way more than it's > comfortable to support. > > We are, however, open for patches to improve portability of the > SSL code, such as providing ngx_ssl_*() wrapper functions in (very > few, actually) places where SSL library interfaces are used > directly rather than via appropriate ngx_ssl_*() wrappers. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Feb 11 13:28:31 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 16:28:31 +0300 Subject: Adding a second TLS implementation In-Reply-To: References: <20210211023825.GN77619@mdounin.ru> Message-ID: <20210211132831.GO77619@mdounin.ru> Hello! On Wed, Feb 10, 2021 at 08:07:46PM -0800, Kevin Burke wrote: > > We are, however, open for patches to improve portability of the > > SSL code, such as providing ngx_ssl_*() wrapper functions in (very > > few, actually) places where SSL library interfaces are used > > directly rather than via appropriate ngx_ssl_*() wrappers. > > If implemented, would the additional wrapper functions make it possible to > compile in a memory safe TLS integration as a third party module? Unlikely. SSL implementation is integrated into nginx core and cannot be replaced as a module. It is, however, will make it possible to provide alternative SSL implementations with minimal patching, simply by providing alternatives to ngx_even_openssl.[ch]. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Thu Feb 11 15:05:37 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 11 Feb 2021 15:05:37 +0000 Subject: [njs] Allowing to pass arbitrary number of arguments in ngx_js_call(). Message-ID: details: https://hg.nginx.org/njs/rev/9631d5c88caf branches: changeset: 1601:9631d5c88caf user: Dmitry Volyntsev date: Thu Feb 11 14:30:59 2021 +0000 description: Allowing to pass arbitrary number of arguments in ngx_js_call(). diffstat: nginx/ngx_http_js_module.c | 10 +++++----- nginx/ngx_js.c | 6 +++--- nginx/ngx_js.h | 4 ++-- nginx/ngx_stream_js_module.c | 8 +++++--- 4 files changed, 15 insertions(+), 13 deletions(-) diffs (103 lines): diff -r 0d15daffba9e -r 9631d5c88caf nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Wed Feb 10 14:03:11 2021 +0000 +++ b/nginx/ngx_http_js_module.c Thu Feb 11 14:30:59 2021 +0000 @@ -660,8 +660,8 @@ ngx_http_js_content_event_handler(ngx_ht ctx->status = NGX_HTTP_INTERNAL_SERVER_ERROR; - rc = ngx_js_call(ctx->vm, &jlcf->content, &ctx->request, - r->connection->log); + rc = ngx_js_call(ctx->vm, &jlcf->content, r->connection->log, + &ctx->request, 1); if (rc == NGX_ERROR) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -773,8 +773,8 @@ ngx_http_js_header_filter(ngx_http_reque pending = njs_vm_pending(ctx->vm); - rc = ngx_js_call(ctx->vm, &jlcf->header_filter, &ctx->request, - r->connection->log); + rc = ngx_js_call(ctx->vm, &jlcf->header_filter, r->connection->log, + &ctx->request, 1); if (rc == NGX_ERROR) { return NGX_ERROR; @@ -820,7 +820,7 @@ ngx_http_js_variable(ngx_http_request_t pending = njs_vm_pending(ctx->vm); - rc = ngx_js_call(ctx->vm, fname, &ctx->request, r->connection->log); + rc = ngx_js_call(ctx->vm, fname, r->connection->log, &ctx->request, 1); if (rc == NGX_ERROR) { v->not_found = 1; diff -r 0d15daffba9e -r 9631d5c88caf nginx/ngx_js.c --- a/nginx/ngx_js.c Wed Feb 10 14:03:11 2021 +0000 +++ b/nginx/ngx_js.c Thu Feb 11 14:30:59 2021 +0000 @@ -66,8 +66,8 @@ static njs_external_t ngx_js_ext_core[] ngx_int_t -ngx_js_call(njs_vm_t *vm, ngx_str_t *fname, njs_opaque_value_t *value, - ngx_log_t *log) +ngx_js_call(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, + njs_opaque_value_t *args, njs_uint_t nargs) { njs_str_t name, exception; njs_function_t *func; @@ -82,7 +82,7 @@ ngx_js_call(njs_vm_t *vm, ngx_str_t *fna return NGX_ERROR; } - if (njs_vm_call(vm, func, njs_value_arg(value), 1) != NJS_OK) { + if (njs_vm_call(vm, func, njs_value_arg(args), nargs) != NJS_OK) { njs_vm_retval_string(vm, &exception); ngx_log_error(NGX_LOG_ERR, log, 0, diff -r 0d15daffba9e -r 9631d5c88caf nginx/ngx_js.h --- a/nginx/ngx_js.h Wed Feb 10 14:03:11 2021 +0000 +++ b/nginx/ngx_js.h Thu Feb 11 14:30:59 2021 +0000 @@ -49,8 +49,8 @@ typedef ngx_msec_t (*ngx_external_resolv : njs_vm_value_buffer_set(vm, value, start, len)) -ngx_int_t ngx_js_call(njs_vm_t *vm, ngx_str_t *s, njs_opaque_value_t *value, - ngx_log_t *log); +ngx_int_t ngx_js_call(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, + njs_opaque_value_t *args, njs_uint_t nargs); njs_int_t ngx_js_ext_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t level); diff -r 0d15daffba9e -r 9631d5c88caf nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Wed Feb 10 14:03:11 2021 +0000 +++ b/nginx/ngx_stream_js_module.c Thu Feb 11 14:30:59 2021 +0000 @@ -461,7 +461,8 @@ ngx_stream_js_phase_handler(ngx_stream_s ctx->status = NGX_ERROR; - rc = ngx_js_call(ctx->vm, name, &ctx->args[0], c->log); + rc = ngx_js_call(ctx->vm, name, c->log, &ctx->args[0], 1); + if (rc == NGX_ERROR) { return rc; } @@ -534,7 +535,8 @@ ngx_stream_js_body_filter(ngx_stream_ses ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module); if (!ctx->filter) { - rc = ngx_js_call(ctx->vm, &jscf->filter, &ctx->args[0], c->log); + rc = ngx_js_call(ctx->vm, &jscf->filter, c->log, &ctx->args[0], 1); + if (rc == NGX_ERROR) { return rc; } @@ -630,7 +632,7 @@ ngx_stream_js_variable(ngx_stream_sessio pending = njs_vm_pending(ctx->vm); - rc = ngx_js_call(ctx->vm, fname, &ctx->args[0], s->connection->log); + rc = ngx_js_call(ctx->vm, fname, s->connection->log, &ctx->args[0], 1); if (rc == NGX_ERROR) { v->not_found = 1; From xeioex at nginx.com Thu Feb 11 15:05:39 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 11 Feb 2021 15:05:39 +0000 Subject: [njs] Types: added definitions for fetch method. Message-ID: details: https://hg.nginx.org/njs/rev/374dec48b9e4 branches: changeset: 1602:374dec48b9e4 user: Dmitry Volyntsev date: Thu Feb 11 14:39:13 2021 +0000 description: Types: added definitions for fetch method. diffstat: test/ts/test.ts | 11 +++++ ts/ngx_core.d.ts | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 0 deletions(-) diffs (143 lines): diff -r 9631d5c88caf -r 374dec48b9e4 test/ts/test.ts --- a/test/ts/test.ts Thu Feb 11 14:30:59 2021 +0000 +++ b/test/ts/test.ts Thu Feb 11 14:39:13 2021 +0000 @@ -82,6 +82,17 @@ function http_module(r: NginxHTTPRequest // r.responseBuffer r.responseBuffer?.equals(Buffer.from([1])); + + ngx.fetch('http://nginx.org/', {method:'POST', headers:{Foo:'bar'}}) + .then(reply => { + if (reply.headers.get('foo')) { + throw 'oops' + }; + + return reply.text() + }) + .then(body => r.return(200, body)) + .catch(e => r.return(501, e.message)) } function fs_module() { diff -r 9631d5c88caf -r 374dec48b9e4 ts/ngx_core.d.ts --- a/ts/ngx_core.d.ts Thu Feb 11 14:30:59 2021 +0000 +++ b/ts/ngx_core.d.ts Thu Feb 11 14:39:13 2021 +0000 @@ -1,3 +1,102 @@ +interface NgxResponseHeaders { + /** + * Returns a string containing the values of all headers + * with the specified name separated by a comma and a space. + * @param name A name of the header. + */ + get(name:NjsStringLike): NjsByteString; + /** + * Returns an array containing the values of all headers + * with the specified name. + * @param name A name of the header. + */ + getAll(name:NjsStringLike): NjsByteString; + /** + * Returns a boolean value indicating whether a header with + * the specified name exists. + * @param name A name of the header. + */ + has(name:NjsStringLike): NjsByteString; +} + +interface NgxResponse { + /** + * Takes a Response stream and reads it to completion. + * Returns a Promise that resolves with an ArrayBuffer. + */ + arrayBuffer(): Promise; + /** + * A boolean value, true if the body has been used. + */ + readonly bodyUsed: boolean; + /** + * Takes a Response stream and reads it to completion. + * Returns a Promise that resolves with the result of + * parsing the body text as JSON. + */ + json(): Promise; + /** + * The NgxResponseHeaders object associated with the response. + */ + headers: NgxResponseHeaders; + /** + * A boolean value, true if the response was successful + * (status in the range 200-299). + */ + readonly ok: boolean; + /** + * A boolean value, true if the response is the result + * of a redirect. + */ + readonly redirected: boolean; + /** + * The status code of the response. + */ + readonly status: number; + /** + * The status message corresponding to the status code. + */ + readonly statusText: NjsByteString; + /** + * Takes a Response stream and reads it to completion. + * Returns a Promise that resolves with a string. + */ + text(): Promise; + /** + * The type of the response. + */ + readonly type: NjsByteString; + /** + * Response url. + */ + readonly url: NjsByteString; +} + +interface NgxFetchOptions { + /** + * Request body, by default is empty. + */ + body?: NjsStringLike, + /** + * The buffer size for reading the response, by default is 4096. + * Nginx specific. + */ + buffer_size?: Number, + /** + * Request headers object. + */ + headers?: Object, + /** + * The maximum size of the response body in bytes, by default is 32768. + * Nginx specific. + */ + max_response_body_size?: Number, + /** + * Request method, by default the GET method is used. + */ + method?: NjsStringLike; +} + interface NgxObject { readonly INFO: number; readonly WARN: number; @@ -9,6 +108,15 @@ interface NgxObject { * @param message Message to log. */ log(level: number, message: NjsStringOrBuffer): void; + /** + * Makes a request to fetch an URL. + * Returns a Promise that resolves with the NgxResponse object. + * Only the http:// scheme is supported, redirects are not handled. + * @param url URL of a resource to fetch. + * @param options An object containing additional settings. + * @since 0.5.1 + */ + fetch(url: NjsStringOrBuffer, options?: NgxFetchOptions): Promise; } declare const ngx: NgxObject; From mdounin at mdounin.ru Thu Feb 11 19:57:19 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:19 +0000 Subject: [nginx] Reuse of connections in lingering close. Message-ID: details: https://hg.nginx.org/nginx/rev/3e83336cda5b branches: changeset: 7766:3e83336cda5b user: Maxim Dounin date: Thu Feb 11 21:52:09 2021 +0300 description: Reuse of connections in lingering close. This is particularly important in HTTP/2, where keepalive connections are closed with lingering. Before the patch, reusing a keepalive HTTP/2 connection resulted in the connection waiting for lingering close to remain in the reusable connections queue, preventing ngx_drain_connections() from closing additional connections. The patch fixes it by marking the connection reusable again, and so moving it in the reusable connections queue. Further, it makes actually possible to reuse such connections if needed. diffstat: src/http/ngx_http_request.c | 5 ++++- src/http/v2/ngx_http_v2.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diffs (44 lines): diff -r 519b55453c45 -r 3e83336cda5b src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Mon Feb 01 16:42:50 2021 +0300 +++ b/src/http/ngx_http_request.c Thu Feb 11 21:52:09 2021 +0300 @@ -3437,6 +3437,9 @@ ngx_http_set_lingering_close(ngx_connect return; } + c->close = 0; + ngx_reusable_connection(c, 1); + ngx_add_timer(rev, clcf->lingering_timeout); if (rev->ready) { @@ -3461,7 +3464,7 @@ ngx_http_lingering_close_handler(ngx_eve ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http lingering close handler"); - if (rev->timedout) { + if (rev->timedout || c->close) { ngx_http_close_request(r, 0); return; } diff -r 519b55453c45 -r 3e83336cda5b src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Mon Feb 01 16:42:50 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:09 2021 +0300 @@ -767,6 +767,9 @@ ngx_http_v2_lingering_close(ngx_connecti return; } + c->close = 0; + ngx_reusable_connection(c, 1); + ngx_add_timer(rev, clcf->lingering_timeout); if (rev->ready) { @@ -791,7 +794,7 @@ ngx_http_v2_lingering_close_handler(ngx_ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 lingering close handler"); - if (rev->timedout) { + if (rev->timedout || c->close) { ngx_http_close_connection(c); return; } From mdounin at mdounin.ru Thu Feb 11 19:57:22 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:22 +0000 Subject: [nginx] Additional connections reuse. Message-ID: details: https://hg.nginx.org/nginx/rev/6d98f29867e8 branches: changeset: 7767:6d98f29867e8 user: Maxim Dounin date: Thu Feb 11 21:52:11 2021 +0300 description: Additional connections reuse. If ngx_drain_connections() fails to immediately reuse any connections and there are no free connections, it now additionally tries to reuse a connection again. This helps to provide at least one free connection in case of HTTP/2 with lingering close, where merely trying to reuse a connection once does not free it, but makes it reusable again, waiting for lingering close. diffstat: src/core/ngx_connection.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diffs (33 lines): diff -r 3e83336cda5b -r 6d98f29867e8 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Thu Feb 11 21:52:09 2021 +0300 +++ b/src/core/ngx_connection.c Thu Feb 11 21:52:11 2021 +0300 @@ -1310,6 +1310,7 @@ ngx_drain_connections(ngx_cycle_t *cycle cycle->connection_n); } + c = NULL; n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1); for (i = 0; i < n; i++) { @@ -1326,6 +1327,21 @@ ngx_drain_connections(ngx_cycle_t *cycle c->close = 1; c->read->handler(c->read); } + + if (cycle->free_connection_n == 0 && c && c->reusable) { + + /* + * if no connections were freed, try to reuse the last + * connection again: this should free it as long as + * previous reuse moved it to lingering close + */ + + ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, + "reusing connection again"); + + c->close = 1; + c->read->handler(c->read); + } } From mdounin at mdounin.ru Thu Feb 11 19:57:24 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:24 +0000 Subject: [nginx] HTTP/2: reuse of connections with incomplete frames. Message-ID: details: https://hg.nginx.org/nginx/rev/fc536dcdbbf7 branches: changeset: 7768:fc536dcdbbf7 user: Maxim Dounin date: Thu Feb 11 21:52:12 2021 +0300 description: HTTP/2: reuse of connections with incomplete frames. Prodded by Taewoo Kim. diffstat: src/http/v2/ngx_http_v2.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diffs (32 lines): diff -r 6d98f29867e8 -r fc536dcdbbf7 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:11 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:12 2021 +0300 @@ -362,6 +362,11 @@ ngx_http_v2_read_handler(ngx_event_t *re return; } + if (!h2c->processing && !h2c->pushing) { + ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); + return; + } + if (!h2c->goaway) { h2c->goaway = 1; @@ -668,6 +673,8 @@ ngx_http_v2_handle_connection(ngx_http_v return; } + ngx_reusable_connection(c, 1); + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, ngx_http_v2_module); if (h2c->state.incomplete) { @@ -689,7 +696,6 @@ ngx_http_v2_handle_connection(ngx_http_v #endif c->destroyed = 1; - ngx_reusable_connection(c, 1); c->write->handler = ngx_http_empty_handler; c->read->handler = ngx_http_v2_idle_handler; From mdounin at mdounin.ru Thu Feb 11 19:57:27 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:27 +0000 Subject: [nginx] HTTP/2: fixed reusing connections with active requests. Message-ID: details: https://hg.nginx.org/nginx/rev/0a5687a458de branches: changeset: 7769:0a5687a458de user: Maxim Dounin date: Thu Feb 11 21:52:17 2021 +0300 description: HTTP/2: fixed reusing connections with active requests. New connections are marked reusable by ngx_http_init_connection() if there are no data available for reading. As a result, if SSL is not used, ngx_http_v2_init() might be called when the connection is marked reusable. If a HEADERS frame is immediately available for reading, this resulted in connection being preserved in reusable state with an active request, and possibly closed later as if during worker shutdown (that is, after all active requests were finalized). Fix is to explicitly mark connections non-reusable in ngx_http_v2_init() instead of (incorrectly) assuming they are already non-reusable. Found by Sergey Kandaurov. diffstat: src/http/v2/ngx_http_v2.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r fc536dcdbbf7 -r 0a5687a458de src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:12 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:17 2021 +0300 @@ -326,6 +326,7 @@ ngx_http_v2_init(ngx_event_t *rev) c->write->handler = ngx_http_v2_write_handler; c->idle = 1; + ngx_reusable_connection(c, 0); ngx_http_v2_read_handler(rev); } From mdounin at mdounin.ru Thu Feb 11 19:57:30 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:30 +0000 Subject: [nginx] HTTP/2: removed SPDY directives handling. Message-ID: details: https://hg.nginx.org/nginx/rev/de0b6f1fe4e4 branches: changeset: 7770:de0b6f1fe4e4 user: Maxim Dounin date: Thu Feb 11 21:52:19 2021 +0300 description: HTTP/2: removed SPDY directives handling. The spdy_* directives are not available since introduction of HTTP/2 module in nginx 1.9.5 more than five years ago. diffstat: src/http/ngx_http_core_module.c | 8 ---- src/http/v2/ngx_http_v2_module.c | 69 ---------------------------------------- 2 files changed, 0 insertions(+), 77 deletions(-) diffs (108 lines): diff -r 0a5687a458de -r de0b6f1fe4e4 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Thu Feb 11 21:52:17 2021 +0300 +++ b/src/http/ngx_http_core_module.c Thu Feb 11 21:52:19 2021 +0300 @@ -4078,14 +4078,6 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx #endif } - if (ngx_strcmp(value[n].data, "spdy") == 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "invalid parameter \"spdy\": " - "ngx_http_spdy_module was superseded " - "by ngx_http_v2_module"); - continue; - } - if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[n].data[13], "on") == 0) { diff -r 0a5687a458de -r de0b6f1fe4e4 src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:17 2021 +0300 +++ b/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:19 2021 +0300 @@ -36,8 +36,6 @@ static char *ngx_http_v2_preread_size(ng static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); -static char *ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post = @@ -152,62 +150,6 @@ static ngx_command_t ngx_http_v2_comman 0, NULL }, - { ngx_string("spdy_recv_buffer_size"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_MAIN_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("spdy_pool_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("spdy_max_concurrent_streams"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("spdy_streams_index_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("spdy_recv_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("spdy_keepalive_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("spdy_headers_comp"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("spdy_chunk_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_http_v2_spdy_deprecated, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - ngx_null_command }; @@ -597,14 +539,3 @@ ngx_http_v2_chunk_size(ngx_conf_t *cf, v return NGX_CONF_OK; } - - -static char * -ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "invalid directive \"%V\": ngx_http_spdy_module " - "was superseded by ngx_http_v2_module", &cmd->name); - - return NGX_CONF_OK; -} From mdounin at mdounin.ru Thu Feb 11 19:57:33 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:33 +0000 Subject: [nginx] HTTP/2: removed http2_recv_timeout. Message-ID: details: https://hg.nginx.org/nginx/rev/02be1baed382 branches: changeset: 7771:02be1baed382 user: Maxim Dounin date: Thu Feb 11 21:52:20 2021 +0300 description: HTTP/2: removed http2_recv_timeout. Instead, the client_header_timeout is now used for HTTP/2 reading. Further, the timeout is changed to be set once till no further data left to read, similarly to how client_header_timeout is used in other places. diffstat: src/http/v2/ngx_http_v2.c | 23 +++++++++++++++++------ src/http/v2/ngx_http_v2_module.c | 32 +++++++++++++++++++++++++------- src/http/v2/ngx_http_v2_module.h | 1 - 3 files changed, 42 insertions(+), 14 deletions(-) diffs (133 lines): diff -r de0b6f1fe4e4 -r 02be1baed382 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:19 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:20 2021 +0300 @@ -635,9 +635,10 @@ error: static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c) { - ngx_int_t rc; - ngx_connection_t *c; - ngx_http_v2_srv_conf_t *h2scf; + ngx_int_t rc; + ngx_connection_t *c; + ngx_http_v2_srv_conf_t *h2scf; + ngx_http_core_srv_conf_t *cscf; if (h2c->last_out || h2c->processing || h2c->pushing) { return; @@ -676,10 +677,13 @@ ngx_http_v2_handle_connection(ngx_http_v ngx_reusable_connection(c, 1); - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); if (h2c->state.incomplete) { - ngx_add_timer(c->read, h2scf->recv_timeout); + if (!c->read->timer_set) { + cscf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + ngx_add_timer(c->read, cscf->client_header_timeout); + } + return; } @@ -705,6 +709,9 @@ ngx_http_v2_handle_connection(ngx_http_v ngx_del_timer(c->write); } + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + ngx_add_timer(c->read, h2scf->idle_timeout); } @@ -4696,6 +4703,10 @@ ngx_http_v2_idle_handler(ngx_event_t *re c->destroyed = 0; ngx_reusable_connection(c, 0); + if (c->read->timer_set) { + ngx_del_timer(c->read); + } + h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); if (h2c->pool == NULL) { ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR); diff -r de0b6f1fe4e4 -r 02be1baed382 src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:19 2021 +0300 +++ b/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:20 2021 +0300 @@ -36,6 +36,13 @@ static char *ngx_http_v2_preread_size(ng static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +static ngx_conf_deprecated_t ngx_http_v2_recv_timeout_deprecated = { + ngx_conf_deprecated, "http2_recv_timeout", "client_header_timeout" +}; static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post = @@ -117,10 +124,10 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_recv_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_v2_srv_conf_t, recv_timeout), - NULL }, + ngx_http_v2_obsolete, + 0, + 0, + &ngx_http_v2_recv_timeout_deprecated }, { ngx_string("http2_idle_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, @@ -304,7 +311,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * h2scf->streams_index_mask = NGX_CONF_UNSET_UINT; - h2scf->recv_timeout = NGX_CONF_UNSET_MSEC; h2scf->idle_timeout = NGX_CONF_UNSET_MSEC; return h2scf; @@ -335,8 +341,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_conf_merge_uint_value(conf->streams_index_mask, prev->streams_index_mask, 32 - 1); - ngx_conf_merge_msec_value(conf->recv_timeout, - prev->recv_timeout, 30000); ngx_conf_merge_msec_value(conf->idle_timeout, prev->idle_timeout, 180000); @@ -539,3 +543,17 @@ ngx_http_v2_chunk_size(ngx_conf_t *cf, v return NGX_CONF_OK; } + + +static char * +ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_conf_deprecated_t *d = cmd->post; + + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "the \"%s\" directive is obsolete, " + "use the \"%s\" directive instead", + d->old_name, d->new_name); + + return NGX_CONF_OK; +} diff -r de0b6f1fe4e4 -r 02be1baed382 src/http/v2/ngx_http_v2_module.h --- a/src/http/v2/ngx_http_v2_module.h Thu Feb 11 21:52:19 2021 +0300 +++ b/src/http/v2/ngx_http_v2_module.h Thu Feb 11 21:52:20 2021 +0300 @@ -29,7 +29,6 @@ typedef struct { size_t max_header_size; size_t preread_size; ngx_uint_t streams_index_mask; - ngx_msec_t recv_timeout; ngx_msec_t idle_timeout; } ngx_http_v2_srv_conf_t; From mdounin at mdounin.ru Thu Feb 11 19:57:36 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:36 +0000 Subject: [nginx] HTTP/2: removed http2_idle_timeout and http2_max_requests. Message-ID: details: https://hg.nginx.org/nginx/rev/f790816a0e87 branches: changeset: 7772:f790816a0e87 user: Maxim Dounin date: Thu Feb 11 21:52:23 2021 +0300 description: HTTP/2: removed http2_idle_timeout and http2_max_requests. Instead, keepalive_timeout and keepalive_requests are now used. This is expected to simplify HTTP/2 code and usage. This also matches directives used by upstream module for all protocols. In case of default settings, this effectively changes maximum number of requests per connection from 1000 to 100. This looks acceptable, especially given that HTTP/2 code now properly supports lingering close. Further, this changes default keepalive timeout in HTTP/2 from 300 seconds to 75 seconds. This also looks acceptable, and larger than PING interval used by Firefox (network.http.spdy.ping-threshold defaults to 58s), the only browser to use PINGs. diffstat: src/http/v2/ngx_http_v2.c | 41 ++++++++++++++++++++++++--------------- src/http/v2/ngx_http_v2_module.c | 31 +++++++++++++++-------------- src/http/v2/ngx_http_v2_module.h | 2 - 3 files changed, 41 insertions(+), 33 deletions(-) diffs (192 lines): diff -r 02be1baed382 -r f790816a0e87 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:20 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:23 2021 +0300 @@ -637,7 +637,7 @@ ngx_http_v2_handle_connection(ngx_http_v { ngx_int_t rc; ngx_connection_t *c; - ngx_http_v2_srv_conf_t *h2scf; + ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; if (h2c->last_out || h2c->processing || h2c->pushing) { @@ -709,10 +709,10 @@ ngx_http_v2_handle_connection(ngx_http_v ngx_del_timer(c->write); } - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - ngx_add_timer(c->read, h2scf->idle_timeout); + clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + + ngx_add_timer(c->read, clcf->keepalive_timeout); } @@ -1200,12 +1200,14 @@ static u_char * ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - size_t size; - ngx_uint_t padded, priority, depend, dependency, excl, weight; - ngx_uint_t status; - ngx_http_v2_node_t *node; - ngx_http_v2_stream_t *stream; - ngx_http_v2_srv_conf_t *h2scf; + size_t size; + ngx_uint_t padded, priority, depend, dependency, excl, + weight; + ngx_uint_t status; + ngx_http_v2_node_t *node; + ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; + ngx_http_core_loc_conf_t *clcf; padded = h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG; priority = h2c->state.flags & NGX_HTTP_V2_PRIORITY_FLAG; @@ -1364,7 +1366,10 @@ ngx_http_v2_state_headers(ngx_http_v2_co ngx_http_v2_set_dependency(h2c, node, depend, excl); } - if (h2c->connection->requests >= h2scf->max_requests) { + clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + + if (h2c->connection->requests >= clcf->keepalive_requests) { h2c->goaway = 1; if (ngx_http_v2_send_goaway(h2c, NGX_HTTP_V2_NO_ERROR) == NGX_ERROR) { @@ -4659,6 +4664,7 @@ ngx_http_v2_idle_handler(ngx_event_t *re ngx_connection_t *c; ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_connection_t *h2c; + ngx_http_core_loc_conf_t *clcf; c = rev->data; h2c = c->data; @@ -4690,10 +4696,10 @@ ngx_http_v2_idle_handler(ngx_event_t *re #endif - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - if (h2c->idle++ > 10 * h2scf->max_requests) { + clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + + if (h2c->idle++ > 10 * clcf->keepalive_requests) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "http2 flood detected"); ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); @@ -4707,6 +4713,9 @@ ngx_http_v2_idle_handler(ngx_event_t *re ngx_del_timer(c->read); } + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); if (h2c->pool == NULL) { ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR); diff -r 02be1baed382 -r f790816a0e87 src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:20 2021 +0300 +++ b/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:23 2021 +0300 @@ -44,6 +44,14 @@ static ngx_conf_deprecated_t ngx_http_v ngx_conf_deprecated, "http2_recv_timeout", "client_header_timeout" }; +static ngx_conf_deprecated_t ngx_http_v2_idle_timeout_deprecated = { + ngx_conf_deprecated, "http2_idle_timeout", "keepalive_timeout" +}; + +static ngx_conf_deprecated_t ngx_http_v2_max_requests_deprecated = { + ngx_conf_deprecated, "http2_max_requests", "keepalive_requests" +}; + static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post = { ngx_http_v2_recv_buffer_size }; @@ -89,10 +97,10 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_max_requests"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_v2_srv_conf_t, max_requests), - NULL }, + ngx_http_v2_obsolete, + 0, + 0, + &ngx_http_v2_max_requests_deprecated }, { ngx_string("http2_max_field_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, @@ -131,10 +139,10 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_idle_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_v2_srv_conf_t, idle_timeout), - NULL }, + ngx_http_v2_obsolete, + 0, + 0, + &ngx_http_v2_idle_timeout_deprecated }, { ngx_string("http2_chunk_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, @@ -302,7 +310,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT; - h2scf->max_requests = NGX_CONF_UNSET_UINT; h2scf->max_field_size = NGX_CONF_UNSET_SIZE; h2scf->max_header_size = NGX_CONF_UNSET_SIZE; @@ -311,8 +318,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * h2scf->streams_index_mask = NGX_CONF_UNSET_UINT; - h2scf->idle_timeout = NGX_CONF_UNSET_MSEC; - return h2scf; } @@ -329,7 +334,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c prev->concurrent_streams, 128); ngx_conf_merge_uint_value(conf->concurrent_pushes, prev->concurrent_pushes, 10); - ngx_conf_merge_uint_value(conf->max_requests, prev->max_requests, 1000); ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size, 4096); @@ -341,9 +345,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_conf_merge_uint_value(conf->streams_index_mask, prev->streams_index_mask, 32 - 1); - ngx_conf_merge_msec_value(conf->idle_timeout, - prev->idle_timeout, 180000); - return NGX_CONF_OK; } diff -r 02be1baed382 -r f790816a0e87 src/http/v2/ngx_http_v2_module.h --- a/src/http/v2/ngx_http_v2_module.h Thu Feb 11 21:52:20 2021 +0300 +++ b/src/http/v2/ngx_http_v2_module.h Thu Feb 11 21:52:23 2021 +0300 @@ -24,12 +24,10 @@ typedef struct { size_t pool_size; ngx_uint_t concurrent_streams; ngx_uint_t concurrent_pushes; - ngx_uint_t max_requests; size_t max_field_size; size_t max_header_size; size_t preread_size; ngx_uint_t streams_index_mask; - ngx_msec_t idle_timeout; } ngx_http_v2_srv_conf_t; From mdounin at mdounin.ru Thu Feb 11 19:57:39 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:39 +0000 Subject: [nginx] HTTP/2: keepalive_timeout now armed once between requests. Message-ID: details: https://hg.nginx.org/nginx/rev/b64f553b1291 branches: changeset: 7773:b64f553b1291 user: Maxim Dounin date: Thu Feb 11 21:52:24 2021 +0300 description: HTTP/2: keepalive_timeout now armed once between requests. Previously, PINGs and other frames extended possible keepalive time, making it possible to keep an open HTTP/2 connection for a long time. Now the connection is always closed as long as keepalive_timeout expires, similarly to how it happens in HTTP/1.x. Note that as a part of this change, incomplete frames are no longer trigger a separate timeout, so http2_recv_timeout (replaced by client_header_timeout in previous patches) is essentially cancelled. The client_header_timeout is, however, used for SSL handshake and while reading HEADERS frames. diffstat: src/http/v2/ngx_http_v2.c | 39 +++++++++++++++------------------------ 1 files changed, 15 insertions(+), 24 deletions(-) diffs (94 lines): diff -r f790816a0e87 -r b64f553b1291 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:23 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:24 2021 +0300 @@ -325,6 +325,10 @@ ngx_http_v2_init(ngx_event_t *rev) rev->handler = ngx_http_v2_read_handler; c->write->handler = ngx_http_v2_write_handler; + if (c->read->timer_set) { + ngx_del_timer(c->read); + } + c->idle = 1; ngx_reusable_connection(c, 0); @@ -455,14 +459,6 @@ ngx_http_v2_read_handler(ngx_event_t *re h2c->blocked = 0; - if (h2c->processing || h2c->pushing) { - if (rev->timer_set) { - ngx_del_timer(rev); - } - - return; - } - ngx_http_v2_handle_connection(h2c); } @@ -638,7 +634,6 @@ ngx_http_v2_handle_connection(ngx_http_v ngx_int_t rc; ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; - ngx_http_core_srv_conf_t *cscf; if (h2c->last_out || h2c->processing || h2c->pushing) { return; @@ -675,15 +670,16 @@ ngx_http_v2_handle_connection(ngx_http_v return; } + clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + + if (!c->read->timer_set) { + ngx_add_timer(c->read, clcf->keepalive_timeout); + } + ngx_reusable_connection(c, 1); if (h2c->state.incomplete) { - if (!c->read->timer_set) { - cscf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_core_module); - ngx_add_timer(c->read, cscf->client_header_timeout); - } - return; } @@ -708,11 +704,6 @@ ngx_http_v2_handle_connection(ngx_http_v if (c->write->timer_set) { ngx_del_timer(c->write); } - - clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, - ngx_http_core_module); - - ngx_add_timer(c->read, clcf->keepalive_timeout); } @@ -3298,6 +3289,10 @@ ngx_http_v2_create_stream(ngx_http_v2_co h2c->priority_limit += h2scf->concurrent_streams; + if (h2c->connection->read->timer_set) { + ngx_del_timer(h2c->connection->read); + } + return stream; } @@ -4709,10 +4704,6 @@ ngx_http_v2_idle_handler(ngx_event_t *re c->destroyed = 0; ngx_reusable_connection(c, 0); - if (c->read->timer_set) { - ngx_del_timer(c->read); - } - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, ngx_http_v2_module); From mdounin at mdounin.ru Thu Feb 11 19:57:41 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Feb 2021 19:57:41 +0000 Subject: [nginx] HTTP/2: removed http2_max_field_size and http2_max_header_size. Message-ID: details: https://hg.nginx.org/nginx/rev/827202ca1269 branches: changeset: 7774:827202ca1269 user: Maxim Dounin date: Thu Feb 11 21:52:26 2021 +0300 description: HTTP/2: removed http2_max_field_size and http2_max_header_size. Instead, size of one large_client_header_buffers buffer and all large client header buffers are used. diffstat: src/http/v2/ngx_http_v2.c | 29 +++++++++++++++++------------ src/http/v2/ngx_http_v2_module.c | 32 ++++++++++++++++---------------- src/http/v2/ngx_http_v2_module.h | 2 -- 3 files changed, 33 insertions(+), 30 deletions(-) diffs (149 lines): diff -r b64f553b1291 -r 827202ca1269 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:24 2021 +0300 +++ b/src/http/v2/ngx_http_v2.c Thu Feb 11 21:52:26 2021 +0300 @@ -1198,6 +1198,7 @@ ngx_http_v2_state_headers(ngx_http_v2_co ngx_http_v2_node_t *node; ngx_http_v2_stream_t *stream; ngx_http_v2_srv_conf_t *h2scf; + ngx_http_core_srv_conf_t *cscf; ngx_http_core_loc_conf_t *clcf; padded = h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG; @@ -1299,11 +1300,15 @@ ngx_http_v2_state_headers(ngx_http_v2_co return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); } + cscf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + + h2c->state.header_limit = cscf->large_client_header_buffers.size + * cscf->large_client_header_buffers.num; + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, ngx_http_v2_module); - h2c->state.header_limit = h2scf->max_header_size; - if (h2c->processing >= h2scf->concurrent_streams) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "concurrent streams exceeded %ui", h2c->processing); @@ -1485,10 +1490,10 @@ static u_char * ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - size_t alloc; - ngx_int_t len; - ngx_uint_t huff; - ngx_http_v2_srv_conf_t *h2scf; + size_t alloc; + ngx_int_t len; + ngx_uint_t huff; + ngx_http_core_srv_conf_t *cscf; if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) && h2c->state.length < NGX_HTTP_V2_INT_OCTETS) @@ -1535,12 +1540,12 @@ ngx_http_v2_state_field_len(ngx_http_v2_ "http2 %s string, len:%i", huff ? "encoded" : "raw", len); - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - if ((size_t) len > h2scf->max_field_size) { + cscf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + + if ((size_t) len > cscf->large_client_header_buffers.size) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, - "client exceeded http2_max_field_size limit"); + "client sent too large header field"); return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM); } @@ -1755,7 +1760,7 @@ ngx_http_v2_state_process_header(ngx_htt if (len > h2c->state.header_limit) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, - "client exceeded http2_max_header_size limit"); + "client sent too large header"); return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM); } diff -r b64f553b1291 -r 827202ca1269 src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:24 2021 +0300 +++ b/src/http/v2/ngx_http_v2_module.c Thu Feb 11 21:52:26 2021 +0300 @@ -52,6 +52,14 @@ static ngx_conf_deprecated_t ngx_http_v ngx_conf_deprecated, "http2_max_requests", "keepalive_requests" }; +static ngx_conf_deprecated_t ngx_http_v2_max_field_size_deprecated = { + ngx_conf_deprecated, "http2_max_field_size", "large_client_header_buffers" +}; + +static ngx_conf_deprecated_t ngx_http_v2_max_header_size_deprecated = { + ngx_conf_deprecated, "http2_max_header_size", "large_client_header_buffers" +}; + static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post = { ngx_http_v2_recv_buffer_size }; @@ -104,17 +112,17 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_max_field_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_v2_srv_conf_t, max_field_size), - NULL }, + ngx_http_v2_obsolete, + 0, + 0, + &ngx_http_v2_max_field_size_deprecated }, { ngx_string("http2_max_header_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_v2_srv_conf_t, max_header_size), - NULL }, + ngx_http_v2_obsolete, + 0, + 0, + &ngx_http_v2_max_header_size_deprecated }, { ngx_string("http2_body_preread_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, @@ -311,9 +319,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT; - h2scf->max_field_size = NGX_CONF_UNSET_SIZE; - h2scf->max_header_size = NGX_CONF_UNSET_SIZE; - h2scf->preread_size = NGX_CONF_UNSET_SIZE; h2scf->streams_index_mask = NGX_CONF_UNSET_UINT; @@ -335,11 +340,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_conf_merge_uint_value(conf->concurrent_pushes, prev->concurrent_pushes, 10); - ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size, - 4096); - ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size, - 16384); - ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536); ngx_conf_merge_uint_value(conf->streams_index_mask, diff -r b64f553b1291 -r 827202ca1269 src/http/v2/ngx_http_v2_module.h --- a/src/http/v2/ngx_http_v2_module.h Thu Feb 11 21:52:24 2021 +0300 +++ b/src/http/v2/ngx_http_v2_module.h Thu Feb 11 21:52:26 2021 +0300 @@ -24,8 +24,6 @@ typedef struct { size_t pool_size; ngx_uint_t concurrent_streams; ngx_uint_t concurrent_pushes; - size_t max_field_size; - size_t max_header_size; size_t preread_size; ngx_uint_t streams_index_mask; } ngx_http_v2_srv_conf_t; From ping.zhao at intel.com Mon Feb 15 06:08:33 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Mon, 15 Feb 2021 06:08:33 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> Message-ID: Hi Mikhail, Sorry for late. I'm on Chinese New Year holiday leave. I can't see any problem from your steps, but the result is different from mine. It's strange, I'll try when I'm back to office next week. Would you check the io_uring nginx with ldd to see if it's linked with liburing first? # ldd /path/to/nginx linux-vdso.so.1 (0x00007ffce4ff8000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f72aa689000) liburing.so.1 => /lib64/liburing.so.1 (0x00007f72aa485000) .... Or you can enable the debug log option in config to see if any 'io_uring_peek_cqe' in the log: [debug] 53391#53391: io_uring_peek_cqe: START BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Tuesday, February 9, 2021 9:31 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx 3. Limit memory to 80 Mb, for example: echo 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. For example, with 100kb files and 1 worker process: free -lh total used free shared buff/cache available Mem: 15Gi 212Mi 14Gi 13Mi 318Mi 14Gi dstat/libaio 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 dstat/io_uring 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 As you can see, libaio even faster a bit. 09.02.2021 11:36, Zhao, Ping ?????: > Hi Mikhail, > > The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. > > If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. > > memory > free -lh > total used free shared buff/cache available > Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi > > libaio: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 > 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 > 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 > 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 > 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 > 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 > 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 > 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 > > Io_uring: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 > 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 > 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 > 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 > 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 > > I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. > > Memory: > free -lh > total used free shared buff/cache available > Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi > > Libaio: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k > 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k > > Io_uring: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k > 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k > 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k > 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k > 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k > 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k > 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k > > Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Tuesday, February 9, 2021 1:17 AM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. > > I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. > > As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: > > a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. > > b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). > > I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? > > Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. > > Thanks in advance! > > 07.02.2021 05:16, Zhao, Ping ?????: >> Hi Mikhail, >> >> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >> >> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> sendfile 70MB/s 260MB/s 700MB/s >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> sendfile 250MB/s 900MB/s 1.6GB/s >> >> BR, >> Ping >> >> -----Original Message----- >> From: Zhao, Ping >> Sent: Friday, February 5, 2021 2:43 PM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Mikhail, >> >> Added 'sendfile on' & 'aio off' test result with previous table: >> >> Following is the test result with 100KB and 1MB: (4KB to be test) >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> sendfile tbt 260MB/s 700MB/s >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> sendfile tbt 900MB/s 1.6GB/s >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Mikhail Isachenkov >> Sent: Thursday, February 4, 2021 4:55 PM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> My test is much simpler than yours. I created >> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >> These files does not change during test. >> >> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >> >> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >> >> Thanks in advance! >> >> 04.02.2021 10:08, Zhao, Ping ?????: >>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>> >>> -----Original Message----- >>> From: Zhao, Ping >>> Sent: Thursday, February 4, 2021 10:33 AM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Mikhail, >>> >>> I didn't see this error in my log. Following is my OS/Kernel: >>> CentOS: 8.1.1911 >>> Kernel: 5.7.19 >>> Liburing: liburing-1.0.7-3.el8.x86_64, >>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>> >>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>> >>> My nginx reported this error before: >>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>> Which is fixed by my 2nd patch(Jan 25) already. >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Wednesday, February 3, 2021 10:11 PM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Ping Zhao, >>> >>> When I try to repeat this test, I've got a huge number of these errors: >>> >>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>> "/usr/local/html/64746" failed (11: Resource temporarily >>> unavailable) while sending response to client, client: 127.0.0.1, server: >>> localhost, >>> request: "GET /64746 HTTP/1.1", host: "localhost" >>> >>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>> >>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>> >>> 25.01.2021 11:24, Zhao, Ping ?????: >>>> Hello, add a small update to correct the length when part of request already received in previous. >>>> This case may happen when using io_uring and throughput increased. >>>> >>>> # HG changeset patch >>>> # User Ping Zhao # Date 1611566408 18000 >>>> # Mon Jan 25 04:20:08 2021 -0500 >>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>> Correct length calculation when part of request received. >>>> >>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>> @@ -531,6 +531,14 @@ >>>> >>>> size = ngx_buf_size(src); >>>> size = ngx_min(size, dst->end - dst->pos); >>>> +#if (NGX_HAVE_FILE_IOURING) >>>> + /* >>>> + * check if already received part of the request in previous, >>>> + * calculate the remain length >>>> + */ >>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>> + size = size - (dst->last - dst->pos); #endif >>>> >>>> sendfile = ctx->sendfile && !ctx->directio; >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Zhao, Ping >>>> Sent: Thursday, January 21, 2021 9:44 AM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Vladimir, >>>> >>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>> >>>> user nobody; >>>> daemon off; >>>> worker_processes 1; >>>> error_log error.log ; >>>> events { >>>> worker_connections 65535; >>>> use epoll; >>>> } >>>> >>>> http { >>>> include mime.types; >>>> default_type application/octet-stream; >>>> access_log on; >>>> aio on; >>>> sendfile off; >>>> directio 2k; >>>> >>>> # Cache Configurations >>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>> >>>> >>>> To better measure the disk io performance data, I do the following steps: >>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>> echo 2G > memory.limit_in_bytes >>>> use ' cgexec -g memory:nginx' to start Nginx. >>>> >>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>> >>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>> >>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>> extract the cache files in nvme cache disk. Use iostat to track the >>>> io data. The data should be align with NIC bw since all data should >>>> be from cache disk.(need exclude memory as cache storage impact) >>>> >>>> Following is the test result: >>>> >>>> Nginx worker_processes 1: >>>> 4k 100k 1M >>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>> >>>> >>>> Nginx worker_processes 4: >>>> 4k 100k 1M >>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>> libaio 250MB/s 900MB/s 2.0GB/s >>>> >>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>> >>>> Regards, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Vladimir Homutov >>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>> It depends on if disk io is the performance hot spot or not. If >>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB length >>>>> 1 Nginx thread it's hard to see performance difference because >>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>> performance bottle neck, both libaio and io_uring have the same >>>>> performance. If you increase request size or Nginx threads number, >>>>> for example 1MB length or Nginx thread number 4. In this case, >>>>> disk io became the performance bottle neck, you will see io_uring performance improvement. >>>> >>>> Can you please provide full test results with specific nginx configuration? >>>> >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From mikhail.isachenkov at nginx.com Mon Feb 15 08:11:34 2021 From: mikhail.isachenkov at nginx.com (Mikhail Isachenkov) Date: Mon, 15 Feb 2021 11:11:34 +0300 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> Message-ID: <853670ef-7379-42bb-15d0-68482e64de24@nginx.com> Hi Zhao Ping, First of all, happy Chinese New Year! Yes, I've checked this first. Nginx binary linked with liburing and, without 'ulimit -l unlimited', there were 'io_uring_queue_init_params() failed (12: Cannot allocate memory)' error in error.log. I believe that io_uring is working correctly. But, as I can see, numbers in last two columns of dstat output (interrupts and context switches) much larger in your case instead of mine. So, could you please re-test (following my steps) when you will return to office? Thanks in advance! 15.02.2021 09:08, Zhao, Ping ?????: > Hi Mikhail, > > Sorry for late. I'm on Chinese New Year holiday leave. I can't see any problem from your steps, but the result is different from mine. It's strange, I'll try when I'm back to office next week. Would you check the io_uring nginx with ldd to see if it's linked with liburing first? > > # ldd /path/to/nginx > linux-vdso.so.1 (0x00007ffce4ff8000) > libdl.so.2 => /lib64/libdl.so.2 (0x00007f72aa689000) > liburing.so.1 => /lib64/liburing.so.1 (0x00007f72aa485000) > .... > > Or you can enable the debug log option in config to see if any 'io_uring_peek_cqe' in the log: > > [debug] 53391#53391: io_uring_peek_cqe: START > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail Isachenkov > Sent: Tuesday, February 9, 2021 9:31 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. > > 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. > 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx 3. Limit memory to 80 Mb, for example: echo > 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes > 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... > > I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. > > For example, with 100kb files and 1 worker process: > > free -lh > total used free shared buff/cache > available > Mem: 15Gi 212Mi 14Gi 13Mi 318Mi > 14Gi > > dstat/libaio > 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 > 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 > 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 > 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 > 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 > 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 > 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 > 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 > 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 > dstat/io_uring > 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k > 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 > 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k > 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 > 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k > 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 > 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 > 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 > 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 > > As you can see, libaio even faster a bit. > > 09.02.2021 11:36, Zhao, Ping ?????: >> Hi Mikhail, >> >> The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. >> >> If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. >> >> memory >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi >> >> libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 >> 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 >> 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 >> 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 >> 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 >> 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 >> 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 >> 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 >> 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 >> 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 >> 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 >> 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 >> >> I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. >> >> Memory: >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi >> >> Libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k >> 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k >> 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k >> 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k >> 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k >> 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k >> 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k >> 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k >> >> Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. >> >> BR, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Mikhail >> Isachenkov >> Sent: Tuesday, February 9, 2021 1:17 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. >> >> I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. >> >> As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: >> >> a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. >> >> b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). >> >> I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? >> >> Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. >> >> Thanks in advance! >> >> 07.02.2021 05:16, Zhao, Ping ?????: >>> Hi Mikhail, >>> >>> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >>> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >>> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >>> >>> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile 70MB/s 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile 250MB/s 900MB/s 1.6GB/s >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: Zhao, Ping >>> Sent: Friday, February 5, 2021 2:43 PM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Mikhail, >>> >>> Added 'sendfile on' & 'aio off' test result with previous table: >>> >>> Following is the test result with 100KB and 1MB: (4KB to be test) >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile tbt 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile tbt 900MB/s 1.6GB/s >>> >>> Regards, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Thursday, February 4, 2021 4:55 PM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Zhao Ping, >>> >>> My test is much simpler than yours. I created >>> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >>> These files does not change during test. >>> >>> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >>> >>> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >>> >>> Thanks in advance! >>> >>> 04.02.2021 10:08, Zhao, Ping ?????: >>>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>>> >>>> -----Original Message----- >>>> From: Zhao, Ping >>>> Sent: Thursday, February 4, 2021 10:33 AM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Mikhail, >>>> >>>> I didn't see this error in my log. Following is my OS/Kernel: >>>> CentOS: 8.1.1911 >>>> Kernel: 5.7.19 >>>> Liburing: liburing-1.0.7-3.el8.x86_64, >>>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>>> >>>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>>> >>>> My nginx reported this error before: >>>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>>> Which is fixed by my 2nd patch(Jan 25) already. >>>> >>>> BR, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Mikhail Isachenkov >>>> Sent: Wednesday, February 3, 2021 10:11 PM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Ping Zhao, >>>> >>>> When I try to repeat this test, I've got a huge number of these errors: >>>> >>>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>>> "/usr/local/html/64746" failed (11: Resource temporarily >>>> unavailable) while sending response to client, client: 127.0.0.1, server: >>>> localhost, >>>> request: "GET /64746 HTTP/1.1", host: "localhost" >>>> >>>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>>> >>>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>>> >>>> 25.01.2021 11:24, Zhao, Ping ?????: >>>>> Hello, add a small update to correct the length when part of request already received in previous. >>>>> This case may happen when using io_uring and throughput increased. >>>>> >>>>> # HG changeset patch >>>>> # User Ping Zhao # Date 1611566408 18000 >>>>> # Mon Jan 25 04:20:08 2021 -0500 >>>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>>> Correct length calculation when part of request received. >>>>> >>>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>>> @@ -531,6 +531,14 @@ >>>>> >>>>> size = ngx_buf_size(src); >>>>> size = ngx_min(size, dst->end - dst->pos); >>>>> +#if (NGX_HAVE_FILE_IOURING) >>>>> + /* >>>>> + * check if already received part of the request in previous, >>>>> + * calculate the remain length >>>>> + */ >>>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>>> + size = size - (dst->last - dst->pos); #endif >>>>> >>>>> sendfile = ctx->sendfile && !ctx->directio; >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Zhao, Ping >>>>> Sent: Thursday, January 21, 2021 9:44 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Vladimir, >>>>> >>>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>>> >>>>> user nobody; >>>>> daemon off; >>>>> worker_processes 1; >>>>> error_log error.log ; >>>>> events { >>>>> worker_connections 65535; >>>>> use epoll; >>>>> } >>>>> >>>>> http { >>>>> include mime.types; >>>>> default_type application/octet-stream; >>>>> access_log on; >>>>> aio on; >>>>> sendfile off; >>>>> directio 2k; >>>>> >>>>> # Cache Configurations >>>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>>> >>>>> >>>>> To better measure the disk io performance data, I do the following steps: >>>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>>> echo 2G > memory.limit_in_bytes >>>>> use ' cgexec -g memory:nginx' to start Nginx. >>>>> >>>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>>> >>>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>>> >>>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>>> extract the cache files in nvme cache disk. Use iostat to track the >>>>> io data. The data should be align with NIC bw since all data should >>>>> be from cache disk.(need exclude memory as cache storage impact) >>>>> >>>>> Following is the test result: >>>>> >>>>> Nginx worker_processes 1: >>>>> 4k 100k 1M >>>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>>> >>>>> >>>>> Nginx worker_processes 4: >>>>> 4k 100k 1M >>>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>>> libaio 250MB/s 900MB/s 2.0GB/s >>>>> >>>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>>> >>>>> Regards, >>>>> Ping >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Vladimir Homutov >>>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>>> It depends on if disk io is the performance hot spot or not. If >>>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB length >>>>>> 1 Nginx thread it's hard to see performance difference because >>>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>>> performance bottle neck, both libaio and io_uring have the same >>>>>> performance. If you increase request size or Nginx threads number, >>>>>> for example 1MB length or Nginx thread number 4. In this case, >>>>>> disk io became the performance bottle neck, you will see io_uring performance improvement. >>>>> >>>>> Can you please provide full test results with specific nginx configuration? >>>>> >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> >>>> >>>> -- >>>> Best regards, >>>> Mikhail Isachenkov >>>> NGINX Professional Services >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From vadimjunk at gmail.com Mon Feb 15 11:05:40 2021 From: vadimjunk at gmail.com (Vadim Fedorenko) Date: Mon, 15 Feb 2021 11:05:40 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <853670ef-7379-42bb-15d0-68482e64de24@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> <853670ef-7379-42bb-15d0-68482e64de24@nginx.com> Message-ID: Hi! There was a regression detected in io_uring in kernel version 5.7.16 with TWA_SIGNAL handling. Looks like fix was not queued the stable branch, but could be backported to Fedora 33 kernel. It could potentially lead to some differences in metrics. Thanks, Vadim ??, 15 ????. 2021 ?., 8:11 Mikhail Isachenkov : > Hi Zhao Ping, > > First of all, happy Chinese New Year! > > Yes, I've checked this first. Nginx binary linked with liburing and, > without 'ulimit -l unlimited', there were 'io_uring_queue_init_params() > failed (12: Cannot allocate memory)' error in error.log. I believe that > io_uring is working correctly. > > But, as I can see, numbers in last two columns of dstat output > (interrupts and context switches) much larger in your case instead of > mine. So, could you please re-test (following my steps) when you will > return to office? > > Thanks in advance! > > 15.02.2021 09:08, Zhao, Ping ?????: > > Hi Mikhail, > > > > Sorry for late. I'm on Chinese New Year holiday leave. I can't see any > problem from your steps, but the result is different from mine. It's > strange, I'll try when I'm back to office next week. Would you check the > io_uring nginx with ldd to see if it's linked with liburing first? > > > > # ldd /path/to/nginx > > linux-vdso.so.1 (0x00007ffce4ff8000) > > libdl.so.2 => /lib64/libdl.so.2 (0x00007f72aa689000) > > liburing.so.1 => /lib64/liburing.so.1 (0x00007f72aa485000) > > .... > > > > Or you can enable the debug log option in config to see if any > 'io_uring_peek_cqe' in the log: > > > > [debug] 53391#53391: io_uring_peek_cqe: START > > > > BR, > > Ping > > > > -----Original Message----- > > From: nginx-devel On Behalf Of Mikhail > Isachenkov > > Sent: Tuesday, February 9, 2021 9:31 PM > > To: nginx-devel at nginx.org > > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > > > Hi Zhao Ping, > > > > Unfortunately, I still couldn't reproduce these results. Maybe you could > point me where I'm wrong? Please find my steps below and configuration/lua > script for wrk attached. > > > > 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, > 1M files. > > 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx 3. > Limit memory to 80 Mb, for example: echo > > 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes > > 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: > cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d > 30 -t 100 -c 1000 -s add_random.lua http://... > > > > I tried different values for limit_in_bytes (from 80M to 2G) and > different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the > same with libaio and io_uring. > > > > For example, with 100kb files and 1 worker process: > > > > free -lh > > total used free shared buff/cache > > available > > Mem: 15Gi 212Mi 14Gi 13Mi 318Mi > > 14Gi > > > > dstat/libaio > > 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 > > 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 > > 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 > > 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 > > 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 > > 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 > > 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 > > 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 > > 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 > > dstat/io_uring > > 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k > > 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 > > 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k > > 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 > > 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k > > 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 > > 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 > > 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 > > 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 > > > > As you can see, libaio even faster a bit. > > > > 09.02.2021 11:36, Zhao, Ping ?????: > >> Hi Mikhail, > >> > >> The performance improvement of Io_uring vs. libaio locates at disk io > interface. So it needs exclude other factors when test, such as memory > cache storage which is much faster than disk io. > >> > >> If I didn't use memory limitation, libaio and io_uring network > bandwidth is very close because both of them use memory as cache file > location, so we can't see the disk io change from it. In following data, as > example, it used 17G memory as cache, network speed is same of io_uring and > libaio, both of them has very few disk io load, which means very low > io_uring/libaio usage. > >> > >> memory > >> free -lh > >> total used free shared buff/cache > available > >> Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi > 370Gi > >> > >> libaio: > >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > >> usr sys idl wai stl| read writ| recv send| in out | int csw > >> 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 > >> 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 > >> 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 > >> 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 > >> 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 > >> 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 > >> 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 > >> 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 > >> > >> Io_uring: > >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > >> usr sys idl wai stl| read writ| recv send| in out | int csw > >> 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 > >> 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 > >> 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 > >> 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 > >> 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 > >> > >> I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G > memory, 50G network. If I limit nginx memory to 2GB, the cache memory will > be about 2.6G and won't increase during test. And disk io speed is close to > network speed which means this can shows the disk io change of libaio vs. > io_uring. This shows io_uring performance improvement. My previous data is > based on this configuration. > >> > >> Memory: > >> free -lh > >> total used free shared buff/cache > available > >> Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi > 370Gi > >> > >> Libaio: > >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > >> usr sys idl wai stl| read writ| recv send| in out | int csw > >> 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k > >> 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k > >> 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k > >> 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k > >> 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k > >> > >> Io_uring: > >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > >> usr sys idl wai stl| read writ| recv send| in out | int csw > >> 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k > >> 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k > >> 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k > >> 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k > >> 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k > >> 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k > >> 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k > >> > >> Considering that server memory won't be always enough for cache storage > when traffic increased and then Nginx will use disk as cache storage. In > this case, io_uring will shows big performance improvement than libaio on > disk io interface. This is the value of this patch. > >> > >> BR, > >> Ping > >> > >> -----Original Message----- > >> From: nginx-devel On Behalf Of Mikhail > >> Isachenkov > >> Sent: Tuesday, February 9, 2021 1:17 AM > >> To: nginx-devel at nginx.org > >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > >> > >> Hi Zhao Ping, > >> > >> First of all, thank you for pointing me to AWS patch -- on Fedora 33 > with 5.10 kernel I don't see any errors now. > >> > >> I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty > fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up > to 25 Gigabit network. > >> > >> As in previous test, I've created a number of 100kb files, but try to > reach them via proxy_cache as on your stand. After warming up disk cache, > I've got the following results: > >> > >> a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of > sendfile/libaio/io_uring. > >> > >> b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than > libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). > >> > >> I didn't use any memory limitations, but I ran 'echo 3 > > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to > 2G with cgroups, results are generally the same. Maybe 2G is not enough? > >> > >> Could you please run the test for ~60 seconds, and run 'dstat' on other > console? I'd like to check disk and network bandwidth at the same > timestamps and compare them to mine. > >> > >> Thanks in advance! > >> > >> 07.02.2021 05:16, Zhao, Ping ?????: > >>> Hi Mikhail, > >>> > >>> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried > >>> kernel 5.8.0 which doesn't has this problem. I can confirm there's a > >>> regression of aws patch(linux-aws_5.8.0-1010.10.diff) > >>> > >>> Updated 'sendfile on' & 'aio off' test result with 4KB data which is > almost same as libaio: > >>> > >>> Nginx worker_processes 1: > >>> 4k 100k 1M > >>> Io_uring 220MB/s 1GB/s 1.3GB/s > >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > >>> sendfile 70MB/s 260MB/s 700MB/s > >>> > >>> > >>> Nginx worker_processes 4: > >>> 4k 100k 1M > >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum > bw) > >>> libaio 250MB/s 900MB/s 2.0GB/s > >>> sendfile 250MB/s 900MB/s 1.6GB/s > >>> > >>> BR, > >>> Ping > >>> > >>> -----Original Message----- > >>> From: Zhao, Ping > >>> Sent: Friday, February 5, 2021 2:43 PM > >>> To: nginx-devel at nginx.org > >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > >>> > >>> Hi Mikhail, > >>> > >>> Added 'sendfile on' & 'aio off' test result with previous table: > >>> > >>> Following is the test result with 100KB and 1MB: (4KB to be test) > >>> > >>> Nginx worker_processes 1: > >>> 4k 100k 1M > >>> Io_uring 220MB/s 1GB/s 1.3GB/s > >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > >>> sendfile tbt 260MB/s 700MB/s > >>> > >>> > >>> Nginx worker_processes 4: > >>> 4k 100k 1M > >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum > bw) > >>> libaio 250MB/s 900MB/s 2.0GB/s > >>> sendfile tbt 900MB/s 1.6GB/s > >>> > >>> Regards, > >>> Ping > >>> > >>> -----Original Message----- > >>> From: nginx-devel On Behalf Of > >>> Mikhail Isachenkov > >>> Sent: Thursday, February 4, 2021 4:55 PM > >>> To: nginx-devel at nginx.org > >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > >>> > >>> Hi Zhao Ping, > >>> > >>> My test is much simpler than yours. I created > >>> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote > small lua script for wrk that adds 5 random digits to request. There are no > such errors without patch with aio enabled. > >>> These files does not change during test. > >>> > >>> I'll try to reproduce this on CentOS 8 -- which repository do you use > to install 5.x kernel? > >>> > >>> Also, could you please run the test with 'sendfile on' and 'aio off' > to get reference numbers for sendfile too? > >>> > >>> Thanks in advance! > >>> > >>> 04.02.2021 10:08, Zhao, Ping ?????: > >>>> Another possible cause is that "/usr/local/html/64746" was > changed/removed when other user tried to read it. > >>>> > >>>> -----Original Message----- > >>>> From: Zhao, Ping > >>>> Sent: Thursday, February 4, 2021 10:33 AM > >>>> To: nginx-devel at nginx.org > >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > >>>> > >>>> Hi Mikhail, > >>>> > >>>> I didn't see this error in my log. Following is my OS/Kernel: > >>>> CentOS: 8.1.1911 > >>>> Kernel: 5.7.19 > >>>> Liburing: liburing-1.0.7-3.el8.x86_64, > >>>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) > >>>> > >>>> Regarding the error: 11: Resource temporarily unavailable. It's > probably that too many read "/usr/local/html/64746" at one time which is > still locked by previous read. I tried to repro this error with single file > but it seems nginx auto store the signal file in memory and I don't see > error. How do you perform the test? I want to repro this if possible. > >>>> > >>>> My nginx reported this error before: > >>>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only > 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", > client: 11.11.11.3, server: _, request: "GET > /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080 > " > >>>> Which is fixed by my 2nd patch(Jan 25) already. > >>>> > >>>> BR, > >>>> Ping > >>>> > >>>> -----Original Message----- > >>>> From: nginx-devel On Behalf Of > >>>> Mikhail Isachenkov > >>>> Sent: Wednesday, February 3, 2021 10:11 PM > >>>> To: nginx-devel at nginx.org > >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > >>>> > >>>> Hi Ping Zhao, > >>>> > >>>> When I try to repeat this test, I've got a huge number of these > errors: > >>>> > >>>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read > >>>> "/usr/local/html/64746" failed (11: Resource temporarily > >>>> unavailable) while sending response to client, client: 127.0.0.1, > server: > >>>> localhost, > >>>> request: "GET /64746 HTTP/1.1", host: "localhost" > >>>> > >>>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) > and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. > >>>> > >>>> Did you get any errors in error log with patch applied? Which > OS/kernel did you use for testing? Did you perform any specific tuning > before running? > >>>> > >>>> 25.01.2021 11:24, Zhao, Ping ?????: > >>>>> Hello, add a small update to correct the length when part of request > already received in previous. > >>>>> This case may happen when using io_uring and throughput increased. > >>>>> > >>>>> # HG changeset patch > >>>>> # User Ping Zhao # Date 1611566408 18000 > >>>>> # Mon Jan 25 04:20:08 2021 -0500 > >>>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 > >>>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 > >>>>> Correct length calculation when part of request received. > >>>>> > >>>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c > >>>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 > >>>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 > >>>>> @@ -531,6 +531,14 @@ > >>>>> > >>>>> size = ngx_buf_size(src); > >>>>> size = ngx_min(size, dst->end - dst->pos); > >>>>> +#if (NGX_HAVE_FILE_IOURING) > >>>>> + /* > >>>>> + * check if already received part of the request in previous, > >>>>> + * calculate the remain length > >>>>> + */ > >>>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) > >>>>> + size = size - (dst->last - dst->pos); #endif > >>>>> > >>>>> sendfile = ctx->sendfile && !ctx->directio; > >>>>> > >>>>> -----Original Message----- > >>>>> From: nginx-devel On Behalf Of > >>>>> Zhao, Ping > >>>>> Sent: Thursday, January 21, 2021 9:44 AM > >>>>> To: nginx-devel at nginx.org > >>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > >>>>> > >>>>> Hi Vladimir, > >>>>> > >>>>> No special/extra configuration needed, but need check if 'aio on' > and 'sendfile off' is correctly set. This is my Nginx config for reference: > >>>>> > >>>>> user nobody; > >>>>> daemon off; > >>>>> worker_processes 1; > >>>>> error_log error.log ; > >>>>> events { > >>>>> worker_connections 65535; > >>>>> use epoll; > >>>>> } > >>>>> > >>>>> http { > >>>>> include mime.types; > >>>>> default_type application/octet-stream; > >>>>> access_log on; > >>>>> aio on; > >>>>> sendfile off; > >>>>> directio 2k; > >>>>> > >>>>> # Cache Configurations > >>>>> proxy_cache_path /mnt/cache0 levels=2 > keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; > ...... > >>>>> > >>>>> > >>>>> To better measure the disk io performance data, I do the following > steps: > >>>>> 1. To exclude other impact, and focus on disk io part.(This patch > only impact disk aio read process) Use cgroup to limit Nginx memory usage. > Otherwise Nginx may also use memory as cache storage and this may cause > test result not so straight.(since most cache hit in memory, disk io bw is > low, like my previous mail found which didn't exclude the memory cache > impact) > >>>>> echo 2G > memory.limit_in_bytes > >>>>> use ' cgexec -g memory:nginx' to start Nginx. > >>>>> > >>>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. > >>>>> My previous test used -t 200 connections, comparing with > -t 1000, libaio performance drop more when connections numbers increased > from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. > >>>>> > >>>>> 3. First clean the cache disk and run the test for 30 minutes to let > Nginx store the cache files to nvme disk as much as possible. > >>>>> > >>>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to > >>>>> extract the cache files in nvme cache disk. Use iostat to track the > >>>>> io data. The data should be align with NIC bw since all data should > >>>>> be from cache disk.(need exclude memory as cache storage impact) > >>>>> > >>>>> Following is the test result: > >>>>> > >>>>> Nginx worker_processes 1: > >>>>> 4k 100k 1M > >>>>> Io_uring 220MB/s 1GB/s 1.3GB/s > >>>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, > 1.0GB/s) > >>>>> > >>>>> > >>>>> Nginx worker_processes 4: > >>>>> 4k 100k 1M > >>>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > >>>>> libaio 250MB/s 900MB/s 2.0GB/s > >>>>> > >>>>> So for small request, io_uring has huge improvement than libaio. In > previous mail, because I didn't exclude the memory cache storage impact, > most cache file is stored in memory, very few are from disk in case of > 4k/100k. The data is not correct.(for 1M, because the cache is too big to > store in memory, it wat in disk) Also I enabled directio option "directio > 2k" this time to avoid this. > >>>>> > >>>>> Regards, > >>>>> Ping > >>>>> > >>>>> -----Original Message----- > >>>>> From: nginx-devel On Behalf Of > >>>>> Vladimir Homutov > >>>>> Sent: Wednesday, January 20, 2021 12:43 AM > >>>>> To: nginx-devel at nginx.org > >>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > >>>>> > >>>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: > >>>>>> It depends on if disk io is the performance hot spot or not. If > >>>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB length > >>>>>> 1 Nginx thread it's hard to see performance difference because > >>>>>> iostat is only around ~10MB/100MB per second. Disk io is not the > >>>>>> performance bottle neck, both libaio and io_uring have the same > >>>>>> performance. If you increase request size or Nginx threads number, > >>>>>> for example 1MB length or Nginx thread number 4. In this case, > >>>>>> disk io became the performance bottle neck, you will see io_uring > performance improvement. > >>>>> > >>>>> Can you please provide full test results with specific nginx > configuration? > >>>>> > >>>>> _______________________________________________ > >>>>> nginx-devel mailing list > >>>>> nginx-devel at nginx.org > >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >>>>> _______________________________________________ > >>>>> nginx-devel mailing list > >>>>> nginx-devel at nginx.org > >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >>>>> _______________________________________________ > >>>>> nginx-devel mailing list > >>>>> nginx-devel at nginx.org > >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >>>>> > >>>> > >>>> -- > >>>> Best regards, > >>>> Mikhail Isachenkov > >>>> NGINX Professional Services > >>>> _______________________________________________ > >>>> nginx-devel mailing list > >>>> nginx-devel at nginx.org > >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >>>> _______________________________________________ > >>>> nginx-devel mailing list > >>>> nginx-devel at nginx.org > >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >>>> > >>> > >>> -- > >>> Best regards, > >>> Mikhail Isachenkov > >>> NGINX Professional Services > >>> _______________________________________________ > >>> nginx-devel mailing list > >>> nginx-devel at nginx.org > >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >>> _______________________________________________ > >>> nginx-devel mailing list > >>> nginx-devel at nginx.org > >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >>> > >> > >> -- > >> Best regards, > >> Mikhail Isachenkov > >> NGINX Professional Services > >> _______________________________________________ > >> nginx-devel mailing list > >> nginx-devel at nginx.org > >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >> _______________________________________________ > >> nginx-devel mailing list > >> nginx-devel at nginx.org > >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > >> > > > > -- > > Best regards, > > Mikhail Isachenkov > > NGINX Professional Services > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From pluknet at nginx.com Mon Feb 15 12:05:15 2021 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 15 Feb 2021 15:05:15 +0300 Subject: nginx-quic: setting transport parameters In-Reply-To: <0CEE5C0E-2EFB-4C0C-BF69-282CAAA18D27@nginx.com> References: <0CEE5C0E-2EFB-4C0C-BF69-282CAAA18D27@nginx.com> Message-ID: > On 27 Jan 2021, at 13:16, Sergey Kandaurov wrote: > >> >> On 26 Jan 2021, at 13:26, Kyriakos Zarifis wrote: >> >> Hi, >> >> I can't seem to set a few of the quic parameters using their respective directives. >> Specifically, doing e.g. this in the conf: >> quic_max_udp_payload_size 1472; >> quic_max_ack_delay 10; >> quic_ack_delay_exponent 2; >> >> ... results in the default values being sent (as seen in qvis): >> "max_packet_size": 65527 >> "max_ack_delay": 25 >> "ack_delay_exponent": 3 >> >> Other parameters (like quic_inital_*) are being set just fine. Any idea what I might be doing wrong for these 3 above? > > These directives do not currently affect sending transport parameters. > It needs to be fixed. This was recently fixed: https://hg.nginx.org/nginx-quic/rev/75603531064a > >> p.s. I think quic_max_packet_size needs to be updated to quic_max_udp_payload_size in the README to match the latest drafts and code. > > This one has been fixed, thanks. > https://hg.nginx.org/nginx-quic/rev/27bd6dc24426 -- Sergey Kandaurov From xeioex at nginx.com Mon Feb 15 16:26:53 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 15 Feb 2021 16:26:53 +0000 Subject: [njs] Fixed Date.prototype.toISOString() with invalid date values. Message-ID: details: https://hg.nginx.org/njs/rev/6c37b561e923 branches: changeset: 1603:6c37b561e923 user: Dmitry Volyntsev date: Mon Feb 15 15:25:00 2021 +0000 description: Fixed Date.prototype.toISOString() with invalid date values. This fixes #373 issue on Github. diffstat: src/njs_date.c | 11 ++++++++++- src/test/njs_unit_test.c | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletions(-) diffs (61 lines): diff -r 374dec48b9e4 -r 6c37b561e923 src/njs_date.c --- a/src/njs_date.c Thu Feb 11 14:39:13 2021 +0000 +++ b/src/njs_date.c Mon Feb 15 15:25:00 2021 +0000 @@ -1136,6 +1136,8 @@ static njs_int_t njs_date_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t fmt) { + double time; + if (njs_slow_path(!njs_is_date(&args[0]))) { njs_type_error(vm, "cannot convert %s to date", njs_type_string(args[0].type)); @@ -1143,7 +1145,14 @@ njs_date_prototype_to_string(njs_vm_t *v return NJS_ERROR; } - return njs_date_string(vm, &vm->retval, fmt, njs_date(&args[0])->time); + time = njs_date(&args[0])->time; + + if (fmt == NJS_DATE_FMT_TO_ISO_STRING && isnan(time)) { + njs_range_error(vm, "Invalid time value"); + return NJS_ERROR; + } + + return njs_date_string(vm, &vm->retval, fmt, time); } diff -r 374dec48b9e4 -r 6c37b561e923 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Feb 11 14:39:13 2021 +0000 +++ b/src/test/njs_unit_test.c Mon Feb 15 15:25:00 2021 +0000 @@ -14431,6 +14431,9 @@ static njs_unit_test_t njs_test[] = { njs_str("var d = new Date(2011, 5, 24, 18, 45); d.toDateString()"), njs_str("Fri Jun 24 2011") }, + { njs_str("new Date(NaN).toDateString()"), + njs_str("Invalid Date") }, + { njs_str("var d = new Date(2011, 5, 24, 18, 45);" "d.toTimeString().slice(0, 17)"), njs_str("18:45:00 GMT+0000") }, @@ -14477,6 +14480,9 @@ static njs_unit_test_t njs_test[] = { njs_str("(new Date('-012345-07-01T00:00Z')).toUTCString()"), njs_str("Thu, 01 Jul -12345 00:00:00 GMT") }, + { njs_str("new Date(NaN).toUTCString()"), + njs_str("Invalid Date") }, + { njs_str("var d = new Date(-62167219200000); d.toISOString()"), njs_str("0000-01-01T00:00:00.000Z") }, @@ -14485,6 +14491,9 @@ static njs_unit_test_t njs_test[] = { njs_str("var d = new Date(-62198755200000); d.toISOString()"), njs_str("-000001-01-01T00:00:00.000Z") }, + + { njs_str("new Date(NaN).toISOString()"), + njs_str("RangeError: Invalid time value") }, #endif { njs_str("Date.UTC(2011, 5, 24, 6, 0)"), From xeioex at nginx.com Tue Feb 16 13:27:07 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 16 Feb 2021 13:27:07 +0000 Subject: [njs] Version 0.5.1. Message-ID: details: https://hg.nginx.org/njs/rev/d355071f55ef branches: changeset: 1604:d355071f55ef user: Dmitry Volyntsev date: Tue Feb 16 13:24:47 2021 +0000 description: Version 0.5.1. diffstat: CHANGES | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-) diffs (40 lines): diff -r 6c37b561e923 -r d355071f55ef CHANGES --- a/CHANGES Mon Feb 15 15:25:00 2021 +0000 +++ b/CHANGES Tue Feb 16 13:24:47 2021 +0000 @@ -1,3 +1,36 @@ + +Changes with njs 0.5.1 16 Feb 2021 + + nginx modules: + + *) Feature: introduced ngx.fetch() method implementing Fetch API. + The following init options are supported: + body, headers, buffer_size (nginx specific), + max_response_body_size (nginx specific), method. + + The following properties and methods of Response object are + implemented: arrayBuffer(), bodyUsed, json(), headers, ok, + redirect, status, statusText, text(), type, url. + + The following properties and methods of Header object are + implemented: get(), getAll(), has(). + + Notable limitations: only the http:// scheme is supported, + redirects are not handled. + + In collaboration with ??? (Hong Zhi Dao). + + *) Feature: added the "js_header_filter" directive. + + *) Bugfix: fixed processing buffered data in body filter + in stream module. + + Core: + + *) Bugfix: fixed safe mode bypass in Function constructor. + + *) Bugfix: fixed Date.prototype.toISOString() with invalid date + values. Changes with njs 0.5.0 01 Dec 2020 From xeioex at nginx.com Tue Feb 16 13:27:09 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 16 Feb 2021 13:27:09 +0000 Subject: [njs] Added tag 0.5.1 for changeset d355071f55ef Message-ID: details: https://hg.nginx.org/njs/rev/2751dd1cc9f2 branches: changeset: 1605:2751dd1cc9f2 user: Dmitry Volyntsev date: Tue Feb 16 13:25:46 2021 +0000 description: Added tag 0.5.1 for changeset d355071f55ef diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r d355071f55ef -r 2751dd1cc9f2 .hgtags --- a/.hgtags Tue Feb 16 13:24:47 2021 +0000 +++ b/.hgtags Tue Feb 16 13:25:46 2021 +0000 @@ -39,3 +39,4 @@ b409e86fd02a6f2cb3d741a41b6562471e1b66ef 1ada1061a040e5cd5ec55744bfa916dfc6744e4c 0.4.3 fdfd580b0dd617a884ed9287d98341ebef03ee9f 0.4.4 69f07c6151628880bf7d5ac28bd8287ce96d8a36 0.5.0 +d355071f55ef4612d89db0ba72e7aaeaa99deef7 0.5.1 From mdounin at mdounin.ru Tue Feb 16 16:00:42 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Feb 2021 16:00:42 +0000 Subject: [nginx] nginx-1.19.7-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/3fa6e2095a7a branches: changeset: 7775:3fa6e2095a7a user: Maxim Dounin date: Tue Feb 16 18:57:18 2021 +0300 description: nginx-1.19.7-RELEASE diffstat: docs/xml/nginx/changes.xml | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 86 insertions(+), 0 deletions(-) diffs (96 lines): diff -r 827202ca1269 -r 3fa6e2095a7a docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Thu Feb 11 21:52:26 2021 +0300 +++ b/docs/xml/nginx/changes.xml Tue Feb 16 18:57:18 2021 +0300 @@ -5,6 +5,92 @@ + + + + +????????? ?????????? ? HTTP/2 ???? ???????? +? ?????? ????? ????????????? HTTP/1.x; +????????? http2_recv_timeout, http2_idle_timeout +? http2_max_requests ??????????, +?????? ??? ??????? ???????????? ????????? +keepalive_timeout ? keepalive_requests. + + +connections handling in HTTP/2 has been changed +to better match HTTP/1.x; +the "http2_recv_timeout", "http2_idle_timeout", +and "http2_max_requests" directives have been removed, +the "keepalive_timeout" and "keepalive_requests" directives +should be used instead. + + + + + +????????? http2_max_field_size ? http2_max_header_size ??????????, +?????? ??? ??????? ???????????? ????????? large_client_header_buffers. + + +the "http2_max_field_size" and "http2_max_header_size" directives +have been removed, +the "large_client_header_buffers" directive should be used instead. + + + + + +?????? ??? ?????????? ????????? ?????????? +nginx ????????? ?? ?????? keepalive-??????????, +?? ? ?????????? ? lingering close. + + +now, if free worker connections are exhausted, +nginx starts closing not only keepalive connections, +but also connections in lingering close. + + + + + +? ????? ????? ?????????? ????????? "zero size buf in output", +???? ?????? ????????? ???????????? ????? +??? ?????????????????? ?????????????; +?????? ????????? ? 1.19.1. + + +"zero size buf in output" alerts might appear in logs +if an upstream server returned an incorrect response +during unbuffered proxying; +the bug had appeared in 1.19.1. + + + + + +??? ????????????? ????????? return +?????? ? image_filter ??? xslt_stylesheet +HEAD-??????? ?????????????? ???????????. + + +HEAD requests were handled incorrectly +if the "return" directive was used +with the "image_filter" or "xslt_stylesheet" directives. + + + + + +? ????????? add_trailer. + + +in the "add_trailer" directive. + + + + + + From mdounin at mdounin.ru Tue Feb 16 16:00:45 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Feb 2021 16:00:45 +0000 Subject: [nginx] release-1.19.7 tag Message-ID: details: https://hg.nginx.org/nginx/rev/f77ad78046dc branches: changeset: 7776:f77ad78046dc user: Maxim Dounin date: Tue Feb 16 18:57:18 2021 +0300 description: release-1.19.7 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 3fa6e2095a7a -r f77ad78046dc .hgtags --- a/.hgtags Tue Feb 16 18:57:18 2021 +0300 +++ b/.hgtags Tue Feb 16 18:57:18 2021 +0300 @@ -456,3 +456,4 @@ 3cbc2602325f0ac08917a4397d76f5155c34b7b1 dc0cc425fa63a80315f6efb68697cadb6626cdf2 release-1.19.4 8e5b068f761cd512d10c9671fbde0b568c1fd08b release-1.19.5 f618488eb769e0ed74ef0d93cd118d2ad79ef94d release-1.19.6 +3fa6e2095a7a51acc630517e1c27a7b7ac41f7b3 release-1.19.7 From Klaus.Kaisersberger at ksb.com Wed Feb 17 18:56:36 2021 From: Klaus.Kaisersberger at ksb.com (Kaisersberger, Klaus) Date: Wed, 17 Feb 2021 18:56:36 +0000 Subject: HTTP status 429 instead of 503 on throttled requests Message-ID: <734f432a2abc4fa9adfee78488b49330@defrksb0051.EMEA.KSB.intern> Hi there nginx responds with 503 for requests discarded due to throttling (https://www.nginx.com/blog/rate-limiting-nginx/). This seems to contradict https://tools.ietf.org/rfc/rfc6585.txt, that recommends 429 (Too Many Requests) instead. Should nginx be adjusted? Regards Klaus -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Wed Feb 17 19:26:49 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 17 Feb 2021 22:26:49 +0300 Subject: HTTP status 429 instead of 503 on throttled requests In-Reply-To: <734f432a2abc4fa9adfee78488b49330@defrksb0051.EMEA.KSB.intern> References: <734f432a2abc4fa9adfee78488b49330@defrksb0051.EMEA.KSB.intern> Message-ID: <20210217192649.GN77619@mdounin.ru> Hello! On Wed, Feb 17, 2021 at 06:56:36PM +0000, Kaisersberger, Klaus wrote: > Hi there > > nginx responds with 503 for requests discarded due to throttling (https://www.nginx.com/blog/rate-limiting-nginx/). > This seems to contradict https://tools.ietf.org/rfc/rfc6585.txt, that recommends 429 (Too Many Requests) instead. > > Should nginx be adjusted? There are no such plans, in particular, because it is generally a bad idea to report to an attacker that the attack was detected and being mitigated. If you think that in your particular case returning 429 is a good idea, you can adjust your configuration by using the limit_req_status directive (http://nginx.org/r/limit_req_status). -- Maxim Dounin http://mdounin.ru/ From Klaus.Kaisersberger at ksb.com Wed Feb 17 19:37:42 2021 From: Klaus.Kaisersberger at ksb.com (Kaisersberger, Klaus) Date: Wed, 17 Feb 2021 19:37:42 +0000 Subject: HTTP status 429 instead of 503 on throttled requests In-Reply-To: <20210217192649.GN77619@mdounin.ru> References: <734f432a2abc4fa9adfee78488b49330@defrksb0051.EMEA.KSB.intern> <20210217192649.GN77619@mdounin.ru> Message-ID: <59492edc5a10437ba3fc8fc7c24e40ee@defrksb0051.EMEA.KSB.intern> Hello! While I am still not sure if it is a good idea to default to not to honor the same RFCs the whole internet is basically built on, your configuration option link will perfectly help us out in our scenario. Thank you!--Klaus -----Original Message----- From: nginx-devel On Behalf Of Maxim Dounin Sent: Wednesday, February 17, 2021 8:27 PM To: nginx-devel at nginx.org Subject: Re: HTTP status 429 instead of 503 on throttled requests ++++++ !!! EXTERNAL MESSAGE: PLEASE USE CAUTION BEFORE OPENING LINKS OR ATTACHMENTS !!! ++++++ Hello! On Wed, Feb 17, 2021 at 06:56:36PM +0000, Kaisersberger, Klaus wrote: > Hi there > > nginx responds with 503 for requests discarded due to throttling (https://smex-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fwww.nginx.com%2fblog%2frate%2dlimiting%2dnginx%2f&umid=e37e541a-9aed-4fb6-94d6-f67c2e9a122b&auth=a7091ace1f2cd12c20469ba3f18a84072a5d0059-289691262c69ae7106e6fa6c2f3cf889b2deb14b). > This seems to contradict https://smex-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2ftools.ietf.org%2frfc%2frfc6585.txt&umid=e37e541a-9aed-4fb6-94d6-f67c2e9a122b&auth=a7091ace1f2cd12c20469ba3f18a84072a5d0059-5235c3e1a3c12049cfb2e2cbcf8269fef99ed341, that recommends 429 (Too Many Requests) instead. > > Should nginx be adjusted? There are no such plans, in particular, because it is generally a bad idea to report to an attacker that the attack was detected and being mitigated. If you think that in your particular case returning 429 is a good idea, you can adjust your configuration by using the limit_req_status directive (https://smex-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=http%3a%2f%2fnginx.org%2fr%2flimit%5freq%5fstatus&umid=e37e541a-9aed-4fb6-94d6-f67c2e9a122b&auth=a7091ace1f2cd12c20469ba3f18a84072a5d0059-f4eba0c1d2b86bcf8e88dc3f7ec6bc12dd385b95). -- Maxim Dounin https://smex-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=http%3a%2f%2fmdounin.ru&umid=e37e541a-9aed-4fb6-94d6-f67c2e9a122b&auth=a7091ace1f2cd12c20469ba3f18a84072a5d0059-76080fd5dbe5d1332f0ef9d013b7f4617fe7a393 _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org https://smex-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=http%3a%2f%2fmailman.nginx.org%2fmailman%2flistinfo%2fnginx%2ddevel&umid=e37e541a-9aed-4fb6-94d6-f67c2e9a122b&auth=a7091ace1f2cd12c20469ba3f18a84072a5d0059-f05a999bad8951d93c94ed23ddc8be65422e2023 From xeioex at nginx.com Fri Feb 19 12:58:19 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 19 Feb 2021 12:58:19 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/047339264048 branches: changeset: 1606:047339264048 user: Dmitry Volyntsev date: Tue Feb 16 13:32:22 2021 +0000 description: Version bump. diffstat: src/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 2751dd1cc9f2 -r 047339264048 src/njs.h --- a/src/njs.h Tue Feb 16 13:25:46 2021 +0000 +++ b/src/njs.h Tue Feb 16 13:32:22 2021 +0000 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.5.1" +#define NJS_VERSION "0.5.2" #include /* STDOUT_FILENO, STDERR_FILENO */ From xeioex at nginx.com Fri Feb 19 12:58:21 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 19 Feb 2021 12:58:21 +0000 Subject: [njs] HTTP: added js body filter. Message-ID: details: https://hg.nginx.org/njs/rev/8770e0292110 branches: changeset: 1607:8770e0292110 user: Dmitry Volyntsev date: Thu Feb 18 19:51:10 2021 +0000 description: HTTP: added js body filter. diffstat: nginx/ngx_http_js_module.c | 340 ++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 339 insertions(+), 1 deletions(-) diffs (448 lines): diff -r 047339264048 -r 8770e0292110 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Feb 16 13:32:22 2021 +0000 +++ b/nginx/ngx_http_js_module.c Thu Feb 18 19:51:10 2021 +0000 @@ -25,6 +25,8 @@ typedef struct { typedef struct { ngx_str_t content; ngx_str_t header_filter; + ngx_str_t body_filter; + ngx_uint_t buffer_type; } ngx_http_js_loc_conf_t; @@ -46,6 +48,12 @@ typedef struct { njs_opaque_value_t response_body; ngx_str_t redirect_uri; ngx_array_t promise_callbacks; + + ngx_int_t filter; + ngx_buf_t *buf; + ngx_chain_t **last_out; + ngx_chain_t *free; + ngx_chain_t *busy; } ngx_http_js_ctx_t; @@ -123,6 +131,10 @@ static njs_int_t ngx_http_js_ext_send_he njs_uint_t nargs, njs_index_t unused); static njs_int_t ngx_http_js_ext_send(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); +static njs_int_t ngx_http_js_ext_send_buffer(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused); +static njs_int_t ngx_http_js_ext_done(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused); static njs_int_t ngx_http_js_ext_finish(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); static njs_int_t ngx_http_js_ext_return(njs_vm_t *vm, njs_value_t *args, @@ -199,6 +211,8 @@ static char *ngx_http_js_import(ngx_conf static char *ngx_http_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_js_content(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_js_body_filter_set(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static void *ngx_http_js_create_main_conf(ngx_conf_t *cf); static char *ngx_http_js_init_main_conf(ngx_conf_t *cf, void *conf); static void *ngx_http_js_create_loc_conf(ngx_conf_t *cf); @@ -250,6 +264,13 @@ static ngx_command_t ngx_http_js_comman offsetof(ngx_http_js_loc_conf_t, header_filter), NULL }, + { ngx_string("js_body_filter"), + NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE12, + ngx_http_js_body_filter_set, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + ngx_null_command }; @@ -286,6 +307,7 @@ ngx_module_t ngx_http_js_module = { static ngx_http_output_header_filter_pt ngx_http_next_header_filter; +static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static njs_external_t ngx_http_js_ext_request[] = { @@ -554,6 +576,28 @@ static njs_external_t ngx_http_js_ext_r { .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("sendBuffer"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_send_buffer, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("done"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_done, + } + }, + + { + .flags = NJS_EXTERN_METHOD, .name.string = njs_str("finish"), .writable = 1, .configurable = 1, @@ -792,6 +836,138 @@ ngx_http_js_header_filter(ngx_http_reque static ngx_int_t +ngx_http_js_body_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + size_t len; + u_char *p; + ngx_int_t rc; + njs_str_t exception; + njs_int_t ret, pending; + ngx_buf_t *b; + ngx_chain_t *out, *cl; + ngx_connection_t *c; + ngx_http_js_ctx_t *ctx; + njs_opaque_value_t last_key, last; + ngx_http_js_loc_conf_t *jlcf; + njs_opaque_value_t arguments[3]; + + static const njs_str_t last_str = njs_str("last"); + + jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); + + if (jlcf->body_filter.len == 0) { + return ngx_http_next_body_filter(r, in); + } + + rc = ngx_http_js_init_vm(r); + + if (rc == NGX_ERROR || rc == NGX_DECLINED) { + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + + if (ctx->done) { + return ngx_http_next_body_filter(r, in); + } + + c = r->connection; + + ctx->filter = 1; + ctx->last_out = &out; + + njs_value_assign(&arguments[0], &ctx->request); + + njs_vm_value_string_set(ctx->vm, njs_value_arg(&last_key), + last_str.start, last_str.length); + + while (in != NULL) { + ctx->buf = in->buf; + b = ctx->buf; + + if (!ctx->done) { + len = b->last - b->pos; + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + njs_vm_memory_error(ctx->vm); + return NJS_ERROR; + } + + if (len) { + ngx_memcpy(p, b->pos, len); + } + + ret = ngx_js_prop(ctx->vm, jlcf->buffer_type, + njs_value_arg(&arguments[1]), p, len); + if (ret != NJS_OK) { + return ret; + } + + njs_value_boolean_set(njs_value_arg(&last), b->last_buf); + + ret = njs_vm_object_alloc(ctx->vm, njs_value_arg(&arguments[2]), + njs_value_arg(&last_key), + njs_value_arg(&last), NULL); + if (ret != NJS_OK) { + return ret; + } + + pending = njs_vm_pending(ctx->vm); + + rc = ngx_js_call(ctx->vm, &jlcf->body_filter, c->log, &arguments[0], + 3); + + if (rc == NGX_ERROR) { + njs_vm_retval_string(ctx->vm, &exception); + + ngx_log_error(NGX_LOG_ERR, c->log, 0, "js exception: %*s", + exception.length, exception.start); + + return NGX_ERROR; + } + + if (!pending && rc == NGX_AGAIN) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "async operation inside \"%V\" body filter", + &jlcf->body_filter); + return NGX_ERROR; + } + + ctx->buf->pos = ctx->buf->last; + + } else { + cl = ngx_alloc_chain_link(c->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + + *ctx->last_out = cl; + ctx->last_out = &cl->next; + } + + in = in->next; + } + + *ctx->last_out = NULL; + + if (out != NULL || c->buffered) { + rc = ngx_http_next_body_filter(r, out); + + ngx_chain_update_chains(c->pool, &ctx->free, &ctx->busy, &out, + (ngx_buf_tag_t) &ngx_http_js_module); + + } else { + rc = NGX_OK; + } + + return rc; +} + + +static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -1726,14 +1902,22 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v uintptr_t next; ngx_uint_t n; ngx_chain_t *out, *cl, **ll; + ngx_http_js_ctx_t *ctx; ngx_http_request_t *r; - r = njs_vm_external(vm, njs_arg(args, nargs, 0)); + r = njs_vm_external(vm, njs_argument(args, 0)); if (r == NULL) { njs_vm_error(vm, "\"this\" is not an external"); return NJS_ERROR; } + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + + if (ctx->filter) { + njs_vm_error(vm, "cannot send while in body filter"); + return NJS_ERROR; + } + out = NULL; ll = &out; @@ -1794,6 +1978,114 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v static njs_int_t +ngx_http_js_ext_send_buffer(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + unsigned last_buf, flush; + njs_str_t buffer; + ngx_buf_t *b; + ngx_chain_t *cl; + njs_value_t *flags, *value; + ngx_http_js_ctx_t *ctx; + ngx_http_request_t *r; + njs_opaque_value_t lvalue; + + static const njs_str_t last_key = njs_str("last"); + static const njs_str_t flush_key = njs_str("flush"); + + r = njs_vm_external(vm, njs_argument(args, 0)); + if (r == NULL) { + njs_vm_error(vm, "\"this\" is not an external"); + return NJS_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + + if (!ctx->filter) { + njs_vm_error(vm, "cannot send buffer while not filtering"); + return NJS_ERROR; + } + + if (ngx_js_string(vm, njs_arg(args, nargs, 1), &buffer) != NGX_OK) { + njs_vm_error(vm, "failed to get buffer arg"); + return NJS_ERROR; + } + + flush = ctx->buf->flush; + last_buf = ctx->buf->last_buf; + + flags = njs_arg(args, nargs, 2); + + if (njs_value_is_object(flags)) { + value = njs_vm_object_prop(vm, flags, &flush_key, &lvalue); + if (value != NULL) { + flush = njs_value_bool(value); + } + + value = njs_vm_object_prop(vm, flags, &last_key, &lvalue); + if (value != NULL) { + last_buf = njs_value_bool(value); + } + } + + cl = ngx_chain_get_free_buf(r->pool, &ctx->free); + if (cl == NULL) { + njs_vm_error(vm, "memory error"); + return NJS_ERROR; + } + + b = cl->buf; + + b->flush = flush; + b->last_buf = last_buf; + + b->memory = (buffer.length ? 1 : 0); + b->sync = (buffer.length ? 0 : 1); + b->tag = (ngx_buf_tag_t) &ngx_http_js_module; + + b->start = buffer.start; + b->end = buffer.start + buffer.length; + b->pos = b->start; + b->last = b->end; + + *ctx->last_out = cl; + ctx->last_out = &cl->next; + + njs_value_undefined_set(njs_vm_retval(vm)); + + return NJS_OK; +} + + +static njs_int_t +ngx_http_js_ext_done(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + ngx_http_js_ctx_t *ctx; + ngx_http_request_t *r; + + r = njs_vm_external(vm, njs_argument(args, 0)); + if (r == NULL) { + njs_vm_error(vm, "\"this\" is not an external"); + return NJS_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + + if (!ctx->filter) { + njs_vm_error(vm, "cannot set done while not filtering"); + return NJS_ERROR; + } + + ctx->done = 1; + + njs_value_undefined_set(njs_vm_retval(vm)); + + return NJS_OK; +} + + +static njs_int_t ngx_http_js_ext_finish(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { @@ -3281,6 +3573,9 @@ ngx_http_js_init(ngx_conf_t *cf) ngx_http_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_js_header_filter; + ngx_http_next_body_filter = ngx_http_top_body_filter; + ngx_http_top_body_filter = ngx_http_js_body_filter; + return NGX_OK; } @@ -3469,6 +3764,44 @@ ngx_http_js_content(ngx_conf_t *cf, ngx_ } +static char * +ngx_http_js_body_filter_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_js_loc_conf_t *jlcf = conf; + + ngx_str_t *value; + + if (jlcf->body_filter.data) { + return "is duplicate"; + } + + value = cf->args->elts; + jlcf->body_filter = value[1]; + + jlcf->buffer_type = NGX_JS_STRING; + + if (cf->args->nelts == 3 + && ngx_strncmp(value[2].data, "buffer_type=", 12) == 0) + { + if (ngx_strcmp(&value[2].data[12], "string") == 0) { + jlcf->buffer_type = NGX_JS_STRING; + + } else if (ngx_strcmp(&value[2].data[12], "buffer") == 0) { + jlcf->buffer_type = NGX_JS_BUFFER; + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid buffer_type value \"%V\", " + "it must be \"string\" or \"buffer\"", + &value[2]); + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; +} + + static void * ngx_http_js_create_main_conf(ngx_conf_t *cf) { @@ -3510,6 +3843,8 @@ ngx_http_js_create_loc_conf(ngx_conf_t * * * conf->content = { 0, NULL }; * conf->header_filter = { 0, NULL }; + * conf->body_filter = { 0, NULL }; + * conf->buffer_type = NGX_JS_UNSET; */ return conf; @@ -3524,6 +3859,9 @@ ngx_http_js_merge_loc_conf(ngx_conf_t *c ngx_conf_merge_str_value(conf->content, prev->content, ""); ngx_conf_merge_str_value(conf->header_filter, prev->header_filter, ""); + ngx_conf_merge_str_value(conf->body_filter, prev->body_filter, ""); + ngx_conf_merge_uint_value(conf->buffer_type, prev->buffer_type, + NGX_JS_STRING); return NGX_CONF_OK; } From xeioex at nginx.com Fri Feb 19 15:50:19 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 19 Feb 2021 15:50:19 +0000 Subject: [njs] Fixed property descriptor reuse for not extensible objects. Message-ID: details: https://hg.nginx.org/njs/rev/21057966d82d branches: changeset: 1608:21057966d82d user: Artem S. Povalyukhin date: Wed Feb 17 16:05:28 2021 +0300 description: Fixed property descriptor reuse for not extensible objects. This closes #375 issue on Github. diffstat: src/njs_value.c | 17 +++++++++++++---- src/test/njs_unit_test.c | 29 +++++++++++++++++------------ 2 files changed, 30 insertions(+), 16 deletions(-) diffs (111 lines): diff -r 8770e0292110 -r 21057966d82d src/njs_value.c --- a/src/njs_value.c Thu Feb 18 19:51:10 2021 +0000 +++ b/src/njs_value.c Wed Feb 17 16:05:28 2021 +0300 @@ -1250,6 +1250,10 @@ slow_path: case NJS_DECLINED: if (njs_slow_path(pq.own_whiteout != NULL)) { /* Previously deleted property. */ + if (!njs_object(value)->extensible) { + goto fail; + } + prop = pq.own_whiteout; prop->type = NJS_PROPERTY; @@ -1278,10 +1282,7 @@ slow_path: } if (njs_slow_path(!njs_object(value)->extensible)) { - njs_key_string_get(vm, &pq.key, &pq.lhq.key); - njs_type_error(vm, "Cannot add property \"%V\", " - "object is not extensible", &pq.lhq.key); - return NJS_ERROR; + goto fail; } prop = njs_object_prop_alloc(vm, &pq.key, &njs_value_undefined, 1); @@ -1304,6 +1305,14 @@ found: prop->value = *setval; return NJS_OK; + +fail: + + njs_key_string_get(vm, &pq.key, &pq.lhq.key); + njs_type_error(vm, "Cannot add property \"%V\", object is not extensible", + &pq.lhq.key); + + return NJS_ERROR; } diff -r 8770e0292110 -r 21057966d82d src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Feb 18 19:51:10 2021 +0000 +++ b/src/test/njs_unit_test.c Wed Feb 17 16:05:28 2021 +0300 @@ -14144,42 +14144,44 @@ static njs_unit_test_t njs_test[] = njs_str("false") }, { njs_str("var o = Object.defineProperties({}, {a:{}, b:{}});" - "o = Object.preventExtensions(o);" - "Object.isSealed(o)"), + "o = Object.preventExtensions(o);" + "Object.isSealed(o)"), njs_str("true") }, { njs_str("var o = Object.defineProperties({}, {a:{}, b:{writable:1}});" - "o = Object.preventExtensions(o);" - "Object.isSealed(o)"), + "o = Object.preventExtensions(o);" + "Object.isSealed(o)"), njs_str("true") }, { njs_str("var o = Object.defineProperties({}, {a:{writable:1}});" - "o = Object.preventExtensions(o);" - "Object.isSealed(o)"), + "o = Object.preventExtensions(o);" + "Object.isSealed(o)"), njs_str("true") }, { njs_str("var o = Object.defineProperties({}, {a:{configurable:1}});" - "o = Object.preventExtensions(o);" - "Object.isSealed(o)"), + "o = Object.preventExtensions(o);" + "Object.isSealed(o)"), njs_str("false") }, { njs_str("var o = Object.preventExtensions({a:1});" - "Object.isFrozen(o)"), + "Object.isFrozen(o)"), njs_str("false") }, { njs_str("var o = Object.freeze({a:1}); Object.isFrozen(o)"), njs_str("true") }, + /* Object.preventExtensions() */ + { njs_str("var o = Object.preventExtensions({a:1});" - "Object.defineProperty(o, 'b', {value:1})"), + "Object.defineProperty(o, 'b', {value:1})"), njs_str("TypeError: Cannot add property \"b\", object is not extensible") }, { njs_str("var o = Object.preventExtensions({});" - "Object.defineProperty(o, Symbol.unscopables, {})"), + "Object.defineProperty(o, Symbol.unscopables, {})"), njs_str("TypeError: Cannot add property \"Symbol(Symbol.unscopables)\", object is not extensible") }, { njs_str("var o = Object.preventExtensions({a:1});" - "Object.defineProperties(o, {b:{value:1}})"), + "Object.defineProperties(o, {b:{value:1}})"), njs_str("TypeError: Cannot add property \"b\", object is not extensible") }, { njs_str("var o = Object.preventExtensions({a:1}); o.a = 2; o.a"), @@ -14194,6 +14196,9 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = Object.preventExtensions({a:1}); o[Symbol.unscopables] = 1"), njs_str("TypeError: Cannot add property \"Symbol(Symbol.unscopables)\", object is not extensible") }, + { njs_str("var o = { a: 1 }; delete o.a; Object.preventExtensions(o).a = 1"), + njs_str("TypeError: Cannot add property \"a\", object is not extensible") }, + { njs_str("Object.preventExtensions()"), njs_str("undefined") }, From xeioex at nginx.com Fri Feb 19 17:53:41 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 19 Feb 2021 17:53:41 +0000 Subject: [njs] Fixed Object.freeze() and friends according to the specification. Message-ID: details: https://hg.nginx.org/njs/rev/4197cc28ea9c branches: changeset: 1609:4197cc28ea9c user: Artem S. Povalyukhin date: Fri Feb 19 17:27:44 2021 +0000 description: Fixed Object.freeze() and friends according to the specification. This fixes #340 and also closes #374 issues on Github. diffstat: src/njs_object.c | 163 ++++++++++++++---------------------------- src/test/njs_unit_test.c | 178 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 180 insertions(+), 161 deletions(-) diffs (477 lines): diff -r 21057966d82d -r 4197cc28ea9c src/njs_object.c --- a/src/njs_object.c Wed Feb 17 16:05:28 2021 +0300 +++ b/src/njs_object.c Fri Feb 19 17:27:44 2021 +0000 @@ -8,6 +8,12 @@ #include +typedef enum { + NJS_OBJECT_INTEGRITY_SEALED, + NJS_OBJECT_INTEGRITY_FROZEN, +} njs_object_integrity_level_t; + + static njs_int_t njs_object_hash_test(njs_lvlhsh_query_t *lhq, void *data); static njs_object_prop_t *njs_object_exist_in_proto(const njs_object_t *begin, const njs_object_t *end, njs_lvlhsh_query_t *lhq); @@ -1507,10 +1513,13 @@ njs_object_set_prototype_of(njs_vm_t *vm } +/* 7.3.15 SetIntegrityLevel */ + static njs_int_t -njs_object_freeze(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) +njs_object_set_integrity_level(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t level) { + njs_int_t ret; njs_value_t *value; njs_lvlhsh_t *hash; njs_object_t *object; @@ -1519,11 +1528,26 @@ njs_object_freeze(njs_vm_t *vm, njs_valu value = njs_arg(args, nargs, 1); - if (!njs_is_object(value)) { - njs_set_undefined(&vm->retval); + if (njs_slow_path(!njs_is_object(value))) { + vm->retval = *value; return NJS_OK; } + if (njs_slow_path(level == NJS_OBJECT_INTEGRITY_FROZEN + && njs_is_typed_array(value) + && njs_typed_array_length(njs_typed_array(value)) != 0)) + { + njs_type_error(vm, "Cannot freeze array buffer views with elements"); + return NJS_ERROR; + } + + if (njs_is_fast_array(value)) { + ret = njs_array_convert_to_slow_array(vm, njs_array(value)); + if (ret != NJS_OK) { + return ret; + } + } + object = njs_object(value); object->extensible = 0; @@ -1538,7 +1562,9 @@ njs_object_freeze(njs_vm_t *vm, njs_valu break; } - if (!njs_is_accessor_descriptor(prop)) { + if (level == NJS_OBJECT_INTEGRITY_FROZEN + && !njs_is_accessor_descriptor(prop)) + { prop->writable = 0; } @@ -1552,8 +1578,8 @@ njs_object_freeze(njs_vm_t *vm, njs_valu static njs_int_t -njs_object_is_frozen(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) +njs_object_test_integrity_level(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t level) { njs_value_t *value; njs_lvlhsh_t *hash; @@ -1564,7 +1590,7 @@ njs_object_is_frozen(njs_vm_t *vm, njs_v value = njs_arg(args, nargs, 1); - if (!njs_is_object(value)) { + if (njs_slow_path(!njs_is_object(value))) { vm->retval = njs_value_true; return NJS_OK; } @@ -1572,14 +1598,22 @@ njs_object_is_frozen(njs_vm_t *vm, njs_v retval = &njs_value_false; object = njs_object(value); - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - - hash = &object->hash; if (object->extensible) { goto done; } + if (njs_slow_path(level == NJS_OBJECT_INTEGRITY_FROZEN) + && njs_is_typed_array(value) + && njs_typed_array_length(njs_typed_array(value)) != 0) + { + goto done; + } + + njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + + hash = &object->hash; + for ( ;; ) { prop = njs_lvlhsh_each(hash, &lhe); @@ -1591,98 +1625,9 @@ njs_object_is_frozen(njs_vm_t *vm, njs_v goto done; } - if (njs_is_data_descriptor(prop) && prop->writable) { - goto done; - } - } - - retval = &njs_value_true; - -done: - - vm->retval = *retval; - - return NJS_OK; -} - - -static njs_int_t -njs_object_seal(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_value_t *value; - njs_lvlhsh_t *hash; - njs_object_t *object; - njs_object_prop_t *prop; - njs_lvlhsh_each_t lhe; - - value = njs_arg(args, nargs, 1); - - if (!njs_is_object(value)) { - vm->retval = *value; - return NJS_OK; - } - - object = njs_object(value); - object->extensible = 0; - - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - - hash = &object->hash; - - for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { - break; - } - - prop->configurable = 0; - } - - vm->retval = *value; - - return NJS_OK; -} - - -static njs_int_t -njs_object_is_sealed(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_value_t *value; - njs_lvlhsh_t *hash; - njs_object_t *object; - njs_object_prop_t *prop; - njs_lvlhsh_each_t lhe; - const njs_value_t *retval; - - value = njs_arg(args, nargs, 1); - - if (!njs_is_object(value)) { - vm->retval = njs_value_true; - return NJS_OK; - } - - retval = &njs_value_false; - - object = njs_object(value); - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - - hash = &object->hash; - - if (object->extensible) { - goto done; - } - - for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { - break; - } - - if (prop->configurable) { + if (level == NJS_OBJECT_INTEGRITY_FROZEN + && njs_is_data_descriptor(prop) && prop->writable) + { goto done; } } @@ -2055,7 +2000,8 @@ static const njs_object_prop_t njs_obje { .type = NJS_PROPERTY, .name = njs_string("freeze"), - .value = njs_native_function(njs_object_freeze, 1), + .value = njs_native_function2(njs_object_set_integrity_level, + 1, NJS_OBJECT_INTEGRITY_FROZEN), .writable = 1, .configurable = 1, }, @@ -2063,7 +2009,8 @@ static const njs_object_prop_t njs_obje { .type = NJS_PROPERTY, .name = njs_string("isFrozen"), - .value = njs_native_function(njs_object_is_frozen, 1), + .value = njs_native_function2(njs_object_test_integrity_level, + 1, NJS_OBJECT_INTEGRITY_FROZEN), .writable = 1, .configurable = 1, }, @@ -2071,7 +2018,8 @@ static const njs_object_prop_t njs_obje { .type = NJS_PROPERTY, .name = njs_string("seal"), - .value = njs_native_function(njs_object_seal, 1), + .value = njs_native_function2(njs_object_set_integrity_level, + 1, NJS_OBJECT_INTEGRITY_SEALED), .writable = 1, .configurable = 1, }, @@ -2079,7 +2027,8 @@ static const njs_object_prop_t njs_obje { .type = NJS_PROPERTY, .name = njs_string("isSealed"), - .value = njs_native_function(njs_object_is_sealed, 1), + .value = njs_native_function2(njs_object_test_integrity_level, + 1, NJS_OBJECT_INTEGRITY_SEALED), .writable = 1, .configurable = 1, }, diff -r 21057966d82d -r 4197cc28ea9c src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Feb 17 16:05:28 2021 +0300 +++ b/src/test/njs_unit_test.c Fri Feb 19 17:27:44 2021 +0000 @@ -13932,6 +13932,42 @@ static njs_unit_test_t njs_test[] = { njs_str("Object.getOwnPropertyNames(Array.isArray)"), njs_str("name,length") }, + /* Object.freeze() */ + + { njs_str("[undefined, null, false, NaN, '', Symbol()]" + ".every((x) => Object.is(Object.freeze(x), x))"), + njs_str("true") + }, + + { njs_str("var buf = new ArrayBuffer(8);" + NJS_TYPED_ARRAY_LIST + ".every((ctr) => {Object.freeze(new ctr([])); " + " Object.freeze(new ctr(buf, 8)); return true; })"), + njs_str("true") + }, + + { njs_str("var buf = new ArrayBuffer(8);" + NJS_TYPED_ARRAY_LIST + ".map((ctr) => { try { Object.freeze(new ctr(buf)); } catch(e) { return e; } })" + ".every((x) => x instanceof TypeError)"), + njs_str("true") + }, + + { njs_str("Object.freeze([1]).pop()"), + njs_str("TypeError: Cannot delete property \"0\" of array") }, + + { njs_str("var a = Object.freeze([1]); a[0] = 2;"), + njs_str("TypeError: Cannot assign to read-only property \"0\" of array") }, + + { njs_str("var a = Object.freeze([1]); a[1] = 2;"), + njs_str("TypeError: Cannot add property \"1\", object is not extensible") }, + + { njs_str("var a = Object.freeze([1,,3]); a[1] = 2;"), + njs_str("TypeError: Cannot add property \"1\", object is not extensible") }, + + { njs_str("var o = { a: 1 }; delete o.a; Object.freeze(o).a = 2;"), + njs_str("TypeError: Cannot add property \"a\", object is not extensible") }, + { njs_str("Object.defineProperty(Object.freeze({}), 'b', {})"), njs_str("TypeError: Cannot add property \"b\", object is not extensible") }, @@ -14032,30 +14068,42 @@ static njs_unit_test_t njs_test[] = "Object.getOwnPropertyDescriptor(o, 'x').writable"), njs_str("undefined") }, - { njs_str("Object.isFrozen({a:1})"), - njs_str("false") }, - - { njs_str("Object.isFrozen([1,2])"), - njs_str("false") }, - - { njs_str("Object.isFrozen(function() {})"), - njs_str("false") }, - - { njs_str("Object.isFrozen(new Date(''))"), - njs_str("false") }, - - { njs_str("Object.isFrozen(new RegExp(''))"), - njs_str("false") }, + /* Object.isFrozen() */ + + { njs_str("[undefined, null, false, NaN, '', Symbol()]" + ".every((x) => Object.isFrozen(x))"), + njs_str("true") }, + + { njs_str("[[], {}]" + ".every((x) => Object.isFrozen(Object.preventExtensions(x)))"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every((ctr) => !Object.isFrozen(new ctr([])))"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every((ctr) => Object.isFrozen(Object.preventExtensions(new ctr([]))))"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".map((ctr) => new ctr([]))" + ".map((x) => { x.broken = true; return x; })" + ".every((x) => !Object.isFrozen(Object.preventExtensions(x)))"), + njs_str("true") }, + + { njs_str("var buf = new ArrayBuffer(8);" + NJS_TYPED_ARRAY_LIST + ".every((ctr) => !Object.isFrozen(Object.preventExtensions(new ctr(buf))))"), + njs_str("true") }, + + { njs_str("[{a:1}, [1,2], function() {}, new Date(''), new RegExp('')]" + ".every((x) => !Object.isFrozen(x))"), + njs_str("true") }, { njs_str("Object.isFrozen()"), njs_str("true") }, - { njs_str("Object.isFrozen(1)"), - njs_str("true") }, - - { njs_str("Object.isFrozen('')"), - njs_str("true") }, - { njs_str("Object.isFrozen(Object.defineProperties({}, {a:{value:1}}))"), njs_str("false") }, @@ -14086,8 +14134,29 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = Object.freeze({a:1}); Object.isFrozen(o)"), njs_str("true") }, - { njs_str("Object.isFrozen(undefined)"), - njs_str("true") }, + /* Object.seal() */ + + { njs_str("[undefined, null, false, NaN, '', Symbol()]" + ".every((x) => Object.is(Object.seal(x), x))"), + njs_str("true") }, + + { njs_str("Object.seal()"), + njs_str("undefined") }, + + { njs_str("Object.seal([1]).pop()"), + njs_str("TypeError: Cannot delete property \"0\" of array") }, + + { njs_str("var a = Object.seal([1]); a[0] = 2; a"), + njs_str("2") }, + + { njs_str("var a = Object.seal([1]); a[1] = 2;"), + njs_str("TypeError: Cannot add property \"1\", object is not extensible") }, + + { njs_str("var a = Object.seal([1,,3]); a[1] = 2;"), + njs_str("TypeError: Cannot add property \"1\", object is not extensible") }, + + { njs_str("var o = { a: 1 }; delete o.a; Object.seal(o).a = 2"), + njs_str("TypeError: Cannot add property \"a\", object is not extensible") }, { njs_str("var o = Object.seal({a:1}); o.a = 2; o.a"), njs_str("2") }, @@ -14104,42 +14173,43 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = Object.seal({a:{b:1}}); o.a.b = 2; o.a.b"), njs_str("2") }, - { njs_str("Object.seal()"), - njs_str("undefined") }, - - { njs_str("Object.seal(1)"), - njs_str("1") }, - - { njs_str("Object.seal('')"), - njs_str("") }, - - { njs_str("Object.seal(undefined)"), - njs_str("undefined") }, - - { njs_str("Object.isSealed({a:1})"), - njs_str("false") }, - - { njs_str("Object.isSealed([1,2])"), - njs_str("false") }, - - { njs_str("Object.isSealed(function() {})"), - njs_str("false") }, - - { njs_str("Object.isSealed(new Date(''))"), - njs_str("false") }, - - { njs_str("Object.isSealed(new RegExp(''))"), - njs_str("false") }, + /* Object.isSealed() */ + + { njs_str("[undefined, null, false, NaN, '', Symbol()]" + ".every((x) => Object.isSealed(x))"), + njs_str("true") }, + + { njs_str("[[], {}]" + ".every((x) => Object.isSealed(Object.preventExtensions(x)))"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every((ctr) => !Object.isSealed(new ctr([])))"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every((ctr) => Object.isSealed(Object.preventExtensions(new ctr([]))))"), + njs_str("true") }, + + { njs_str("var buf = new ArrayBuffer(8);" + NJS_TYPED_ARRAY_LIST + ".every((ctr) => Object.isSealed(Object.preventExtensions(new ctr(buf))))"), + njs_str("true") }, + + { njs_str("var buf = new ArrayBuffer(8);" + NJS_TYPED_ARRAY_LIST + ".map((ctr) => new ctr(buf))" + ".map((x) => { x.broken = true; return x; })" + ".every((x) => !Object.isSealed(Object.preventExtensions(x)))"), + njs_str("true") }, + + { njs_str("[{a:1}, [1,2], function() {}, new Date(''), new RegExp('')]" + ".every((x) => !Object.isSealed(x))"), + njs_str("true") }, { njs_str("Object.isSealed()"), njs_str("true") }, - { njs_str("Object.isSealed(1)"), - njs_str("true") }, - - { njs_str("Object.isSealed('')"), - njs_str("true") }, - { njs_str("Object.isSealed(Object.defineProperties({}, {a:{value:1}}))"), njs_str("false") }, From ru at nginx.com Sat Feb 20 09:44:46 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Sat, 20 Feb 2021 09:44:46 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/5ef14498edf7 branches: changeset: 7777:5ef14498edf7 user: Ruslan Ermilov date: Sat Feb 20 12:44:07 2021 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r f77ad78046dc -r 5ef14498edf7 src/core/nginx.h --- a/src/core/nginx.h Tue Feb 16 18:57:18 2021 +0300 +++ b/src/core/nginx.h Sat Feb 20 12:44:07 2021 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1019007 -#define NGINX_VERSION "1.19.7" +#define nginx_version 1019008 +#define NGINX_VERSION "1.19.8" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From ru at nginx.com Sat Feb 20 09:44:48 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Sat, 20 Feb 2021 09:44:48 +0000 Subject: [nginx] Configure: marked top-level make targets as phony. Message-ID: details: https://hg.nginx.org/nginx/rev/549b13cd793b branches: changeset: 7778:549b13cd793b user: Ruslan Ermilov date: Sat Feb 20 12:44:26 2021 +0300 description: Configure: marked top-level make targets as phony. Reported by Thibault N?lis. diffstat: auto/init | 2 ++ auto/install | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diffs (20 lines): diff -r 5ef14498edf7 -r 549b13cd793b auto/init --- a/auto/init Sat Feb 20 12:44:07 2021 +0300 +++ b/auto/init Sat Feb 20 12:44:26 2021 +0300 @@ -48,4 +48,6 @@ default: build clean: rm -rf Makefile $NGX_OBJS + +.PHONY: default clean END diff -r 5ef14498edf7 -r 549b13cd793b auto/install --- a/auto/install Sat Feb 20 12:44:07 2021 +0300 +++ b/auto/install Sat Feb 20 12:44:26 2021 +0300 @@ -215,4 +215,6 @@ upgrade: test -f $NGX_PID_PATH.oldbin kill -QUIT \`cat $NGX_PID_PATH.oldbin\` + +.PHONY: build install modules upgrade END From ru at nginx.com Sat Feb 20 09:46:17 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Sat, 20 Feb 2021 12:46:17 +0300 Subject: [PATCH] Define phony make targets as such. In-Reply-To: <8c7fd0395e69fc54e31b6062ec2c72708a523a7d.camel@stammed.net> References: <8c7fd0395e69fc54e31b6062ec2c72708a523a7d.camel@stammed.net> Message-ID: <20210220094617.GB3649@lo0.su> http://hg.nginx.org/nginx/rev/549b13cd793b On Fri, Feb 05, 2021 at 12:48:50AM +0100, Thibault N?lis wrote: > Hello, > > I just spent more time than I care to admit troubleshooting a make > issue after naively using `./configure --builddir=build` (make target > inadvertently matches this directory name). > > Not sure if taking a dep on POSIX sed in the build system is kosher or > not, but if it is I figure this patch could save the next one some time > ;). > > Quickly tested on top of default tip as of this writing > (7765:519b55453c45). > > Best regards, > > --- a/auto/init > +++ b/auto/init > @@ -44,6 +44,8 @@ fi > ? > ?cat << END > Makefile > ? > +.PHONY: default clean > + > ?default:???????build > ? > ?clean: > --- a/auto/install > +++ b/auto/install > @@ -196,6 +196,8 @@ done > ? > ?# create Makefile > ? > +sed -i "/^\.PHONY/s/$/ build install modules upgrade/" Makefile > + > ?cat << END >> Makefile > ? > ?build: -- Ruslan Ermilov Assume stupidity not malice From mdounin at mdounin.ru Sat Feb 20 13:44:57 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 20 Feb 2021 16:44:57 +0300 Subject: [PATCH] Mail: added PROXY PROTOCOL support In-Reply-To: <4618e767b84c5b3a7712.1611070470@muradm-aln1> References: <20210118160128.GO1147@mdounin.ru> <4618e767b84c5b3a7712.1611070470@muradm-aln1> Message-ID: <20210220134457.GQ77619@mdounin.ru> Hello! On Tue, Jan 19, 2021 at 06:34:30PM +0300, muradm wrote: > # HG changeset patch > # User muradm > # Date 1611069863 -10800 > # Tue Jan 19 18:24:23 2021 +0300 > # Node ID 4618e767b84c5b3a7712466edb5bf37e3f0294ed > # Parent 83c4622053b02821a12d522d08eaff3ac27e65e3 Thanks for the patch. Overall it looks much better than previous attempts and close to what I would like to see implemented. See below for additional comments. > Mail: added PROXY PROTOCOL support. The specification spells it as "PROXY protocol" (https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt). > > This implements propxy protocol support for both upstream and downstream. > > Downstream proxy protocol support: > > mail { > server { > listen [ssl] proxy_protocol; > protocol ; Just a side notee: "[ssl]" in the examples looks unneeded. There are multiple possible parameters of the listen directive, and listing just one of them doesn't look right. On the other hand, providing full current syntax of the listen directive would be a bad idea as well. The same applies to the "protocol <...>;" directive. This directive isn't needed when configuring mail proxy servers on standard ports. If it's needed, this is something up to the user to configure. > } > } > > This will properly handle incoming connections from load balancer sending > PROXY protocol header. Without this, it is impossible to run nginx mail > proxy behind such balancer. Header reading is done with existing function > "ngx_proxy_protocol_read", so it should support both v1 and v2 headers. > This will also set "sockaddr" and "local_sockaddr" addresses from received > header, mimicing "set_realip". While "realip_module" deals with variables > etc., which is necessary for HTTP protocol, mail protocols are pretty > strict, so there is no need for flexible handling of real addresses > received. > > Upstream proxy protocol support: > > mail { > server { > listen [ssl]; > protocol ; > proxy_protocol on; > } > } > > With this, upstream server (like Postfix, Exim, Dovecot) will have PROXY > protocol header. Mentioned programs do support proxy protocol out of the > box. Header is written with existing function "ngx_proxy_protocol_write" > which supports only v1 header writing. Contents of header are written > from "sockaddr" and "local_sockaddr". These are two distinct features: reading PROXY protocol header provided by the balancer, and sending PROXY protocol to backends. As such, these should be in separate patches. In particular, this will simplify review. > > Downstream and upstream proxy protocol support: > > mail { > server { > listen [ssl] proxy_protocol; > protocol ; > proxy_protocol on; > } > } > > This will combine both receiving PROXY header and sending PROXY header. With > this, upstream server (like Postfix, Exim, Dovecot) will receive the same > header as was sent by downstream load balancer. > > Above configurations work for SSL as well and should be transparent to other > mail related configurations. > > Added upstream server "connect_timeout" which defaults to 1 second. There is no need to introduce additional timeouts here: there is already the "timeout" directive (cscf->timeout), which limits aggregate timeout for the full login process, including connect. If you think that a separate connect_timeout is needed for whatever reason, consider submitting a separate patch - with appropriate reasoning. > > Server configurations enabling proxy_protocol in listen directive, require > "set_real_ip_from" configuration. Like the following: > > mail { > # ... > server { > listen 587 proxy_protocol; > set_real_ip_from "192.168.1.1"; > set_real_ip_from "10.10.0.0/16"; > set_real_ip_from "0.0.0.0/0"; > } > } > > With enabled "proxy_protocol" and missing at least one "set_real_ip_from", > all connections will be dropped and at startup user will see in error_log: > > using PROXY protocol without set_real_ip_from \ > while reading PROXY protocol header > > When "set_real_ip_from" is provided, but remote address on physical connection > does not satisfy any address criteria, at "notice" level, in error_log, user > will see: > > UNTRUSTED PROXY protocol provider: 127.0.0.1 \ > while reading PROXY protocol header, \ > client: 127.0.0.1, server: 127.0.0.1:8143 Such behaviour, "reject connection if not matched by set_real_ip_from", looks wrong. It is not how things are handled in stream/http, so such behaviour will break POLA. It also contradicts the name of the set_real_ip_from directive: it is expected to set addreses got from the IPs in question, but not reject anything else. Further, accepting PROXY protocol header and _not_ changing the address nginx thinks the connection is from looks like a valid use case to me. For example, the address from PROXY protocol can be provided to the auth_http script, making it possible for the script to do appropriate decisions. Overall, it looks like there should be at least 3 patches here: first one to introduce "listen ... proxy_protocol" and sending appropriate information to auth_http script, second one for "set_real_ip_from", and third one for "proxy_protocol on;" in the proxy module. > > diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail.c > --- a/src/mail/ngx_mail.c Tue Jan 12 16:59:31 2021 +0300 > +++ b/src/mail/ngx_mail.c Tue Jan 19 18:24:23 2021 +0300 > @@ -402,6 +402,7 @@ > addrs[i].addr = sin->sin_addr.s_addr; > > addrs[i].conf.ctx = addr[i].opt.ctx; > + addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; > #if (NGX_MAIL_SSL) > addrs[i].conf.ssl = addr[i].opt.ssl; > #endif > @@ -436,6 +437,7 @@ > addrs6[i].addr6 = sin6->sin6_addr; > > addrs6[i].conf.ctx = addr[i].opt.ctx; > + addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; > #if (NGX_MAIL_SSL) > addrs6[i].conf.ssl = addr[i].opt.ssl; > #endif > diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail.h > --- a/src/mail/ngx_mail.h Tue Jan 12 16:59:31 2021 +0300 > +++ b/src/mail/ngx_mail.h Tue Jan 19 18:24:23 2021 +0300 > @@ -37,6 +37,7 @@ > unsigned bind:1; > unsigned wildcard:1; > unsigned ssl:1; > + unsigned proxy_protocol:1; > #if (NGX_HAVE_INET6) > unsigned ipv6only:1; > #endif It's a better idea to keep proxy_protocol similar to stream/http, after the so_keepalive. > @@ -56,6 +57,7 @@ > ngx_mail_conf_ctx_t *ctx; > ngx_str_t addr_text; > ngx_uint_t ssl; /* unsigned ssl:1; */ > + unsigned proxy_protocol:1; The "ssl" flag needs to be converted to bitfield (as specified in the comment) as long as another bitfield is added. > } ngx_mail_addr_conf_t; > > typedef struct { > @@ -125,6 +127,8 @@ > ngx_mail_conf_ctx_t *ctx; > > ngx_uint_t listen; /* unsigned listen:1; */ > + > + ngx_array_t *realip_from; /* array of ngx_cidr_t */ > } ngx_mail_core_srv_conf_t; > > It should be a good idea to put the realip_from field close to other configuration field of the mail core module, that is, somewhere before the pointer to other module configuration contexts. Alternatively, a separate module for set_real_ip_from with its own configuration might be a good idea as well. > @@ -190,6 +194,7 @@ > void **ctx; > void **main_conf; > void **srv_conf; > + ngx_mail_addr_conf_t *addr_conf; > > ngx_resolver_ctx_t *resolver_ctx; > > @@ -197,6 +202,7 @@ > > ngx_uint_t mail_state; > > + unsigned proxy_protocol:1; > unsigned protocol:3; > unsigned blocked:1; > unsigned quit:1; > diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail_core_module.c > --- a/src/mail/ngx_mail_core_module.c Tue Jan 12 16:59:31 2021 +0300 > +++ b/src/mail/ngx_mail_core_module.c Tue Jan 19 18:24:23 2021 +0300 > @@ -25,7 +25,7 @@ > void *conf); > static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, > void *conf); > - Unrelated (and wrong from the style point of view) change, two empty lines between functions and the following variable should be preserved. > +static char *ngx_mail_core_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); > > static ngx_command_t ngx_mail_core_commands[] = { > > @@ -85,6 +85,13 @@ > offsetof(ngx_mail_core_srv_conf_t, resolver_timeout), > NULL }, > > + { ngx_string("set_real_ip_from"), > + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, > + ngx_mail_core_realip_from, > + NGX_MAIL_SRV_CONF_OFFSET, > + offsetof(ngx_mail_core_srv_conf_t, realip_from), > + NULL }, > + > ngx_null_command > }; > > @@ -165,6 +172,8 @@ > > cscf->resolver = NGX_CONF_UNSET_PTR; > > + cscf->realip_from = NGX_CONF_UNSET_PTR; > + > cscf->file_name = cf->conf_file->file.name.data; > cscf->line = cf->conf_file->line; > > @@ -206,6 +215,10 @@ > > ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL); > > + ngx_conf_merge_ptr_value(conf->realip_from, > + prev->realip_from, > + NGX_CONF_UNSET_PTR); > + It is generally incorrect to preserve unset values till runtime unless strictly necessary. A better approach would be to follow how set_real_ip_from is handled in http/stream and use NULL if not set. Checking for NULL to mean "no set_real_ip_from items defined" is also more natural. > return NGX_CONF_OK; > } > > @@ -548,6 +561,11 @@ > #endif > } > > + if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { > + ls->proxy_protocol = 1; > + continue; > + } > + > ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, > "the invalid \"%V\" parameter", &value[i]); > return NGX_CONF_ERROR; > @@ -676,3 +694,104 @@ > > return NGX_CONF_OK; > } > + > +char * Style: there should be two empty lines between functions. Missing static specifier. > +ngx_mail_core_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) > +{ > + ngx_mail_core_srv_conf_t *cscf = conf; > + > + ngx_int_t rc; > + ngx_str_t *value; > + ngx_url_t u; > + ngx_cidr_t c, *cidr; > + ngx_uint_t i; > + struct sockaddr_in *sin; > +#if (NGX_HAVE_INET6) > + struct sockaddr_in6 *sin6; > +#endif > + > + value = cf->args->elts; > + > + if (cscf->realip_from == NGX_CONF_UNSET_PTR) { > + cscf->realip_from = ngx_array_create(cf->pool, 2, sizeof(ngx_cidr_t)); > + if (cscf->realip_from == NULL) { > + return NGX_CONF_ERROR; > + } > + } > + > +#if (NGX_HAVE_UNIX_DOMAIN) > + > + if (ngx_strcmp(value[1].data, "unix:") == 0) { > + cidr = ngx_array_push(cscf->realip_from); > + if (cidr == NULL) { > + return NGX_CONF_ERROR; > + } > + > + cidr->family = AF_UNIX; > + return NGX_CONF_OK; > + } > + > +#endif > + > + rc = ngx_ptocidr(&value[1], &c); > + > + if (rc != NGX_ERROR) { > + if (rc == NGX_DONE) { > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "low address bits of %V are meaningless", > + &value[1]); > + } > + > + cidr = ngx_array_push(cscf->realip_from); > + if (cidr == NULL) { > + return NGX_CONF_ERROR; > + } > + > + *cidr = c; > + > + return NGX_CONF_OK; > + } > + > + ngx_memzero(&u, sizeof(ngx_url_t)); > + u.host = value[1]; > + > + if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { > + if (u.err) { > + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, > + "%s in set_real_ip_from \"%V\"", > + u.err, &u.host); > + } > + > + return NGX_CONF_ERROR; > + } > + > + cidr = ngx_array_push_n(cscf->realip_from, u.naddrs); > + if (cidr == NULL) { > + return NGX_CONF_ERROR; > + } > + > + ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t)); > + > + for (i = 0; i < u.naddrs; i++) { > + cidr[i].family = u.addrs[i].sockaddr->sa_family; > + > + switch (cidr[i].family) { > + > +#if (NGX_HAVE_INET6) > + case AF_INET6: > + sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr; > + cidr[i].u.in6.addr = sin6->sin6_addr; > + ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16); > + break; > +#endif > + > + default: /* AF_INET */ > + sin = (struct sockaddr_in *) u.addrs[i].sockaddr; > + cidr[i].u.in.addr = sin->sin_addr.s_addr; > + cidr[i].u.in.mask = 0xffffffff; > + break; > + } > + } > + > + return NGX_CONF_OK; > +} > diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail_handler.c > --- a/src/mail/ngx_mail_handler.c Tue Jan 12 16:59:31 2021 +0300 > +++ b/src/mail/ngx_mail_handler.c Tue Jan 19 18:24:23 2021 +0300 > @@ -12,6 +12,8 @@ > > > static void ngx_mail_init_session(ngx_connection_t *c); > +static void ngx_mail_init_connection_complete(ngx_connection_t *c); > +static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev); > > #if (NGX_MAIL_SSL) > static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); > @@ -128,6 +130,7 @@ > > s->main_conf = addr_conf->ctx->main_conf; > s->srv_conf = addr_conf->ctx->srv_conf; > + s->addr_conf = addr_conf; There is no need to preserve addr_conf here, relevant flags can (notably, ssl) can be preserved by itself, similarly to how it is done in ngx_stream_init_connection(). > > s->addr_text = &addr_conf->addr_text; > > @@ -159,13 +162,181 @@ > > c->log_error = NGX_ERROR_INFO; > > + /* > + * Before all process proxy protocol > + */ > + This looks too verbose. > + if (addr_conf->proxy_protocol) { > + s->proxy_protocol = 1; The "s->proxy_protocol" flag looks meaningless, it is not used anywhere. > + c->log->action = "reading PROXY protocol header"; > + c->read->handler = ngx_mail_proxy_protocol_handler; > + > + ngx_add_timer(c->read, cscf->timeout); > + > + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { > + ngx_mail_close_connection(c); > + } > + > + return; Here the handler is not called as long as some data is already available for reading. While this is unlikely to cause problems right now in the mail module due to lack of accept filters / deferred accept support in the mail module (and iocp support being broken), this is generally wrong. A better approach is to check c->read->ready and act appropriately, much like stream module code does. > + } > + > + ngx_mail_init_connection_complete(c); > +} > + > + > +ngx_int_t > +ngx_mail_proxy_protoco_set_addrs(ngx_connection_t *c) > +{ > + ngx_addr_t addr_peer, addr_local; > + u_char *p, text[NGX_SOCKADDR_STRLEN]; > + size_t len; Style: wrong order of types, wrong amount of spaces between types and variable names. > + > + if (ngx_parse_addr(c->pool, &addr_peer, > + c->proxy_protocol->src_addr.data, > + c->proxy_protocol->src_addr.len) != NGX_OK) > + { > + return NGX_ERROR; > + } > + > + ngx_inet_set_port(addr_peer.sockaddr, c->proxy_protocol->src_port); > + > + if (ngx_parse_addr(c->pool, &addr_local, > + c->proxy_protocol->dst_addr.data, > + c->proxy_protocol->dst_addr.len) != NGX_OK) > + { > + return NGX_ERROR; > + } > + > + ngx_inet_set_port(addr_local.sockaddr, c->proxy_protocol->dst_port); > + > + len = ngx_sock_ntop(addr_peer.sockaddr, addr_peer.socklen, text, > + NGX_SOCKADDR_STRLEN, 0); > + if (len == 0) { > + return NGX_ERROR; > + } > + > + p = ngx_pnalloc(c->pool, len); > + if (p == NULL) { > + return NGX_ERROR; > + } > + > + ngx_memcpy(p, text, len); > + > + c->sockaddr = addr_peer.sockaddr; > + c->socklen = addr_peer.socklen; > + c->addr_text.len = len; > + c->addr_text.data = p; > + > + len = ngx_sock_ntop(addr_local.sockaddr, addr_local.socklen, text, > + NGX_SOCKADDR_STRLEN, 0); > + if (len == 0) { > + return NGX_ERROR; > + } > + > + p = ngx_pnalloc(c->pool, len); > + if (p == NULL) { > + return NGX_ERROR; > + } > + > + ngx_memcpy(p, text, len); > + > + c->local_sockaddr = addr_local.sockaddr; > + c->local_socklen = addr_local.socklen; Updating c->local_sockaddr looks like a bad idea even if the address comes from trusted proxy servers. We don't do this neither in stream nor in http, and I don't think that mail module is a good place to start doing this. > + > + return NGX_OK; > +} > + > + > +void > +ngx_mail_proxy_protocol_handler(ngx_event_t *rev) > +{ > + ngx_mail_core_srv_conf_t *cscf; > + ngx_mail_session_t *s; > + ngx_connection_t *c; > + u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; > + size_t size; > + ssize_t n; > + > + c = rev->data; > + s = c->data; > + > + if (rev->timedout) { > + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, > + "mail PROXY protocol header timed out"); There is no need to write such error messages as there is c->log->action to provide appropriate context. Just "client timed out" is enough. > + c->timedout = 1; > + ngx_mail_close_connection(c); > + return; > + } > + > + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, > + "mail PROXY protocol handler"); > + > + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); > + > + if (cscf->realip_from == NGX_CONF_UNSET_PTR) { > + ngx_log_error(NGX_LOG_WARN, c->log, 0, > + "using PROXY protocol without set_real_ip_from"); > + ngx_mail_close_connection(c); With the approach taken, this is clearly a configuration error. Such configurations should be reported (and rejected) during configuration parsing. Further, for configuration errors which cannot be detected during configuration parsing yet result in things like connections being dropped a better log level is NGX_LOG_ERR. The approach, however, looks wrong, see above. > + return; > + } > + > + if (ngx_cidr_match(c->sockaddr, cscf->realip_from) != NGX_OK) { > + ngx_log_error(NGX_LOG_NOTICE, c->log, 0, > + "UNTRUSTED PROXY protocol provider: %V", > + &c->addr_text); > + ngx_mail_close_connection(c); The "notice" level also looks wrong here. Client-related errors are usually logged at the "info" level. The approach, however, looks wrong, see above. > + return; > + } > + > + size = NGX_PROXY_PROTOCOL_MAX_HEADER; > + > + n = recv(c->fd, (char *) buf, size, MSG_PEEK); > + > + ngx_log_debug1(NGX_LOG_DEBUG, c->log, 0, "mail recv(): %z", n); > + > + p = ngx_proxy_protocol_read(c, buf, buf + n); This seems to lack any error checking for the "n" value returned by recv(), and will happily call ngx_proxy_protocol_read() with "last" set to "buf - 1" if recv() returns an error. Most likely this will result in a segmentation fault. > + > + if (p == NULL) { > + ngx_mail_close_connection(c); > + return; > + } > + > + ngx_log_error(NGX_LOG_NOTICE, c->log, 0, > + "PROXY protocol %V:%d => %V:%d", > + &c->proxy_protocol->src_addr, > + c->proxy_protocol->src_port, > + &c->proxy_protocol->dst_addr, > + c->proxy_protocol->dst_port); Logging level used looks wrong. At most this should be "info", much like connect / disconnect logging. Or shouldn't be at all, as this information is already logged at debug level by ngx_proxy_protocol_read(). > + > + size = p - buf; > + > + if (c->recv(c, buf, size) != (ssize_t) size) { > + ngx_mail_close_connection(c); > + return; > + } > + > + if (ngx_mail_proxy_protoco_set_addrs(c) != NGX_OK) { > + ngx_mail_close_connection(c); > + return; > + } > + > + ngx_mail_init_connection_complete(c); > +} > + > + > +void > +ngx_mail_init_connection_complete(ngx_connection_t *c) > +{ > #if (NGX_MAIL_SSL) > { > - ngx_mail_ssl_conf_t *sslcf; > + ngx_mail_session_t *s; > + ngx_mail_ssl_conf_t *sslcf; > + > + s = c->data; Style: since the code under #if is in a separate function now, additional block is not needed anymore to introduce variables; wrong number of spaces between type and variable names. > > sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); > > - if (sslcf->enable || addr_conf->ssl) { > + if (sslcf->enable || s->addr_conf->ssl) { > c->log->action = "SSL handshaking"; > > ngx_mail_ssl_init_connection(&sslcf->ssl, c); > @@ -348,6 +519,7 @@ > return; > } > > + c->log->action = "sending client greeting line"; > c->write->handler = ngx_mail_send; > > cscf->protocol->init_session(s, c); This looks like a pre-existing bug, probably should be addressed by a separate patch. > diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail_proxy_module.c > --- a/src/mail/ngx_mail_proxy_module.c Tue Jan 12 16:59:31 2021 +0300 > +++ b/src/mail/ngx_mail_proxy_module.c Tue Jan 19 18:24:23 2021 +0300 > @@ -19,6 +19,8 @@ > ngx_flag_t smtp_auth; > size_t buffer_size; > ngx_msec_t timeout; > + ngx_msec_t connect_timeout; > + ngx_flag_t proxy_protocol; > } ngx_mail_proxy_conf_t; > > > @@ -36,7 +38,9 @@ > static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf); > static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, > void *child); > - Style, see above. > +static void ngx_mail_proxy_connect_handler(ngx_event_t *ev); > +static void ngx_mail_proxy_start(ngx_mail_session_t *s); > +static void ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s); Style: order of function prototypes does not match order of functions. > > static ngx_command_t ngx_mail_proxy_commands[] = { > > @@ -61,6 +65,13 @@ > offsetof(ngx_mail_proxy_conf_t, timeout), > NULL }, > > + { ngx_string("connect_timeout"), > + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, > + ngx_conf_set_msec_slot, > + NGX_MAIL_SRV_CONF_OFFSET, > + offsetof(ngx_mail_proxy_conf_t, connect_timeout), > + NULL }, > + Not needed, see above. > { ngx_string("proxy_pass_error_message"), > NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, > ngx_conf_set_flag_slot, > @@ -82,6 +93,13 @@ > offsetof(ngx_mail_proxy_conf_t, smtp_auth), > NULL }, > > + { ngx_string("proxy_protocol"), > + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, > + ngx_conf_set_flag_slot, > + NGX_MAIL_SRV_CONF_OFFSET, > + offsetof(ngx_mail_proxy_conf_t, proxy_protocol), > + NULL }, > + > ngx_null_command > }; > > @@ -156,7 +174,6 @@ > p->upstream.connection->pool = s->connection->pool; > > s->connection->read->handler = ngx_mail_proxy_block_read; > - p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler; > > pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); > > @@ -169,23 +186,139 @@ > > s->out.len = 0; > > + if (rc == NGX_AGAIN) { > + p->upstream.connection->write->handler = ngx_mail_proxy_connect_handler; > + p->upstream.connection->read->handler = ngx_mail_proxy_connect_handler; > + > + ngx_add_timer(p->upstream.connection->write, pcf->connect_timeout); > + > + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail proxy delay connect"); Style: too long line, should be less than 80 chars. Further, the message looks misleading. There is no delay here, but rather connect is in progress. If you think that better debugging should be added to indicate the connect() status, a better approach would be to add debugging right after the ngx_event_connect_peer() call, like in the ngx_http_upstream_module: rc = ngx_event_connect_peer(&u->peer); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http upstream connect: %i", rc); Note though that this look unrelated to the change itself, and should be a separate patch. > + return; > + } > + > + if (pcf->proxy_protocol) { > + ngx_mail_proxy_send_proxy_protocol(s); > + return; > + } > + > + ngx_mail_proxy_start(s); > +} > + > + > +void > +ngx_mail_proxy_connect_handler(ngx_event_t *ev) > +{ > + ngx_connection_t *c; > + ngx_mail_session_t *s; > + ngx_mail_proxy_conf_t *pcf; Style: should be two spaces between the longest type and variable name. > + > + c = ev->data; > + s = c->data; > + > + if (ev->timedout) { > + ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "upstream timed out"); > + ngx_mail_session_internal_server_error(s); > + return; > + } > + > + ngx_del_timer(c->write); > + > + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, > + "mail proxy connect upstream"); > + > + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); > + > + if (pcf->proxy_protocol) { > + ngx_mail_proxy_send_proxy_protocol(s); > + return; > + } > + > + ngx_mail_proxy_start(s); > +} > + > + > +void > +ngx_mail_proxy_start(ngx_mail_session_t *s) > +{ > + ngx_connection_t *pc; > + > + pc = s->proxy->upstream.connection; > + > + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, > + "mail proxy starting"); > + > + pc->write->handler = ngx_mail_proxy_dummy_handler; > + > switch (s->protocol) { > > case NGX_MAIL_POP3_PROTOCOL: > - p->upstream.connection->read->handler = ngx_mail_proxy_pop3_handler; > + pc->read->handler = ngx_mail_proxy_pop3_handler; > s->mail_state = ngx_pop3_start; > break; > > case NGX_MAIL_IMAP_PROTOCOL: > - p->upstream.connection->read->handler = ngx_mail_proxy_imap_handler; > + pc->read->handler = ngx_mail_proxy_imap_handler; > s->mail_state = ngx_imap_start; > break; > > default: /* NGX_MAIL_SMTP_PROTOCOL */ > - p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler; > + pc->read->handler = ngx_mail_proxy_smtp_handler; > s->mail_state = ngx_smtp_start; > break; > } > + > + if (pc->read->ready) { > + ngx_post_event(pc->read, &ngx_posted_events); > + } > +} > + > + > +void > +ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s) > +{ > + u_char *p; > + ssize_t n, size; > + ngx_connection_t *c, *pc; > + ngx_peer_connection_t *u; > + u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; > + > + c = s->connection; > + > + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, > + "mail proxy send PROXY protocol header"); > + > + p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER); > + if (p == NULL) { > + ngx_mail_proxy_internal_server_error(s); > + return; > + } > + > + u = &s->proxy->upstream; > + > + pc = u->connection; > + > + size = p - buf; > + > + n = pc->send(pc, buf, size); > + > + if (n != size) { > + > + /* > + * PROXY protocol specification: > + * The sender must always ensure that the header > + * is sent at once, so that the transport layer > + * maintains atomicity along the path to the receiver. > + */ > + > + ngx_log_error(NGX_LOG_ERR, c->log, 0, > + "could not send PROXY protocol header at once (%z)", n); > + > + ngx_mail_proxy_internal_server_error(s); > + > + return; > + } The error handling seems to be incomplete here. While it is unlikely that things like NGX_AGAIN will be returned here, it is quite possible that c->send() will fail with an error if connection is reset by the upstream server, and this is going to result in duplicate and misleading error message. > + > + ngx_mail_proxy_start(s); > } > > > @@ -1184,6 +1317,8 @@ > pcf->smtp_auth = NGX_CONF_UNSET; > pcf->buffer_size = NGX_CONF_UNSET_SIZE; > pcf->timeout = NGX_CONF_UNSET_MSEC; > + pcf->connect_timeout = NGX_CONF_UNSET_MSEC; > + pcf->proxy_protocol = NGX_CONF_UNSET; > > return pcf; > } > @@ -1202,6 +1337,8 @@ > ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, > (size_t) ngx_pagesize); > ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); > + ngx_conf_merge_msec_value(conf->connect_timeout, prev->connect_timeout, 1000); > + ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0); > > return NGX_CONF_OK; > } Below is a patch series which tries to address most of the above comments, and also fixes several existing problems in the code found in the process. Review is appreciated. # HG changeset patch # User Maxim Dounin # Date 1613784928 -10800 # Sat Feb 20 04:35:28 2021 +0300 # Node ID 00bc617ccb86019850640db9c93ee6d8ea5f56d4 # Parent f77ad78046dcaa39ae4d4ddeeb52a63846f7d579 SSL: fixed build by Sun C with old OpenSSL versions. Sun C complains about "statement not reached" if a "return" is followed by additional statements. diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -4841,9 +4841,9 @@ ngx_http_grpc_ssl_conf_command_check(ngx { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -4876,9 +4876,9 @@ ngx_http_proxy_ssl_conf_command_check(ng { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -1274,9 +1274,9 @@ ngx_http_ssl_conf_command_check(ngx_conf { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -2398,9 +2398,9 @@ ngx_http_uwsgi_ssl_conf_command_check(ng { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; } diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -682,7 +682,7 @@ ngx_mail_ssl_conf_command_check(ngx_conf { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; } diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -1026,9 +1026,9 @@ ngx_stream_proxy_ssl_conf_command_check( { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; } diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -1061,9 +1061,9 @@ ngx_stream_ssl_conf_command_check(ngx_co { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; } # HG changeset patch # User Maxim Dounin # Date 1613784931 -10800 # Sat Feb 20 04:35:31 2021 +0300 # Node ID 63777b5cbc69027eb96ff70674d4ffa2b99aa3a4 # Parent 00bc617ccb86019850640db9c93ee6d8ea5f56d4 Events: fixed eventport handling in ngx_handle_read_event(). The "!rev->ready" test seems to be a typo, introduced in the original commit (719:f30b1a75fd3b). The ngx_handle_write_event() code properly tests for "rev->ready" instead. Due to this typo, read events might be unexpectedly removed during proxying after an event on the other part of the proxied connection. Catched by mail proxying tests. diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -318,7 +318,7 @@ ngx_handle_read_event(ngx_event_t *rev, return NGX_OK; } - if (rev->oneshot && !rev->ready) { + if (rev->oneshot && rev->ready) { if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } # HG changeset patch # User Maxim Dounin # Date 1613784935 -10800 # Sat Feb 20 04:35:35 2021 +0300 # Node ID f776e728c2527301bf2cd22ef11bee1fb982f537 # Parent 63777b5cbc69027eb96ff70674d4ffa2b99aa3a4 Mail: added missing event handling after blocking events. As long as a read event is blocked (ignored), ngx_handle_read_event() needs to be called to make sure no further notifications will be triggered when using level-triggered event methods, such as select() or poll(). diff --git a/src/mail/ngx_mail_imap_handler.c b/src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c +++ b/src/mail/ngx_mail_imap_handler.c @@ -123,6 +123,12 @@ ngx_mail_imap_auth_state(ngx_event_t *re if (s->out.len) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap send handler busy"); s->blocked = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + return; } diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -138,6 +138,12 @@ ngx_mail_pop3_auth_state(ngx_event_t *re if (s->out.len) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy"); s->blocked = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + return; } diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -449,6 +449,12 @@ ngx_mail_smtp_auth_state(ngx_event_t *re if (s->out.len) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy"); s->blocked = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + return; } # HG changeset patch # User Maxim Dounin # Date 1613787594 -10800 # Sat Feb 20 05:19:54 2021 +0300 # Node ID 0ab90ee2fd58ec5d33405333cc44049d8e5a37a7 # Parent f776e728c2527301bf2cd22ef11bee1fb982f537 Mail: added missing event handling after reading data. If we need to be notified about further events, ngx_handle_read_event() needs to be called after a read event is processed. Without this, an event can be removed from the kernel and won't be reported again, notably when using oneshot event methods, such as eventport on Solaris. For consistency, existing ngx_handle_read_event() call removed from ngx_mail_read_command(), as this call only covers of of the code paths where ngx_mail_read_command() returns NGX_AGAIN. Instead, appropriate processing added to the callers, covering all code paths where NGX_AGAIN is returned. diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -722,11 +722,6 @@ ngx_mail_read_command(ngx_mail_session_t } if (n == NGX_AGAIN) { - if (ngx_handle_read_event(c->read, 0) != NGX_OK) { - ngx_mail_session_internal_server_error(s); - return NGX_ERROR; - } - if (s->buffer->pos == s->buffer->last) { return NGX_AGAIN; } diff --git a/src/mail/ngx_mail_imap_handler.c b/src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c +++ b/src/mail/ngx_mail_imap_handler.c @@ -136,7 +136,16 @@ ngx_mail_imap_auth_state(ngx_event_t *re rc = ngx_mail_read_command(s, c); - if (rc == NGX_AGAIN || rc == NGX_ERROR) { + if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + + return; + } + + if (rc == NGX_ERROR) { return; } @@ -299,6 +308,11 @@ ngx_mail_imap_auth_state(ngx_event_t *re } } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + ngx_mail_send(c->write); } diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -151,7 +151,16 @@ ngx_mail_pop3_auth_state(ngx_event_t *re rc = ngx_mail_read_command(s, c); - if (rc == NGX_AGAIN || rc == NGX_ERROR) { + if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + + return; + } + + if (rc == NGX_ERROR) { return; } @@ -281,6 +290,11 @@ ngx_mail_pop3_auth_state(ngx_event_t *re s->arg_start = s->buffer->start; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + ngx_mail_send(c->write); } } diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -233,6 +233,11 @@ ngx_mail_proxy_pop3_handler(ngx_event_t rc = ngx_mail_proxy_read_response(s, 0); if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + return; } @@ -314,6 +319,11 @@ ngx_mail_proxy_pop3_handler(ngx_event_t return; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; } @@ -346,6 +356,11 @@ ngx_mail_proxy_imap_handler(ngx_event_t rc = ngx_mail_proxy_read_response(s, s->mail_state); if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + return; } @@ -448,6 +463,11 @@ ngx_mail_proxy_imap_handler(ngx_event_t return; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; } @@ -482,6 +502,11 @@ ngx_mail_proxy_smtp_handler(ngx_event_t rc = ngx_mail_proxy_read_response(s, s->mail_state); if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + return; } @@ -763,6 +788,11 @@ ngx_mail_proxy_smtp_handler(ngx_event_t return; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; } diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -462,7 +462,16 @@ ngx_mail_smtp_auth_state(ngx_event_t *re rc = ngx_mail_read_command(s, c); - if (rc == NGX_AGAIN || rc == NGX_ERROR) { + if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + + return; + } + + if (rc == NGX_ERROR) { return; } @@ -574,6 +583,11 @@ ngx_mail_smtp_auth_state(ngx_event_t *re s->arg_start = s->buffer->pos; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + ngx_mail_send(c->write); } } # HG changeset patch # User Maxim Dounin # Date 1613787635 -10800 # Sat Feb 20 05:20:35 2021 +0300 # Node ID 7361e60def463335d33d6406257b2f2f905d33dd # Parent 0ab90ee2fd58ec5d33405333cc44049d8e5a37a7 Mail: postponed session initialization under accept mutex. Similarly to 40e8ce405859 in the stream module, this reduces the time accept mutex is held. This also simplifies following changes to introduce PROXY protocol support. diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -197,6 +197,7 @@ typedef struct { ngx_uint_t mail_state; + unsigned ssl:1; unsigned protocol:3; unsigned blocked:1; unsigned quit:1; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -11,6 +11,7 @@ #include +static void ngx_mail_init_session_handler(ngx_event_t *rev); static void ngx_mail_init_session(ngx_connection_t *c); #if (NGX_MAIL_SSL) @@ -26,6 +27,7 @@ ngx_mail_init_connection(ngx_connection_ { size_t len; ngx_uint_t i; + ngx_event_t *rev; ngx_mail_port_t *port; struct sockaddr *sa; struct sockaddr_in *sin; @@ -129,6 +131,10 @@ ngx_mail_init_connection(ngx_connection_ s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; +#if (NGX_MAIL_SSL) + s->ssl = addr_conf->ssl; +#endif + s->addr_text = &addr_conf->addr_text; c->data = s; @@ -159,13 +165,34 @@ ngx_mail_init_connection(ngx_connection_ c->log_error = NGX_ERROR_INFO; + rev = c->read; + rev->handler = ngx_mail_init_session_handler; + + if (ngx_use_accept_mutex) { + ngx_post_event(rev, &ngx_posted_events); + return; + } + + rev->handler(rev); +} + + +static void +ngx_mail_init_session_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + + c = rev->data; + s = c->data; + #if (NGX_MAIL_SSL) { ngx_mail_ssl_conf_t *sslcf; sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - if (sslcf->enable || addr_conf->ssl) { + if (sslcf->enable || s->ssl) { c->log->action = "SSL handshaking"; ngx_mail_ssl_init_connection(&sslcf->ssl, c); # HG changeset patch # User Maxim Dounin # Date 1613787636 -10800 # Sat Feb 20 05:20:36 2021 +0300 # Node ID 698118019f618a4b746986b727189e281310d9d1 # Parent 7361e60def463335d33d6406257b2f2f905d33dd Mail: fixed log action after SSL handshake. diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -365,6 +365,8 @@ ngx_mail_init_session(ngx_connection_t * s = c->data; + c->log->action = "sending client greeting line"; + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); s->protocol = cscf->protocol->type; # HG changeset patch # User Maxim Dounin # Date 1613787637 -10800 # Sat Feb 20 05:20:37 2021 +0300 # Node ID 23008e1a0113f5bc22028473e1c914e32d503374 # Parent 698118019f618a4b746986b727189e281310d9d1 Mail: made auth http creating request easier to extend. diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -1224,22 +1224,38 @@ ngx_mail_auth_http_create_request(ngx_ma + sizeof("Client-IP: ") - 1 + s->connection->addr_text.len + sizeof(CRLF) - 1 + sizeof("Client-Host: ") - 1 + s->host.len + sizeof(CRLF) - 1 - + sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 - + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + sizeof(CRLF) - 1 - + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + sizeof(CRLF) - 1 -#if (NGX_MAIL_SSL) - + sizeof("Auth-SSL: on" CRLF) - 1 - + sizeof("Auth-SSL-Verify: ") - 1 + verify.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Subject: ") - 1 + subject.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Serial: ") - 1 + serial.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len - + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Cert: ") - 1 + cert.len + sizeof(CRLF) - 1 -#endif + ahcf->header.len + sizeof(CRLF) - 1; + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + len += sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + + sizeof(CRLF) - 1; + } + +#if (NGX_MAIL_SSL) + + if (c->ssl) { + len += sizeof("Auth-SSL: on" CRLF) - 1 + + sizeof("Auth-SSL-Verify: ") - 1 + verify.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Subject: ") - 1 + subject.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Serial: ") - 1 + serial.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Cert: ") - 1 + cert.len + + sizeof(CRLF) - 1; + } + +#endif + b = ngx_create_temp_buf(pool, len); if (b == NULL) { return NULL; # HG changeset patch # User Maxim Dounin # Date 1613793031 -10800 # Sat Feb 20 06:50:31 2021 +0300 # Node ID e7035246851a7c50ac7083f563ba754cc3ddb2f0 # Parent 23008e1a0113f5bc22028473e1c914e32d503374 Mail: parsing of the PROXY protocol from clients. Activated with the "proxy_protocol" parameter of the "listen" directive. Obtained information is passed to the auth_http script in Proxy-Protocol-Addr, Proxy-Protocol-Port, Proxy-Protocol-Server-Addr, and Proxy-Protocol-Server-Port headers. diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -405,6 +405,7 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_m #if (NGX_MAIL_SSL) addrs[i].conf.ssl = addr[i].opt.ssl; #endif + addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; addrs[i].conf.addr_text = addr[i].opt.addr_text; } @@ -439,6 +440,7 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_ #if (NGX_MAIL_SSL) addrs6[i].conf.ssl = addr[i].opt.ssl; #endif + addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; addrs6[i].conf.addr_text = addr[i].opt.addr_text; } diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -41,6 +41,7 @@ typedef struct { unsigned ipv6only:1; #endif unsigned so_keepalive:2; + unsigned proxy_protocol:1; #if (NGX_HAVE_KEEPALIVE_TUNABLE) int tcp_keepidle; int tcp_keepintvl; @@ -55,7 +56,8 @@ typedef struct { typedef struct { ngx_mail_conf_ctx_t *ctx; ngx_str_t addr_text; - ngx_uint_t ssl; /* unsigned ssl:1; */ + unsigned ssl:1; + unsigned proxy_protocol:1; } ngx_mail_addr_conf_t; typedef struct { diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -1227,6 +1227,17 @@ ngx_mail_auth_http_create_request(ngx_ma + ahcf->header.len + sizeof(CRLF) - 1; + if (c->proxy_protocol) { + len += sizeof("Proxy-Protocol-Addr: ") - 1 + + c->proxy_protocol->src_addr.len + sizeof(CRLF) - 1 + + sizeof("Proxy-Protocol-Port: ") - 1 + + sizeof("65535") - 1 + sizeof(CRLF) - 1 + + sizeof("Proxy-Protocol-Server-Addr: ") - 1 + + c->proxy_protocol->dst_addr.len + sizeof(CRLF) - 1 + + sizeof("Proxy-Protocol-Server-Port: ") - 1 + + sizeof("65535") - 1 + sizeof(CRLF) - 1; + } + if (s->auth_method == NGX_MAIL_AUTH_NONE) { len += sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 @@ -1314,6 +1325,26 @@ ngx_mail_auth_http_create_request(ngx_ma *b->last++ = CR; *b->last++ = LF; } + if (c->proxy_protocol) { + b->last = ngx_cpymem(b->last, "Proxy-Protocol-Addr: ", + sizeof("Proxy-Protocol-Addr: ") - 1); + b->last = ngx_copy(b->last, c->proxy_protocol->src_addr.data, + c->proxy_protocol->src_addr.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_sprintf(b->last, "Proxy-Protocol-Port: %d" CRLF, + c->proxy_protocol->src_port); + + b->last = ngx_cpymem(b->last, "Proxy-Protocol-Server-Addr: ", + sizeof("Proxy-Protocol-Server-Addr: ") - 1); + b->last = ngx_copy(b->last, c->proxy_protocol->dst_addr.data, + c->proxy_protocol->dst_addr.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_sprintf(b->last, "Proxy-Protocol-Server-Port: %d" CRLF, + c->proxy_protocol->dst_port); + } + if (s->auth_method == NGX_MAIL_AUTH_NONE) { /* HELO, MAIL FROM, and RCPT TO can't contain CRLF, no need to escape */ diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -548,6 +548,11 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx #endif } + if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { + ls->proxy_protocol = 1; + continue; + } + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the invalid \"%V\" parameter", &value[i]); return NGX_CONF_ERROR; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -11,6 +11,7 @@ #include +static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev); static void ngx_mail_init_session_handler(ngx_event_t *rev); static void ngx_mail_init_session(ngx_connection_t *c); @@ -168,6 +169,22 @@ ngx_mail_init_connection(ngx_connection_ rev = c->read; rev->handler = ngx_mail_init_session_handler; + if (addr_conf->proxy_protocol) { + c->log->action = "reading PROXY protocol"; + + rev->handler = ngx_mail_proxy_protocol_handler; + + if (!rev->ready) { + ngx_add_timer(rev, cscf->timeout); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + return; + } + } + if (ngx_use_accept_mutex) { ngx_post_event(rev, &ngx_posted_events); return; @@ -178,6 +195,76 @@ ngx_mail_init_connection(ngx_connection_ static void +ngx_mail_proxy_protocol_handler(ngx_event_t *rev) +{ + u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; + size_t size; + ssize_t n; + ngx_err_t err; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + + c = rev->data; + s = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail PROXY protocol handler"); + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + n = recv(c->fd, (char *) buf, sizeof(buf), MSG_PEEK); + + err = ngx_socket_errno; + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "recv(): %z", n); + + if (n == -1) { + if (err == NGX_EAGAIN) { + rev->ready = 0; + + if (!rev->timer_set) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + ngx_add_timer(rev, cscf->timeout); + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + return; + } + + ngx_connection_error(c, err, "recv() failed"); + + ngx_mail_close_connection(c); + return; + } + + p = ngx_proxy_protocol_read(c, buf, buf + n); + + if (p == NULL) { + ngx_mail_close_connection(c); + return; + } + + size = p - buf; + + if (c->recv(c, buf, size) != (ssize_t) size) { + ngx_mail_close_connection(c); + return; + } + + ngx_mail_init_session_handler(rev); +} + + +static void ngx_mail_init_session_handler(ngx_event_t *rev) { ngx_connection_t *c; @@ -242,9 +329,10 @@ ngx_mail_ssl_init_connection(ngx_ssl_t * s = c->data; - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - - ngx_add_timer(c->read, cscf->timeout); + if (!c->read->timer_set) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + ngx_add_timer(c->read, cscf->timeout); + } c->ssl->handler = ngx_mail_ssl_handshake_handler; # HG changeset patch # User Maxim Dounin # Date 1613793034 -10800 # Sat Feb 20 06:50:34 2021 +0300 # Node ID 068d1bf4f2b3faaf84ec937c091274c940b5e1ca # Parent e7035246851a7c50ac7083f563ba754cc3ddb2f0 Mail: realip module. When configured with the "set_real_ip_from", it can set client's IP address as visible in logs to the one obtained via the PROXY protocol. diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -985,6 +985,12 @@ if [ $MAIL != NO ]; then ngx_module_srcs=src/mail/ngx_mail_proxy_module.c . auto/module + + ngx_module_name=ngx_mail_realip_module + ngx_module_deps= + ngx_module_srcs=src/mail/ngx_mail_realip_module.c + + . auto/module fi diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -408,6 +408,7 @@ char *ngx_mail_capabilities(ngx_conf_t * /* STUB */ void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer); void ngx_mail_auth_http_init(ngx_mail_session_t *s); +ngx_int_t ngx_mail_realip_handler(ngx_mail_session_t *s); /**/ diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -260,6 +260,11 @@ ngx_mail_proxy_protocol_handler(ngx_even return; } + if (ngx_mail_realip_handler(s) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + ngx_mail_init_session_handler(rev); } diff --git a/src/stream/ngx_stream_realip_module.c b/src/mail/ngx_mail_realip_module.c copy from src/stream/ngx_stream_realip_module.c copy to src/mail/ngx_mail_realip_module.c --- a/src/stream/ngx_stream_realip_module.c +++ b/src/mail/ngx_mail_realip_module.c @@ -7,45 +7,29 @@ #include #include -#include +#include typedef struct { ngx_array_t *from; /* array of ngx_cidr_t */ -} ngx_stream_realip_srv_conf_t; - - -typedef struct { - struct sockaddr *sockaddr; - socklen_t socklen; - ngx_str_t addr_text; -} ngx_stream_realip_ctx_t; +} ngx_mail_realip_srv_conf_t; -static ngx_int_t ngx_stream_realip_handler(ngx_stream_session_t *s); -static ngx_int_t ngx_stream_realip_set_addr(ngx_stream_session_t *s, +static ngx_int_t ngx_mail_realip_set_addr(ngx_mail_session_t *s, ngx_addr_t *addr); -static char *ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, +static char *ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static void *ngx_stream_realip_create_srv_conf(ngx_conf_t *cf); -static char *ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, +static void *ngx_mail_realip_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); -static ngx_int_t ngx_stream_realip_add_variables(ngx_conf_t *cf); -static ngx_int_t ngx_stream_realip_init(ngx_conf_t *cf); -static ngx_int_t ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data); - - -static ngx_command_t ngx_stream_realip_commands[] = { +static ngx_command_t ngx_mail_realip_commands[] = { { ngx_string("set_real_ip_from"), - NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_stream_realip_from, - NGX_STREAM_SRV_CONF_OFFSET, + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_mail_realip_from, + NGX_MAIL_SRV_CONF_OFFSET, 0, NULL }, @@ -53,23 +37,22 @@ static ngx_command_t ngx_stream_realip_ }; -static ngx_stream_module_t ngx_stream_realip_module_ctx = { - ngx_stream_realip_add_variables, /* preconfiguration */ - ngx_stream_realip_init, /* postconfiguration */ +static ngx_mail_module_t ngx_mail_realip_module_ctx = { + NULL, /* protocol */ NULL, /* create main configuration */ NULL, /* init main configuration */ - ngx_stream_realip_create_srv_conf, /* create server configuration */ - ngx_stream_realip_merge_srv_conf /* merge server configuration */ + ngx_mail_realip_create_srv_conf, /* create server configuration */ + ngx_mail_realip_merge_srv_conf /* merge server configuration */ }; -ngx_module_t ngx_stream_realip_module = { +ngx_module_t ngx_mail_realip_module = { NGX_MODULE_V1, - &ngx_stream_realip_module_ctx, /* module context */ - ngx_stream_realip_commands, /* module directives */ - NGX_STREAM_MODULE, /* module type */ + &ngx_mail_realip_module_ctx, /* module context */ + ngx_mail_realip_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ @@ -81,70 +64,52 @@ ngx_module_t ngx_stream_realip_module = }; -static ngx_stream_variable_t ngx_stream_realip_vars[] = { - - { ngx_string("realip_remote_addr"), NULL, - ngx_stream_realip_remote_addr_variable, 0, 0, 0 }, - - { ngx_string("realip_remote_port"), NULL, - ngx_stream_realip_remote_port_variable, 0, 0, 0 }, +ngx_int_t +ngx_mail_realip_handler(ngx_mail_session_t *s) +{ + ngx_addr_t addr; + ngx_connection_t *c; + ngx_mail_realip_srv_conf_t *rscf; - ngx_stream_null_variable -}; - - -static ngx_int_t -ngx_stream_realip_handler(ngx_stream_session_t *s) -{ - ngx_addr_t addr; - ngx_connection_t *c; - ngx_stream_realip_srv_conf_t *rscf; - - rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_realip_module); + rscf = ngx_mail_get_module_srv_conf(s, ngx_mail_realip_module); if (rscf->from == NULL) { - return NGX_DECLINED; + return NGX_OK; } c = s->connection; if (c->proxy_protocol == NULL) { - return NGX_DECLINED; + return NGX_OK; } if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) { - return NGX_DECLINED; + return NGX_OK; } if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol->src_addr.data, c->proxy_protocol->src_addr.len) != NGX_OK) { - return NGX_DECLINED; + return NGX_OK; } ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port); - return ngx_stream_realip_set_addr(s, &addr); + return ngx_mail_realip_set_addr(s, &addr); } static ngx_int_t -ngx_stream_realip_set_addr(ngx_stream_session_t *s, ngx_addr_t *addr) +ngx_mail_realip_set_addr(ngx_mail_session_t *s, ngx_addr_t *addr) { - size_t len; - u_char *p; - u_char text[NGX_SOCKADDR_STRLEN]; - ngx_connection_t *c; - ngx_stream_realip_ctx_t *ctx; + size_t len; + u_char *p; + u_char text[NGX_SOCKADDR_STRLEN]; + ngx_connection_t *c; c = s->connection; - ctx = ngx_palloc(c->pool, sizeof(ngx_stream_realip_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text, NGX_SOCKADDR_STRLEN, 0); if (len == 0) { @@ -158,25 +123,19 @@ ngx_stream_realip_set_addr(ngx_stream_se ngx_memcpy(p, text, len); - ngx_stream_set_ctx(s, ctx, ngx_stream_realip_module); - - ctx->sockaddr = c->sockaddr; - ctx->socklen = c->socklen; - ctx->addr_text = c->addr_text; - c->sockaddr = addr->sockaddr; c->socklen = addr->socklen; c->addr_text.len = len; c->addr_text.data = p; - return NGX_DECLINED; + return NGX_OK; } static char * -ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_stream_realip_srv_conf_t *rscf = conf; + ngx_mail_realip_srv_conf_t *rscf = conf; ngx_int_t rc; ngx_str_t *value; @@ -277,11 +236,11 @@ ngx_stream_realip_from(ngx_conf_t *cf, n static void * -ngx_stream_realip_create_srv_conf(ngx_conf_t *cf) +ngx_mail_realip_create_srv_conf(ngx_conf_t *cf) { - ngx_stream_realip_srv_conf_t *conf; + ngx_mail_realip_srv_conf_t *conf; - conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_realip_srv_conf_t)); + conf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_realip_srv_conf_t)); if (conf == NULL) { return NULL; } @@ -297,10 +256,10 @@ ngx_stream_realip_create_srv_conf(ngx_co static char * -ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { - ngx_stream_realip_srv_conf_t *prev = parent; - ngx_stream_realip_srv_conf_t *conf = child; + ngx_mail_realip_srv_conf_t *prev = parent; + ngx_mail_realip_srv_conf_t *conf = child; if (conf->from == NULL) { conf->from = prev->from; @@ -308,94 +267,3 @@ ngx_stream_realip_merge_srv_conf(ngx_con return NGX_CONF_OK; } - - -static ngx_int_t -ngx_stream_realip_add_variables(ngx_conf_t *cf) -{ - ngx_stream_variable_t *var, *v; - - for (v = ngx_stream_realip_vars; v->name.len; v++) { - var = ngx_stream_add_variable(cf, &v->name, v->flags); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = v->get_handler; - var->data = v->data; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_stream_realip_init(ngx_conf_t *cf) -{ - ngx_stream_handler_pt *h; - ngx_stream_core_main_conf_t *cmcf; - - cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); - - h = ngx_array_push(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers); - if (h == NULL) { - return NGX_ERROR; - } - - *h = ngx_stream_realip_handler; - - return NGX_OK; -} - - -static ngx_int_t -ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data) -{ - ngx_str_t *addr_text; - ngx_stream_realip_ctx_t *ctx; - - ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); - - addr_text = ctx ? &ctx->addr_text : &s->connection->addr_text; - - v->len = addr_text->len; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = addr_text->data; - - return NGX_OK; -} - - -static ngx_int_t -ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data) -{ - ngx_uint_t port; - struct sockaddr *sa; - ngx_stream_realip_ctx_t *ctx; - - ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); - - sa = ctx ? ctx->sockaddr : s->connection->sockaddr; - - v->len = 0; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1); - if (v->data == NULL) { - return NGX_ERROR; - } - - port = ngx_inet_get_port(sa); - - if (port > 0 && port < 65536) { - v->len = ngx_sprintf(v->data, "%ui", port) - v->data; - } - - return NGX_OK; -} # HG changeset patch # User Maxim Dounin # Date 1613827679 -10800 # Sat Feb 20 16:27:59 2021 +0300 # Node ID 30a66f88bb5d30bbfb445b57bd54c9ca35a345ec # Parent 068d1bf4f2b3faaf84ec937c091274c940b5e1ca Mail: sending of the PROXY protocol to backends. Activated with the "proxy_protocol" directive. Can be combined with "listen ... proxy_protocol;" and "set_real_ip_from ...;" to pass client address provided to nginx in the PROXY protocol header. diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -178,6 +178,7 @@ typedef enum { typedef struct { ngx_peer_connection_t upstream; ngx_buf_t *buffer; + ngx_uint_t proxy_protocol; /* unsigned proxy_protocol:1; */ } ngx_mail_proxy_ctx_t; diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -17,6 +17,7 @@ typedef struct { ngx_flag_t pass_error_message; ngx_flag_t xclient; ngx_flag_t smtp_auth; + ngx_flag_t proxy_protocol; size_t buffer_size; ngx_msec_t timeout; } ngx_mail_proxy_conf_t; @@ -26,7 +27,8 @@ static void ngx_mail_proxy_block_read(ng static void ngx_mail_proxy_pop3_handler(ngx_event_t *rev); static void ngx_mail_proxy_imap_handler(ngx_event_t *rev); static void ngx_mail_proxy_smtp_handler(ngx_event_t *rev); -static void ngx_mail_proxy_dummy_handler(ngx_event_t *ev); +static void ngx_mail_proxy_write_handler(ngx_event_t *wev); +static ngx_int_t ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s); static ngx_int_t ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state); static void ngx_mail_proxy_handler(ngx_event_t *ev); @@ -82,6 +84,13 @@ static ngx_command_t ngx_mail_proxy_com offsetof(ngx_mail_proxy_conf_t, smtp_auth), NULL }, + { ngx_string("proxy_protocol"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, proxy_protocol), + NULL }, + ngx_null_command }; @@ -156,7 +165,7 @@ ngx_mail_proxy_init(ngx_mail_session_t * p->upstream.connection->pool = s->connection->pool; s->connection->read->handler = ngx_mail_proxy_block_read; - p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler; + p->upstream.connection->write->handler = ngx_mail_proxy_write_handler; pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); @@ -167,6 +176,8 @@ ngx_mail_proxy_init(ngx_mail_session_t * return; } + s->proxy->proxy_protocol = pcf->proxy_protocol; + s->out.len = 0; switch (s->protocol) { @@ -186,6 +197,12 @@ ngx_mail_proxy_init(ngx_mail_session_t * s->mail_state = ngx_smtp_start; break; } + + if (rc == NGX_AGAIN) { + return; + } + + ngx_mail_proxy_write_handler(p->upstream.connection->write); } @@ -230,6 +247,17 @@ ngx_mail_proxy_pop3_handler(ngx_event_t return; } + if (s->proxy->proxy_protocol) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy pop3 busy"); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + return; + } + rc = ngx_mail_proxy_read_response(s, 0); if (rc == NGX_AGAIN) { @@ -353,6 +381,17 @@ ngx_mail_proxy_imap_handler(ngx_event_t return; } + if (s->proxy->proxy_protocol) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy imap busy"); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + return; + } + rc = ngx_mail_proxy_read_response(s, s->mail_state); if (rc == NGX_AGAIN) { @@ -499,6 +538,17 @@ ngx_mail_proxy_smtp_handler(ngx_event_t return; } + if (s->proxy->proxy_protocol) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy smtp busy"); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + return; + } + rc = ngx_mail_proxy_read_response(s, s->mail_state); if (rc == NGX_AGAIN) { @@ -799,19 +849,92 @@ ngx_mail_proxy_smtp_handler(ngx_event_t static void -ngx_mail_proxy_dummy_handler(ngx_event_t *wev) +ngx_mail_proxy_write_handler(ngx_event_t *wev) { ngx_connection_t *c; ngx_mail_session_t *s; - ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy dummy handler"); + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy write handler"); + + c = wev->data; + s = c->data; + + if (s->proxy->proxy_protocol) { + if (ngx_mail_proxy_send_proxy_protocol(s) != NGX_OK) { + return; + } + + s->proxy->proxy_protocol = 0; + } if (ngx_handle_write_event(wev, 0) != NGX_OK) { - c = wev->data; - s = c->data; + ngx_mail_proxy_internal_server_error(s); + } + + if (c->read->ready) { + ngx_post_event(c->read, &ngx_posted_events); + } +} + + +static ngx_int_t +ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s) +{ + u_char *p; + ssize_t n, size; + ngx_connection_t *c; + u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; + + s->connection->log->action = "sending PROXY protocol header to upstream"; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "mail proxy send PROXY protocol header"); + + p = ngx_proxy_protocol_write(s->connection, buf, + buf + NGX_PROXY_PROTOCOL_MAX_HEADER); + if (p == NULL) { + ngx_mail_proxy_internal_server_error(s); + return NGX_ERROR; + } + + c = s->proxy->upstream.connection; + + size = p - buf; - ngx_mail_proxy_close_session(s); + n = c->send(c, buf, size); + + if (n == NGX_AGAIN) { + if (ngx_handle_write_event(c->write, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return NGX_ERROR; + } + + return NGX_AGAIN; + } + + if (n == NGX_ERROR) { + ngx_mail_proxy_internal_server_error(s); + return NGX_ERROR; } + + if (n != size) { + + /* + * PROXY protocol specification: + * The sender must always ensure that the header + * is sent at once, so that the transport layer + * maintains atomicity along the path to the receiver. + */ + + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "could not send PROXY protocol header at once"); + + ngx_mail_proxy_internal_server_error(s); + + return NGX_ERROR; + } + + return NGX_OK; } @@ -1212,6 +1335,7 @@ ngx_mail_proxy_create_conf(ngx_conf_t *c pcf->pass_error_message = NGX_CONF_UNSET; pcf->xclient = NGX_CONF_UNSET; pcf->smtp_auth = NGX_CONF_UNSET; + pcf->proxy_protocol = NGX_CONF_UNSET; pcf->buffer_size = NGX_CONF_UNSET_SIZE; pcf->timeout = NGX_CONF_UNSET_MSEC; @@ -1229,6 +1353,7 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf ngx_conf_merge_value(conf->pass_error_message, prev->pass_error_message, 0); ngx_conf_merge_value(conf->xclient, prev->xclient, 1); ngx_conf_merge_value(conf->smtp_auth, prev->smtp_auth, 0); + ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0); ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, (size_t) ngx_pagesize); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Sat Feb 20 16:21:29 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 20 Feb 2021 16:21:29 +0000 Subject: [nginx] SSL: X509_NAME_oneline() error handling. Message-ID: details: https://hg.nginx.org/nginx/rev/018a09b766ef branches: changeset: 7779:018a09b766ef user: Maxim Dounin date: Sat Feb 20 18:02:49 2021 +0300 description: SSL: X509_NAME_oneline() error handling. diffstat: src/event/ngx_event_openssl.c | 44 +++++++++++++++++++++++++++++++++++++----- 1 files changed, 38 insertions(+), 6 deletions(-) diffs (77 lines): diff -r 549b13cd793b -r 018a09b766ef src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Sat Feb 20 12:44:26 2021 +0300 +++ b/src/event/ngx_event_openssl.c Sat Feb 20 18:02:49 2021 +0300 @@ -1019,21 +1019,43 @@ ngx_ssl_verify_callback(int ok, X509_STO depth = X509_STORE_CTX_get_error_depth(x509_store); sname = X509_get_subject_name(cert); - subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)"; + + if (sname) { + subject = X509_NAME_oneline(sname, NULL, 0); + if (subject == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, + "X509_NAME_oneline() failed"); + } + + } else { + subject = NULL; + } iname = X509_get_issuer_name(cert); - issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)"; + + if (iname) { + issuer = X509_NAME_oneline(iname, NULL, 0); + if (issuer == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, + "X509_NAME_oneline() failed"); + } + + } else { + issuer = NULL; + } ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0, "verify:%d, error:%d, depth:%d, " "subject:\"%s\", issuer:\"%s\"", - ok, err, depth, subject, issuer); - - if (sname) { + ok, err, depth, + subject ? subject : "(none)", + issuer ? issuer : "(none)"); + + if (subject) { OPENSSL_free(subject); } - if (iname) { + if (issuer) { OPENSSL_free(issuer); } #endif @@ -4900,6 +4922,11 @@ ngx_ssl_get_subject_dn_legacy(ngx_connec } p = X509_NAME_oneline(name, NULL, 0); + if (p == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed"); + X509_free(cert); + return NGX_ERROR; + } for (len = 0; p[len]; len++) { /* void */ } @@ -4943,6 +4970,11 @@ ngx_ssl_get_issuer_dn_legacy(ngx_connect } p = X509_NAME_oneline(name, NULL, 0); + if (p == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed"); + X509_free(cert); + return NGX_ERROR; + } for (len = 0; p[len]; len++) { /* void */ } From mdounin at mdounin.ru Sat Feb 20 16:21:32 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 20 Feb 2021 16:21:32 +0000 Subject: [nginx] SSL: added missed error reporting during variables evaluation. Message-ID: details: https://hg.nginx.org/nginx/rev/3bed5797a1b7 branches: changeset: 7780:3bed5797a1b7 user: Maxim Dounin date: Sat Feb 20 18:02:54 2021 +0300 description: SSL: added missed error reporting during variables evaluation. diffstat: src/event/ngx_event_openssl.c | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-) diffs (101 lines): diff -r 018a09b766ef -r 3bed5797a1b7 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Sat Feb 20 18:02:49 2021 +0300 +++ b/src/event/ngx_event_openssl.c Sat Feb 20 18:02:54 2021 +0300 @@ -83,7 +83,7 @@ static time_t ngx_ssl_parse_time( #if OPENSSL_VERSION_NUMBER > 0x10100000L const #endif - ASN1_TIME *asn1time); + ASN1_TIME *asn1time, ngx_log_t *log); static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -4817,11 +4817,13 @@ ngx_ssl_get_subject_dn(ngx_connection_t bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed"); goto failed; } @@ -4869,11 +4871,13 @@ ngx_ssl_get_issuer_dn(ngx_connection_t * bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed"); goto failed; } @@ -5011,6 +5015,7 @@ ngx_ssl_get_serial_number(ngx_connection bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } @@ -5049,6 +5054,7 @@ ngx_ssl_get_fingerprint(ngx_connection_t } if (!X509_digest(cert, EVP_sha1(), buf, &len)) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_digest() failed"); X509_free(cert); return NGX_ERROR; } @@ -5122,6 +5128,7 @@ ngx_ssl_get_client_v_start(ngx_connectio bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } @@ -5166,6 +5173,7 @@ ngx_ssl_get_client_v_end(ngx_connection_ bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } @@ -5208,9 +5216,9 @@ ngx_ssl_get_client_v_remain(ngx_connecti } #if OPENSSL_VERSION_NUMBER > 0x10100000L - end = ngx_ssl_parse_time(X509_get0_notAfter(cert)); + end = ngx_ssl_parse_time(X509_get0_notAfter(cert), c->log); #else - end = ngx_ssl_parse_time(X509_get_notAfter(cert)); + end = ngx_ssl_parse_time(X509_get_notAfter(cert), c->log); #endif if (end == (time_t) NGX_ERROR) { @@ -5245,7 +5253,7 @@ ngx_ssl_parse_time( #if OPENSSL_VERSION_NUMBER > 0x10100000L const #endif - ASN1_TIME *asn1time) + ASN1_TIME *asn1time, ngx_log_t *log) { BIO *bio; char *value; @@ -5261,6 +5269,7 @@ ngx_ssl_parse_time( bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "BIO_new() failed"); return NGX_ERROR; } From mdounin at mdounin.ru Sat Feb 20 16:21:35 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 20 Feb 2021 16:21:35 +0000 Subject: [nginx] SSL: added check for debugging. Message-ID: details: https://hg.nginx.org/nginx/rev/51e6a665523c branches: changeset: 7781:51e6a665523c user: Maxim Dounin date: Sat Feb 20 18:03:04 2021 +0300 description: SSL: added check for debugging. If debugging is not enabled, there is no need to do extra work in ngx_ssl_verify_callback() and ngx_ssl_handshake_log(). diffstat: src/event/ngx_event_openssl.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diffs (25 lines): diff -r 3bed5797a1b7 -r 51e6a665523c src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Sat Feb 20 18:02:54 2021 +0300 +++ b/src/event/ngx_event_openssl.c Sat Feb 20 18:03:04 2021 +0300 @@ -1014,6 +1014,10 @@ ngx_ssl_verify_callback(int ok, X509_STO c = ngx_ssl_get_connection(ssl_conn); + if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) { + return 1; + } + cert = X509_STORE_CTX_get_current_cert(x509_store); err = X509_STORE_CTX_get_error(x509_store); depth = X509_STORE_CTX_get_error_depth(x509_store); @@ -1970,6 +1974,10 @@ ngx_ssl_handshake_log(ngx_connection_t * #endif SSL_CIPHER *cipher; + if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) { + return; + } + cipher = SSL_get_current_cipher(c->ssl->connection); if (cipher) { From vadimjunk at gmail.com Sun Feb 21 21:55:10 2021 From: vadimjunk at gmail.com (Vadim Fedorenko) Date: Sun, 21 Feb 2021 21:55:10 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> Message-ID: Hi! Looks like this small fix doesn't work in case when the total size of the file is less than the size of the buffer and it was partly read. In my case the size of the file is 16384 bytes and only one page of the file was in page cache. This patch produces size = 8192 bytes for my case and the next call reads 12288 bytes and generates errors like below: "[alert] 28441#28441: *20855 pread() read only 12288 of 8192 from " changing to size = ngx_min(size, dst->end - dst->last); fixes the problem Thanks, Vadim ??, 25 ???. 2021 ?. ? 08:25, Zhao, Ping : > Hello, add a small update to correct the length when part of request > already received in previous. > This case may happen when using io_uring and throughput increased. > > # HG changeset patch > # User Ping Zhao > # Date 1611566408 18000 > # Mon Jan 25 04:20:08 2021 -0500 > # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 > # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 > Correct length calculation when part of request received. > > diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c > --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 > +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 > @@ -531,6 +531,14 @@ > > size = ngx_buf_size(src); > size = ngx_min(size, dst->end - dst->pos); > +#if (NGX_HAVE_FILE_IOURING) > + /* > + * check if already received part of the request in previous, > + * calculate the remain length > + */ > + if(dst->last > dst->pos && size > (dst->last - dst->pos)) > + size = size - (dst->last - dst->pos); > +#endif > > sendfile = ctx->sendfile && !ctx->directio; > > -----Original Message----- > From: nginx-devel On Behalf Of Zhao, Ping > Sent: Thursday, January 21, 2021 9:44 AM > To: nginx-devel at nginx.org > Subject: RE: [PATCH] Add io_uring support in AIO(async io) module > > Hi Vladimir, > > No special/extra configuration needed, but need check if 'aio on' and > 'sendfile off' is correctly set. This is my Nginx config for reference: > > user nobody; > daemon off; > worker_processes 1; > error_log error.log ; > events { > worker_connections 65535; > use epoll; > } > > http { > include mime.types; > default_type application/octet-stream; > access_log on; > aio on; > sendfile off; > directio 2k; > > # Cache Configurations > proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m > max_size=1400g inactive=4d use_temp_path=off; ...... > > > To better measure the disk io performance data, I do the following steps: > 1. To exclude other impact, and focus on disk io part.(This patch only > impact disk aio read process) Use cgroup to limit Nginx memory usage. > Otherwise Nginx may also use memory as cache storage and this may cause > test result not so straight.(since most cache hit in memory, disk io bw is > low, like my previous mail found which didn't exclude the memory cache > impact) > echo 2G > memory.limit_in_bytes > use ' cgexec -g memory:nginx' to start Nginx. > > 2. use wrk -t 100 -c 1000, with random 25000 http requests. > My previous test used -t 200 connections, comparing with -t 1000, > libaio performance drop more when connections numbers increased from 200 to > 1000, but io_uring doesn't. It's another advantage of io_uring. > > 3. First clean the cache disk and run the test for 30 minutes to let Nginx > store the cache files to nvme disk as much as possible. > > 4. Rerun the test, this time Nginx will use ngx_file_aio_read to extract > the cache files in nvme cache disk. Use iostat to track the io data. The > data should be align with NIC bw since all data should be from cache > disk.(need exclude memory as cache storage impact) > > Following is the test result: > > Nginx worker_processes 1: > 4k 100k 1M > Io_uring 220MB/s 1GB/s 1.3GB/s > Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) > > > Nginx worker_processes 4: > 4k 100k 1M > Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) > libaio 250MB/s 900MB/s 2.0GB/s > > So for small request, io_uring has huge improvement than libaio. In > previous mail, because I didn't exclude the memory cache storage impact, > most cache file is stored in memory, very few are from disk in case of > 4k/100k. The data is not correct.(for 1M, because the cache is too big to > store in memory, it wat in disk) Also I enabled directio option "directio > 2k" this time to avoid this. > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Vladimir > Homutov > Sent: Wednesday, January 20, 2021 12:43 AM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: > > It depends on if disk io is the performance hot spot or not. If yes, > > io_uring shows improvement than libaio. With 4KB/100KB length 1 Nginx > > thread it's hard to see performance difference because iostat is only > > around ~10MB/100MB per second. Disk io is not the performance bottle > > neck, both libaio and io_uring have the same performance. If you > > increase request size or Nginx threads number, for example 1MB length > > or Nginx thread number 4. In this case, disk io became the performance > > bottle neck, you will see io_uring performance improvement. > > Can you please provide full test results with specific nginx configuration? > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ping.zhao at intel.com Mon Feb 22 07:39:46 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Mon, 22 Feb 2021 07:39:46 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <853670ef-7379-42bb-15d0-68482e64de24@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> <853670ef-7379-42bb-15d0-68482e64de24@nginx.com> Message-ID: Hi Mikhail, My steps are almost same as yours. The context switches number(csw) seems related with the file size if other configurations are same. My previous data is with 4KB file(csw: ~90k). With 100KB file(csw: ~40k), 1MB file(csw: ~5k). Which kernel version are you using? I think if it's possible some problems in kernel. For 'io_uring_queue_init_params() failed (12: Cannot allocate memory)' problem. I have a patch to fix it. Add a io_uring_entries in config file event section. # HG changeset patch # User Ping Zhao # Date 1614006158 18000 # Mon Feb 22 10:02:38 2021 -0500 # Node ID 9e3ad9721e224ab193f0311bf4a6e4a1cb4f754b # Parent f2c91860b7ac4b374fff4353a830cd9427e1d027 Add io_uring_entries in configure file. diff -r f2c91860b7ac -r 9e3ad9721e22 src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c Mon Jan 25 04:20:08 2021 -0500 +++ b/src/event/modules/ngx_epoll_module.c Mon Feb 22 10:02:38 2021 -0500 @@ -104,6 +104,9 @@ typedef struct { ngx_uint_t events; ngx_uint_t aio_requests; +#if (NGX_HAVE_FILE_IOURING) + ngx_uint_t entries; +#endif } ngx_epoll_conf_t; @@ -184,7 +187,14 @@ 0, offsetof(ngx_epoll_conf_t, aio_requests), NULL }, - +#if (NGX_HAVE_FILE_IOURING) + { ngx_string("io_uring_entries"), + NGX_EVENT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + 0, + offsetof(ngx_epoll_conf_t, entries), + NULL }, +#endif ngx_null_command }; @@ -237,7 +247,7 @@ { struct epoll_event ee; - if (io_uring_queue_init_params(32763, &ngx_ring, &ngx_ring_params) < 0) { + if (io_uring_queue_init_params(epcf->entries, &ngx_ring, &ngx_ring_params) < 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "io_uring_queue_init_params() failed"); goto failed; @@ -1130,7 +1140,9 @@ epcf->events = NGX_CONF_UNSET; epcf->aio_requests = NGX_CONF_UNSET; - +#if (NGX_HAVE_FILE_IOURING) + epcf->entries = NGX_CONF_UNSET; +#endif return epcf; } @@ -1142,6 +1154,9 @@ ngx_conf_init_uint_value(epcf->events, 512); ngx_conf_init_uint_value(epcf->aio_requests, 32); +#if (NGX_HAVE_FILE_IOURING) + ngx_conf_init_uint_value(epcf->entries, 1024); +#endif return NGX_CONF_OK; } BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Monday, February 15, 2021 4:12 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, First of all, happy Chinese New Year! Yes, I've checked this first. Nginx binary linked with liburing and, without 'ulimit -l unlimited', there were 'io_uring_queue_init_params() failed (12: Cannot allocate memory)' error in error.log. I believe that io_uring is working correctly. But, as I can see, numbers in last two columns of dstat output (interrupts and context switches) much larger in your case instead of mine. So, could you please re-test (following my steps) when you will return to office? Thanks in advance! 15.02.2021 09:08, Zhao, Ping ?????: > Hi Mikhail, > > Sorry for late. I'm on Chinese New Year holiday leave. I can't see any problem from your steps, but the result is different from mine. It's strange, I'll try when I'm back to office next week. Would you check the io_uring nginx with ldd to see if it's linked with liburing first? > > # ldd /path/to/nginx > linux-vdso.so.1 (0x00007ffce4ff8000) > libdl.so.2 => /lib64/libdl.so.2 (0x00007f72aa689000) > liburing.so.1 => /lib64/liburing.so.1 (0x00007f72aa485000) > .... > > Or you can enable the debug log option in config to see if any 'io_uring_peek_cqe' in the log: > > [debug] 53391#53391: io_uring_peek_cqe: START > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Tuesday, February 9, 2021 9:31 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. > > 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. > 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx > 3. Limit memory to 80 Mb, for example: echo > 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes > 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... > > I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. > > For example, with 100kb files and 1 worker process: > > free -lh > total used free shared buff/cache > available > Mem: 15Gi 212Mi 14Gi 13Mi 318Mi > 14Gi > > dstat/libaio > 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 > 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 > 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 > 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 > 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 > 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 > 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 > 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 > 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 > dstat/io_uring > 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k > 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 > 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k > 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 > 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k > 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 > 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 > 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 > 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 > > As you can see, libaio even faster a bit. > > 09.02.2021 11:36, Zhao, Ping ?????: >> Hi Mikhail, >> >> The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. >> >> If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. >> >> memory >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi >> >> libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 >> 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 >> 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 >> 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 >> 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 >> 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 >> 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 >> 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 >> 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 >> 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 >> 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 >> 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 >> >> I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. >> >> Memory: >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi >> >> Libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k >> 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k >> 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k >> 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k >> 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k >> 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k >> 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k >> 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k >> >> Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. >> >> BR, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Mikhail Isachenkov >> Sent: Tuesday, February 9, 2021 1:17 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. >> >> I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. >> >> As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: >> >> a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. >> >> b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). >> >> I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? >> >> Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. >> >> Thanks in advance! >> >> 07.02.2021 05:16, Zhao, Ping ?????: >>> Hi Mikhail, >>> >>> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >>> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >>> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >>> >>> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile 70MB/s 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile 250MB/s 900MB/s 1.6GB/s >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: Zhao, Ping >>> Sent: Friday, February 5, 2021 2:43 PM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Mikhail, >>> >>> Added 'sendfile on' & 'aio off' test result with previous table: >>> >>> Following is the test result with 100KB and 1MB: (4KB to be test) >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile tbt 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile tbt 900MB/s 1.6GB/s >>> >>> Regards, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Thursday, February 4, 2021 4:55 PM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Zhao Ping, >>> >>> My test is much simpler than yours. I created >>> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >>> These files does not change during test. >>> >>> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >>> >>> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >>> >>> Thanks in advance! >>> >>> 04.02.2021 10:08, Zhao, Ping ?????: >>>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>>> >>>> -----Original Message----- >>>> From: Zhao, Ping >>>> Sent: Thursday, February 4, 2021 10:33 AM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Mikhail, >>>> >>>> I didn't see this error in my log. Following is my OS/Kernel: >>>> CentOS: 8.1.1911 >>>> Kernel: 5.7.19 >>>> Liburing: liburing-1.0.7-3.el8.x86_64, >>>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>>> >>>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>>> >>>> My nginx reported this error before: >>>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>>> Which is fixed by my 2nd patch(Jan 25) already. >>>> >>>> BR, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Mikhail Isachenkov >>>> Sent: Wednesday, February 3, 2021 10:11 PM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Ping Zhao, >>>> >>>> When I try to repeat this test, I've got a huge number of these errors: >>>> >>>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>>> "/usr/local/html/64746" failed (11: Resource temporarily >>>> unavailable) while sending response to client, client: 127.0.0.1, server: >>>> localhost, >>>> request: "GET /64746 HTTP/1.1", host: "localhost" >>>> >>>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>>> >>>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>>> >>>> 25.01.2021 11:24, Zhao, Ping ?????: >>>>> Hello, add a small update to correct the length when part of request already received in previous. >>>>> This case may happen when using io_uring and throughput increased. >>>>> >>>>> # HG changeset patch >>>>> # User Ping Zhao # Date 1611566408 18000 >>>>> # Mon Jan 25 04:20:08 2021 -0500 >>>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>>> Correct length calculation when part of request received. >>>>> >>>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>>> @@ -531,6 +531,14 @@ >>>>> >>>>> size = ngx_buf_size(src); >>>>> size = ngx_min(size, dst->end - dst->pos); >>>>> +#if (NGX_HAVE_FILE_IOURING) >>>>> + /* >>>>> + * check if already received part of the request in previous, >>>>> + * calculate the remain length >>>>> + */ >>>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>>> + size = size - (dst->last - dst->pos); #endif >>>>> >>>>> sendfile = ctx->sendfile && !ctx->directio; >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Zhao, Ping >>>>> Sent: Thursday, January 21, 2021 9:44 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Vladimir, >>>>> >>>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>>> >>>>> user nobody; >>>>> daemon off; >>>>> worker_processes 1; >>>>> error_log error.log ; >>>>> events { >>>>> worker_connections 65535; >>>>> use epoll; >>>>> } >>>>> >>>>> http { >>>>> include mime.types; >>>>> default_type application/octet-stream; >>>>> access_log on; >>>>> aio on; >>>>> sendfile off; >>>>> directio 2k; >>>>> >>>>> # Cache Configurations >>>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>>> >>>>> >>>>> To better measure the disk io performance data, I do the following steps: >>>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>>> echo 2G > memory.limit_in_bytes >>>>> use ' cgexec -g memory:nginx' to start Nginx. >>>>> >>>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>>> >>>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>>> >>>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>>> extract the cache files in nvme cache disk. Use iostat to track >>>>> the io data. The data should be align with NIC bw since all data >>>>> should be from cache disk.(need exclude memory as cache storage >>>>> impact) >>>>> >>>>> Following is the test result: >>>>> >>>>> Nginx worker_processes 1: >>>>> 4k 100k 1M >>>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>>> >>>>> >>>>> Nginx worker_processes 4: >>>>> 4k 100k 1M >>>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>>> libaio 250MB/s 900MB/s 2.0GB/s >>>>> >>>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>>> >>>>> Regards, >>>>> Ping >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Vladimir Homutov >>>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>>> It depends on if disk io is the performance hot spot or not. If >>>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB >>>>>> length >>>>>> 1 Nginx thread it's hard to see performance difference because >>>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>>> performance bottle neck, both libaio and io_uring have the same >>>>>> performance. If you increase request size or Nginx threads >>>>>> number, for example 1MB length or Nginx thread number 4. In this >>>>>> case, disk io became the performance bottle neck, you will see io_uring performance improvement. >>>>> >>>>> Can you please provide full test results with specific nginx configuration? >>>>> >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> >>>> >>>> -- >>>> Best regards, >>>> Mikhail Isachenkov >>>> NGINX Professional Services >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From ping.zhao at intel.com Mon Feb 22 08:27:10 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Mon, 22 Feb 2021 08:27:10 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> Message-ID: Hi Vadim, Thanks for your finding. The size is updated after previous io request. This method is correct and better. BR, Ping From: Vadim Fedorenko Sent: Monday, February 22, 2021 5:55 AM To: nginx-devel at nginx.org Cc: Zhao, Ping Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi! Looks like this small fix doesn't work in case when the total size of the file is less than the size of the buffer and it was partly read. In my case the size of the file is 16384 bytes and only one page of the file was in page cache. This patch produces size = 8192 bytes for my case and the next call reads 12288 bytes and generates errors like below: "[alert] 28441#28441: *20855 pread() read only 12288 of 8192 from " changing to size = ngx_min(size, dst->end - dst->last); fixes the problem Thanks, Vadim ??, 25 ???. 2021 ?. ? 08:25, Zhao, Ping >: Hello, add a small update to correct the length when part of request already received in previous. This case may happen when using io_uring and throughput increased. # HG changeset patch # User Ping Zhao > # Date 1611566408 18000 # Mon Jan 25 04:20:08 2021 -0500 # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 Correct length calculation when part of request received. diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 @@ -531,6 +531,14 @@ size = ngx_buf_size(src); size = ngx_min(size, dst->end - dst->pos); +#if (NGX_HAVE_FILE_IOURING) + /* + * check if already received part of the request in previous, + * calculate the remain length + */ + if(dst->last > dst->pos && size > (dst->last - dst->pos)) + size = size - (dst->last - dst->pos); +#endif sendfile = ctx->sendfile && !ctx->directio; -----Original Message----- From: nginx-devel > On Behalf Of Zhao, Ping Sent: Thursday, January 21, 2021 9:44 AM To: nginx-devel at nginx.org Subject: RE: [PATCH] Add io_uring support in AIO(async io) module Hi Vladimir, No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: user nobody; daemon off; worker_processes 1; error_log error.log ; events { worker_connections 65535; use epoll; } http { include mime.types; default_type application/octet-stream; access_log on; aio on; sendfile off; directio 2k; # Cache Configurations proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... To better measure the disk io performance data, I do the following steps: 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) echo 2G > memory.limit_in_bytes use ' cgexec -g memory:nginx' to start Nginx. 2. use wrk -t 100 -c 1000, with random 25000 http requests. My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. 4. Rerun the test, this time Nginx will use ngx_file_aio_read to extract the cache files in nvme cache disk. Use iostat to track the io data. The data should be align with NIC bw since all data should be from cache disk.(need exclude memory as cache storage impact) Following is the test result: Nginx worker_processes 1: 4k 100k 1M Io_uring 220MB/s 1GB/s 1.3GB/s Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) Nginx worker_processes 4: 4k 100k 1M Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) libaio 250MB/s 900MB/s 2.0GB/s So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. Regards, Ping -----Original Message----- From: nginx-devel > On Behalf Of Vladimir Homutov Sent: Wednesday, January 20, 2021 12:43 AM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: > It depends on if disk io is the performance hot spot or not. If yes, > io_uring shows improvement than libaio. With 4KB/100KB length 1 Nginx > thread it's hard to see performance difference because iostat is only > around ~10MB/100MB per second. Disk io is not the performance bottle > neck, both libaio and io_uring have the same performance. If you > increase request size or Nginx threads number, for example 1MB length > or Nginx thread number 4. In this case, disk io became the performance > bottle neck, you will see io_uring performance improvement. Can you please provide full test results with specific nginx configuration? _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From pgnet.dev at gmail.com Mon Feb 22 16:57:22 2021 From: pgnet.dev at gmail.com (PGNet Dev) Date: Mon, 22 Feb 2021 11:57:22 -0500 Subject: nginx 1.19.7 + njs {0.5.0/0.5.1/HEAD} fail for Fedora 34; ok for Fedora 33. gcc version? (F33 -> 10x, F34 -> 11x) Message-ID: <21d62839-fba9-f693-aabc-c85861cf43f7@gmail.com> i'm re-building nginx 1.19.7 @ fedora's COPR buildsys, enabling Fedora 34 builds, in addition to (current) Fedora 33 builds, https://copr.fedorainfracloud.org/coprs/pgfed/nginx-mainline/build/2013618/ builds with any of njs release tag 0.5.0, 0.5.1 or HEAD are fine for Fedora 33 -- no errors on build, and bins exec ok. builds with same spec, for Fedora 34, fails @ njs ... /usr/bin/gcc -c -pipe -fPIC -fvisibility=hidden -O -W -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wmissing-prototypes -Werror -g -O -I/usr/local/luajit2-openresty/include/luajit-2.1 -O3 -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -march=x86-64 -mtune=generic -O3 -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -march=x86-64 -mtune=generic -DNDK_SET_VAR -Wno-deprecated-declarations \ -Isrc -Ibuild -Injs \ -o build/src/njs_fs.o \ -MMD -MF build/src/njs_fs.dep -MT build/src/njs_fs.o \ src/njs_fs.c !!! src/njs_fs.c:1376:33: error: argument 2 of type 'char *' declared as a pointer [-Werror=array-parameter=] 1376 | njs_fs_path(njs_vm_t *vm, char *storage, const njs_value_t *src, | ~~~~~~^~~~~~~ src/njs_fs.c:96:51: note: previously declared as an array 'char[4097]' 96 | static const char *njs_fs_path(njs_vm_t *vm, char storage[NJS_MAX_PATH + 1], | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~ /usr/bin/gcc -c -pipe -fPIC -fvisibility=hidden -O -W -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wmissing-prototypes -Werror -g -O -I/usr/local/luajit2-openresty/include/luajit-2.1 -O3 -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -march=x86-64 -mtune=generic -O3 -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -march=x86-64 -mtune=generic -DNDK_SET_VAR -Wno-deprecated-declarations \ -Isrc -Ibuild -Injs \ -o build/src/njs_crypto.o \ -MMD -MF build/src/njs_crypto.dep -MT build/src/njs_crypto.o \ src/njs_crypto.c ... full build log, https://download.copr.fedorainfracloud.org/results/pgfed/nginx-mainline/fedora-34-x86_64/02013618-nginx/builder-live.log.gz i suspect F34's updated gcc version may be at fault @ https://src.fedoraproject.org/rpms/gcc, gcc release versions are Fedora 34 gcc-11.0.0-0.19.fc34 Fedora 33 gcc-10.2.1-3.fc33 i checked @ njs github, and didn't find a gcc11-related issue. is this a known/suspected issue already? or some other cause? From xeioex at nginx.com Mon Feb 22 17:20:03 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 22 Feb 2021 20:20:03 +0300 Subject: nginx 1.19.7 + njs {0.5.0/0.5.1/HEAD} fail for Fedora 34; ok for Fedora 33. gcc version? (F33 -> 10x, F34 -> 11x) In-Reply-To: <21d62839-fba9-f693-aabc-c85861cf43f7@gmail.com> References: <21d62839-fba9-f693-aabc-c85861cf43f7@gmail.com> Message-ID: On 22.02.2021 19:57, PGNet Dev wrote: > i checked @ njs github, and didn't find a gcc11-related issue. > > is this a known/suspected issue already? or some other cause? No, it is not. Feel free to report it on Github. From pgnet.dev at gmail.com Mon Feb 22 17:32:31 2021 From: pgnet.dev at gmail.com (PGNet Dev) Date: Mon, 22 Feb 2021 12:32:31 -0500 Subject: nginx 1.19.7 + njs {0.5.0/0.5.1/HEAD} fail for Fedora 34; ok for Fedora 33. gcc version? (F33 -> 10x, F34 -> 11x) In-Reply-To: References: <21d62839-fba9-f693-aabc-c85861cf43f7@gmail.com> Message-ID: <981dd0a3-7427-5bb1-b2e0-cfa71c7b5369@gmail.com> On 2/22/21 12:20 PM, Dmitry Volyntsev wrote: > No, it is not. Feel free to report it on Github. +1 -> https://github.com/nginx/njs/issues/376 From xeioex at nginx.com Wed Feb 24 14:51:02 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 24 Feb 2021 14:51:02 +0000 Subject: [njs] Decoupling parser structure from the main VM structure. Message-ID: details: https://hg.nginx.org/njs/rev/1f22e9008cc3 branches: changeset: 1610:1f22e9008cc3 user: Dmitry Volyntsev date: Wed Feb 24 14:48:20 2021 +0000 description: Decoupling parser structure from the main VM structure. vm->parser is only needed during parsing phase, so it can be eliminated. This improves dependencies tracking and readability. As a side effect it fixes #372 issue on Github: previously, Function constructor left VM context in inconsistent state if compilation failed. The direct root cause was that a function object was created, but because Function constructor ended prematurely the object was not fully initialized. This is not a problem by itself because usually this partially created object cannot be referenced. In the accumulative mode, which is only enabled in CLI, vm->parser was used to store the references to the variables from the previous iteration. diffstat: src/njs_builtin.c | 6 +-- src/njs_function.c | 22 ++++-------- src/njs_module.c | 10 +++-- src/njs_parser.c | 84 +++++++++++++++++------------------------------ src/njs_parser.h | 9 ++-- src/njs_regexp.c | 8 +---- src/njs_shell.c | 10 ++-- src/njs_variable.c | 23 ++++++------ src/njs_variable.h | 4 +- src/njs_vm.c | 67 ++++++++++++-------------------------- src/njs_vm.h | 1 - src/test/njs_unit_test.c | 20 ++++++++-- 12 files changed, 104 insertions(+), 160 deletions(-) diffs (695 lines): diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_builtin.c --- a/src/njs_builtin.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_builtin.c Wed Feb 24 14:48:20 2021 +0000 @@ -613,10 +613,6 @@ njs_vm_expression_completions(njs_vm_t * njs_lvlhsh_query_t lhq; njs_variable_node_t var_node; - if (njs_slow_path(vm->parser == NULL)) { - return NULL; - } - p = expression->start; end = p + expression->length; @@ -635,7 +631,7 @@ njs_vm_expression_completions(njs_vm_t * var_node.key = (uintptr_t) lhq.value; - node = njs_rbtree_find(&vm->parser->scope->variables, &var_node.node); + node = njs_rbtree_find(vm->variables_hash, &var_node.node); if (njs_slow_path(node == NULL)) { return NULL; } diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_function.c --- a/src/njs_function.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_function.c Wed Feb 24 14:48:20 2021 +0000 @@ -874,7 +874,7 @@ njs_function_constructor(njs_vm_t *vm, n njs_str_t str, file; njs_uint_t i; njs_lexer_t lexer; - njs_parser_t *parser; + njs_parser_t parser; njs_vm_code_t *code; njs_function_t *function; njs_generator_t generator; @@ -926,15 +926,6 @@ njs_function_constructor(njs_vm_t *vm, n return NJS_ERROR; } - vm->options.accumulative = 1; - - parser = njs_mp_zalloc(vm->mem_pool, sizeof(njs_parser_t)); - if (njs_slow_path(parser == NULL)) { - return NJS_ERROR; - } - - vm->parser = parser; - file = njs_str_value("runtime"); ret = njs_lexer_init(vm, &lexer, &file, str.start, str.start + str.length); @@ -942,10 +933,11 @@ njs_function_constructor(njs_vm_t *vm, n return ret; } - parser->vm = vm; - parser->lexer = &lexer; + njs_memzero(&parser, sizeof(njs_parser_t)); - ret = njs_parser(parser, NULL); + parser.lexer = &lexer; + + ret = njs_parser(vm, &parser, NULL); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -957,7 +949,7 @@ njs_function_constructor(njs_vm_t *vm, n * the global object in a portable way. */ - node = parser->node; + node = parser.node; type = &safe_ast[0]; for (; *type != NJS_TOKEN_ILLEGAL; type++, node = node->right) { @@ -971,7 +963,7 @@ njs_function_constructor(njs_vm_t *vm, n } } - scope = parser->scope; + scope = parser.scope; ret = njs_variables_copy(vm, &scope->variables, vm->variables_hash); if (njs_slow_path(ret != NJS_OK)) { diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_module.c --- a/src/njs_module.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_module.c Wed Feb 24 14:48:20 2021 +0000 @@ -40,7 +40,7 @@ static njs_int_t njs_module_read(njs_vm_ static njs_module_t *njs_module_find(njs_vm_t *vm, njs_str_t *name, njs_bool_t local); static njs_module_t *njs_module_add(njs_vm_t *vm, njs_str_t *name); -static njs_int_t njs_module_insert(njs_vm_t *vm, njs_module_t *module); +static njs_int_t njs_module_insert(njs_parser_t *parser, njs_module_t *module); njs_int_t @@ -273,7 +273,7 @@ njs_parser_module_after(njs_parser_t *pa module = (njs_module_t *) parser->target; if (module->index == 0) { - ret = njs_module_insert(parser->vm, module); + ret = njs_module_insert(parser, module); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -564,12 +564,14 @@ njs_module_add(njs_vm_t *vm, njs_str_t * static njs_int_t -njs_module_insert(njs_vm_t *vm, njs_module_t *module) +njs_module_insert(njs_parser_t *parser, njs_module_t *module) { + njs_vm_t *vm; njs_module_t **value; njs_parser_scope_t *scope; - scope = njs_parser_global_scope(vm); + scope = njs_parser_global_scope(parser); + vm = parser->vm; module->index = njs_scope_next_index(vm, scope, NJS_SCOPE_INDEX_LOCAL, &njs_value_undefined); diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_parser.c --- a/src/njs_parser.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_parser.c Wed Feb 24 14:48:20 2021 +0000 @@ -503,23 +503,26 @@ njs_parser_reject(njs_parser_t *parser) njs_int_t -njs_parser(njs_parser_t *parser, njs_parser_t *prev) +njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_rbtree_t *prev_vars) { njs_int_t ret; njs_lexer_token_t *token; + parser->vm = vm; + + njs_set_undefined(&vm->retval); + ret = njs_parser_scope_begin(parser, NJS_SCOPE_GLOBAL); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - if (prev != NULL) { + if (prev_vars != NULL) { /* * Copy the global scope variables from the previous * iteration of the accumulative mode. */ - ret = njs_variables_copy(parser->vm, &parser->scope->variables, - &prev->scope->variables); + ret = njs_variables_copy(vm, &parser->scope->variables, prev_vars); if (ret != NJS_OK) { return ret; } @@ -551,7 +554,7 @@ njs_parser(njs_parser_t *parser, njs_par return NJS_ERROR; } - if (njs_is_error(&parser->vm->retval)) { + if (njs_is_error(&vm->retval)) { return NJS_ERROR; } @@ -1196,11 +1199,14 @@ njs_parser_regexp_literal(njs_parser_t * { u_char *p; njs_str_t text; + njs_int_t ret; njs_lexer_t *lexer; - njs_value_t *value; + njs_value_t *value, retval; njs_regexp_flags_t flags; njs_regexp_pattern_t *pattern; + static const njs_value_t string_message = njs_string("message"); + value = &parser->node->u.value; lexer = parser->lexer; @@ -1269,6 +1275,18 @@ njs_parser_regexp_literal(njs_parser_t * text.length, flags); if (njs_slow_path(pattern == NULL)) { + ret = njs_value_property(parser->vm, &parser->vm->retval, + njs_value_arg(&string_message), + &retval); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + njs_string_get(&retval, &text); + njs_value_undefined_set(&parser->vm->retval); + + njs_parser_syntax_error(parser, "%V", &text); + return NJS_ERROR; } @@ -6460,7 +6478,7 @@ njs_parser_function_declaration(njs_pars njs_lexer_consume_token(parser->lexer, 1); - var = njs_variable_add(parser->vm, parser->scope, unique_id, + var = njs_variable_add(parser, parser->scope, unique_id, NJS_VARIABLE_FUNCTION); if (var == NULL) { return NJS_ERROR; @@ -6552,7 +6570,7 @@ njs_parser_function_expression(njs_parse } if (njs_lexer_token_is_binding_identifier(token)) { - var = njs_variable_add(parser->vm, parser->scope, token->unique_id, + var = njs_variable_add(parser, parser->scope, token->unique_id, NJS_VARIABLE_SHIM); if (var == NULL) { return NJS_ERROR; @@ -6649,7 +6667,7 @@ njs_parser_formal_parameters(njs_parser_ default: /* SingleNameBinding */ if (njs_lexer_token_is_binding_identifier(token)) { - arg = njs_variable_add(parser->vm, parser->scope, + arg = njs_variable_add(parser, parser->scope, token->unique_id, NJS_VARIABLE_VAR); if (arg == NULL) { return NJS_ERROR; @@ -6764,7 +6782,7 @@ njs_parser_arrow_function(njs_parser_t * njs_parser_arrow_function_args_after); } else if (njs_lexer_token_is_binding_identifier(token)) { - arg = njs_variable_add(parser->vm, parser->scope, + arg = njs_variable_add(parser, parser->scope, token->unique_id, NJS_VARIABLE_VAR); if (arg == NULL) { return NJS_ERROR; @@ -7517,7 +7535,7 @@ njs_parser_variable_node(njs_parser_t *p njs_variable_t *var; njs_parser_node_t *node; - var = njs_variable_add(parser->vm, parser->scope, unique_id, type); + var = njs_variable_add(parser, parser->scope, unique_id, type); if (njs_slow_path(var == NULL)) { return NULL; } @@ -7590,7 +7608,7 @@ njs_parser_reference(njs_parser_t *parse return NULL; } - var = njs_variable_add(parser->vm, scope, token->unique_id, + var = njs_variable_add(parser, scope, token->unique_id, NJS_VARIABLE_VAR); if (njs_slow_path(var == NULL)) { return NULL; @@ -7625,7 +7643,7 @@ njs_parser_reference(njs_parser_t *parse return NULL; } - var = njs_variable_add(parser->vm, scope, token->unique_id, + var = njs_variable_add(parser, scope, token->unique_id, NJS_VARIABLE_VAR); if (njs_slow_path(var == NULL)) { return NULL; @@ -8319,46 +8337,6 @@ njs_parser_unexpected_token(njs_vm_t *vm } -u_char * -njs_parser_trace_handler(njs_trace_t *trace, njs_trace_data_t *td, - u_char *start) -{ - u_char *p; - size_t size; - njs_vm_t *vm; - njs_lexer_t *lexer; - njs_parser_t *parser; - - size = njs_length("InternalError: "); - memcpy(start, "InternalError: ", size); - p = start + size; - - vm = trace->data; - - trace = trace->next; - p = trace->handler(trace, td, p); - - parser = vm->parser; - - if (parser != NULL && parser->lexer != NULL) { - lexer = parser->lexer; - - if (lexer->file.length != 0) { - njs_internal_error(vm, "%s in %V:%uD", start, &lexer->file, - parser->lexer->token->line); - } else { - njs_internal_error(vm, "%s in %uD", start, - parser->lexer->token->line); - } - - } else { - njs_internal_error(vm, "%s", start); - } - - return p; -} - - static void njs_parser_scope_error(njs_vm_t *vm, njs_parser_scope_t *scope, njs_object_type_t type, uint32_t line, const char *fmt, va_list args) diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_parser.h --- a/src/njs_parser.h Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_parser.h Wed Feb 24 14:48:20 2021 +0000 @@ -110,7 +110,8 @@ njs_int_t njs_parser_failed_state(njs_pa intptr_t njs_parser_scope_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2); -njs_int_t njs_parser(njs_parser_t *parser, njs_parser_t *prev); +njs_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, + njs_rbtree_t *prev_vars); njs_int_t njs_parser_module_lambda(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current); @@ -121,8 +122,6 @@ njs_token_type_t njs_parser_unexpected_t njs_str_t *name, njs_token_type_t type); njs_int_t njs_parser_string_create(njs_vm_t *vm, njs_lexer_token_t *token, njs_value_t *value); -u_char *njs_parser_trace_handler(njs_trace_t *trace, njs_trace_data_t *td, - u_char *start); void njs_parser_lexer_error(njs_parser_t *parser, njs_object_type_t type, const char *fmt, ...); void njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, @@ -201,11 +200,11 @@ njs_parser_node_string(njs_vm_t *vm, njs njs_inline njs_parser_scope_t * -njs_parser_global_scope(njs_vm_t *vm) +njs_parser_global_scope(njs_parser_t *parser) { njs_parser_scope_t *scope; - scope = vm->parser->scope; + scope = parser->scope; while (scope->type != NJS_SCOPE_GLOBAL) { scope = scope->parent; diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_regexp.c --- a/src/njs_regexp.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_regexp.c Wed Feb 24 14:48:20 2021 +0000 @@ -536,13 +536,7 @@ njs_regexp_compile_trace_handler(njs_tra trace = trace->next; p = trace->handler(trace, td, start); - if (vm->parser != NULL && vm->parser->lexer != NULL) { - njs_syntax_error(vm, "%*s in %uD", p - start, start, - vm->parser->lexer->line); - - } else { - njs_syntax_error(vm, "%*s", p - start, start); - } + njs_syntax_error(vm, "%*s", p - start, start); return p; } diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_shell.c --- a/src/njs_shell.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_shell.c Wed Feb 24 14:48:20 2021 +0000 @@ -996,8 +996,8 @@ njs_completion_generator(const char *tex cmpl->length = njs_strlen(text); cmpl->suffix_completions = NULL; - if (vm->parser != NULL) { - cmpl->node = njs_rbtree_min(&vm->parser->scope->variables); + if (vm->variables_hash != NULL) { + cmpl->node = njs_rbtree_min(vm->variables_hash); } } @@ -1005,12 +1005,12 @@ next: switch (cmpl->phase) { case NJS_COMPLETION_VAR: - if (vm->parser == NULL) { + variables = vm->variables_hash; + + if (variables == NULL) { njs_next_phase(cmpl); } - variables = &vm->parser->scope->variables; - while (njs_rbtree_is_there_successor(variables, cmpl->node)) { var_node = (njs_variable_node_t *) cmpl->node; diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_variable.c --- a/src/njs_variable.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_variable.c Wed Feb 24 14:48:20 2021 +0000 @@ -9,7 +9,7 @@ #include -static njs_variable_t *njs_variable_scope_add(njs_vm_t *vm, +static njs_variable_t *njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type); static njs_int_t njs_variable_reference_resolve(njs_vm_t *vm, njs_variable_reference_t *vr, njs_parser_scope_t *node_scope); @@ -18,12 +18,12 @@ static njs_variable_t *njs_variable_allo njs_variable_t * -njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id, - njs_variable_type_t type) +njs_variable_add(njs_parser_t *parser, njs_parser_scope_t *scope, + uintptr_t unique_id, njs_variable_type_t type) { njs_variable_t *var; - var = njs_variable_scope_add(vm, scope, unique_id, type); + var = njs_variable_scope_add(parser, scope, unique_id, type); if (njs_slow_path(var == NULL)) { return NULL; } @@ -33,7 +33,7 @@ njs_variable_add(njs_vm_t *vm, njs_parse do { scope = scope->parent; - var = njs_variable_scope_add(vm, scope, unique_id, type); + var = njs_variable_scope_add(parser, scope, unique_id, type); if (njs_slow_path(var == NULL)) { return NULL; } @@ -78,7 +78,7 @@ njs_variables_copy(njs_vm_t *vm, njs_rbt static njs_variable_t * -njs_variable_scope_add(njs_vm_t *vm, njs_parser_scope_t *scope, +njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type) { njs_variable_t *var; @@ -104,7 +104,7 @@ njs_variable_scope_add(njs_vm_t *vm, njs if (scope->type == NJS_SCOPE_GLOBAL) { - if (vm->options.module) { + if (parser->vm->options.module) { if (type == NJS_VARIABLE_FUNCTION || var->type == NJS_VARIABLE_FUNCTION) { @@ -116,12 +116,12 @@ njs_variable_scope_add(njs_vm_t *vm, njs return var; } - var = njs_variable_alloc(vm, unique_id, type); + var = njs_variable_alloc(parser->vm, unique_id, type); if (njs_slow_path(var == NULL)) { goto memory_error; } - var_node_new = njs_variable_node_alloc(vm, var, unique_id); + var_node_new = njs_variable_node_alloc(parser->vm, var, unique_id); if (njs_slow_path(var_node_new == NULL)) { goto memory_error; } @@ -132,7 +132,7 @@ njs_variable_scope_add(njs_vm_t *vm, njs memory_error: - njs_memory_error(vm); + njs_memory_error(parser->vm); return NULL; @@ -140,8 +140,7 @@ fail: entry = njs_lexer_entry(unique_id); - njs_parser_syntax_error(vm->parser, - "\"%V\" has already been declared", + njs_parser_syntax_error(parser, "\"%V\" has already been declared", &entry->name); return NULL; } diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_variable.h --- a/src/njs_variable.h Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_variable.h Wed Feb 24 14:48:20 2021 +0000 @@ -55,8 +55,8 @@ typedef struct { } njs_variable_node_t; -njs_variable_t *njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope, - uintptr_t unique_id, njs_variable_type_t type); +njs_variable_t *njs_variable_add(njs_parser_t *parser, + njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type); njs_int_t njs_variables_copy(njs_vm_t *vm, njs_rbtree_t *variables, njs_rbtree_t *prev_variables); njs_variable_t * njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_vm.c --- a/src/njs_vm.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_vm.c Wed Feb 24 14:48:20 2021 +0000 @@ -68,7 +68,6 @@ njs_vm_create(njs_vm_opt_t *options) vm->trace.level = NJS_LEVEL_TRACE; vm->trace.size = 2048; - vm->trace.handler = njs_parser_trace_handler; vm->trace.data = vm; njs_set_undefined(&vm->retval); @@ -113,66 +112,48 @@ njs_vm_destroy(njs_vm_t *vm) njs_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) { - njs_int_t ret; - njs_str_t ast; - njs_chb_t chain; - njs_lexer_t lexer; - njs_parser_t *parser, *prev; - njs_vm_code_t *code; - njs_generator_t generator; - njs_parser_scope_t *scope; - - if (vm->parser != NULL && !vm->options.accumulative) { - return NJS_ERROR; - } + njs_int_t ret; + njs_str_t ast; + njs_chb_t chain; + njs_lexer_t lexer; + njs_parser_t parser; + njs_vm_code_t *code; + njs_generator_t generator; if (vm->modules != NULL && vm->options.accumulative) { njs_module_reset(vm); } - parser = njs_mp_zalloc(vm->mem_pool, sizeof(njs_parser_t)); - if (njs_slow_path(parser == NULL)) { - return NJS_ERROR; - } - - prev = vm->parser; - vm->parser = parser; - ret = njs_lexer_init(vm, &lexer, &vm->options.file, *start, end); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - parser->vm = vm; - parser->lexer = &lexer; + njs_memzero(&parser, sizeof(njs_parser_t)); - njs_set_undefined(&vm->retval); + parser.lexer = &lexer; - ret = njs_parser(parser, prev); + ret = njs_parser(vm, &parser, vm->variables_hash); if (njs_slow_path(ret != NJS_OK)) { - goto fail; - } - - parser->lexer = NULL; - - scope = parser->scope; - - ret = njs_variables_scope_reference(vm, scope); - if (njs_slow_path(ret != NJS_OK)) { - goto fail; + return NJS_ERROR; } *start = lexer.start; + ret = njs_variables_scope_reference(vm, parser.scope); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + njs_memzero(&generator, sizeof(njs_generator_t)); - code = njs_generate_scope(vm, &generator, scope, &njs_entry_main); + code = njs_generate_scope(vm, &generator, parser.scope, &njs_entry_main); if (njs_slow_path(code == NULL)) { if (!njs_is_error(&vm->retval)) { njs_internal_error(vm, "njs_generate_scope() failed"); } - goto fail; + return NJS_ERROR; } vm->main_index = code - (njs_vm_code_t *) vm->codes->start; @@ -180,7 +161,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st vm->global_scope = generator.local_scope; vm->scope_size = generator.scope_size; - vm->variables_hash = &scope->variables; + vm->variables_hash = &parser.scope->variables; if (vm->options.init && !vm->options.accumulative) { ret = njs_vm_init(vm); @@ -195,7 +176,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st if (njs_slow_path(vm->options.ast)) { njs_chb_init(&chain, vm->mem_pool); - ret = njs_parser_serialize_ast(parser->node, &chain); + ret = njs_parser_serialize_ast(parser.node, &chain); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -210,13 +191,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st njs_mp_free(vm->mem_pool, ast.start); } - return ret; - -fail: - - vm->parser = prev; - - return NJS_ERROR; + return NJS_OK; } diff -r 4197cc28ea9c -r 1f22e9008cc3 src/njs_vm.h --- a/src/njs_vm.h Fri Feb 19 17:27:44 2021 +0000 +++ b/src/njs_vm.h Wed Feb 24 14:48:20 2021 +0000 @@ -218,7 +218,6 @@ struct njs_vm_s { size_t stack_size; njs_vm_shared_t *shared; - njs_parser_t *parser; njs_regex_context_t *regex_context; njs_regex_match_data_t *single_match_data; diff -r 4197cc28ea9c -r 1f22e9008cc3 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Feb 19 17:27:44 2021 +0000 +++ b/src/test/njs_unit_test.c Wed Feb 24 14:48:20 2021 +0000 @@ -12696,25 +12696,26 @@ static njs_unit_test_t njs_test[] = njs_str("1") }, { njs_str("var sum = new Function('a', 'b', 'return a + b');" - "sum(2, 4);"), + "sum(2, 4);"), njs_str("6") }, { njs_str("var sum = new Function('a, b', 'return a + b');" - "sum(2, 4);"), + "sum(2, 4);"), njs_str("6") }, { njs_str("var sum = new Function('a, b', 'c', 'return a + b + c');" - "sum(2, 4, 4);"), + "sum(2, 4, 4);"), njs_str("10") }, { njs_str("(new Function({ toString() { return '...a'; }}, { toString() { return 'return a;' }}))(1,2,3)"), njs_str("1,2,3") }, { njs_str("var x = 10; function foo() { var x = 20; return new Function('return x;'); }" - "var f = foo(); f()"), + "var f = foo(); f()"), njs_str("10") }, - { njs_str("var fn = (function() { return new Function('return this'); }).call({}), o = {}; fn.call(o) == o && fn.bind(o).call(this) == o"), + { njs_str("var fn = (function() { return new Function('return this'); }).call({}), o = {}; " + "fn.call(o) == o && fn.bind(o).call(this) == o"), njs_str("true") }, { njs_str("(new Function('return this'))() === globalThis"), @@ -12733,6 +12734,10 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = {}; (new Function('return this')).call(o) === o"), njs_str("true") }, + { njs_str("(new Function('function foo(){return 1}; return foo()'))();" + "foo"), + njs_str("ReferenceError: \"foo\" is not defined") }, + { njs_str("this.NN = {}; var f = Function('eval = 42;'); f()"), njs_str("SyntaxError: Identifier \"eval\" is forbidden as left-hand in assignment in runtime:1") }, @@ -20315,6 +20320,11 @@ static njs_unit_test_t njs_shell_test[] "Number.prototype.test" ENTER), njs_str("test") }, + { njs_str("try {(new Function('function foo(){return 1}; ()=>{}breakhere'))} catch (e) {}" ENTER + "foo()" ENTER), + njs_str("ReferenceError: \"foo\" is not defined\n" + " at main (:1)\n") }, + /* Error handling */ { njs_str("var a = ;" ENTER From xeioex at nginx.com Wed Feb 24 14:51:04 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 24 Feb 2021 14:51:04 +0000 Subject: [njs] Eliminating vm->main_index introduced in ea2ec4c3ed7d. Message-ID: details: https://hg.nginx.org/njs/rev/0efac7257447 branches: changeset: 1611:0efac7257447 user: Dmitry Volyntsev date: Wed Feb 24 14:50:14 2021 +0000 description: Eliminating vm->main_index introduced in ea2ec4c3ed7d. The vm->main_index was only needed for the disassembler in the accumulative mode. It was used to prevent from disassembling the code from the previous iterations in the CLI. The same result can be achieved without introducing the VM level field. diffstat: src/njs_disassembler.c | 12 ++++++++++-- src/njs_vm.c | 1 - src/njs_vm.h | 2 -- 3 files changed, 10 insertions(+), 5 deletions(-) diffs (46 lines): diff -r 1f22e9008cc3 -r 0efac7257447 src/njs_disassembler.c --- a/src/njs_disassembler.c Wed Feb 24 14:48:20 2021 +0000 +++ b/src/njs_disassembler.c Wed Feb 24 14:50:14 2021 +0000 @@ -146,8 +146,16 @@ njs_disassembler(njs_vm_t *vm) njs_vm_code_t *code; code = vm->codes->start; - code += vm->main_index; - n = vm->codes->items - vm->main_index; + n = vm->codes->items; + + while (n != 0) { + if (code->start == vm->start) { + break; + } + + code++; + n--; + } while (n != 0) { njs_printf("%V:%V\n", &code->file, &code->name); diff -r 1f22e9008cc3 -r 0efac7257447 src/njs_vm.c --- a/src/njs_vm.c Wed Feb 24 14:48:20 2021 +0000 +++ b/src/njs_vm.c Wed Feb 24 14:50:14 2021 +0000 @@ -156,7 +156,6 @@ njs_vm_compile(njs_vm_t *vm, u_char **st return NJS_ERROR; } - vm->main_index = code - (njs_vm_code_t *) vm->codes->start; vm->start = generator.code_start; vm->global_scope = generator.local_scope; vm->scope_size = generator.scope_size; diff -r 1f22e9008cc3 -r 0efac7257447 src/njs_vm.h --- a/src/njs_vm.h Wed Feb 24 14:48:20 2021 +0000 +++ b/src/njs_vm.h Wed Feb 24 14:50:14 2021 +0000 @@ -233,9 +233,7 @@ struct njs_vm_s { njs_object_t string_object; njs_object_t global_object; - njs_uint_t main_index; njs_arr_t *codes; /* of njs_vm_code_t */ - njs_arr_t *functions_name_cache; njs_trace_t trace; From xeioex at nginx.com Wed Feb 24 16:59:04 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 24 Feb 2021 16:59:04 +0000 Subject: [njs] Fixed compilation error with gcc-11. Message-ID: details: https://hg.nginx.org/njs/rev/804afbc89677 branches: changeset: 1612:804afbc89677 user: Dmitry Volyntsev date: Wed Feb 24 16:57:05 2021 +0000 description: Fixed compilation error with gcc-11. This closes #376 issue on Github. diffstat: src/njs_fs.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 0efac7257447 -r 804afbc89677 src/njs_fs.c --- a/src/njs_fs.c Wed Feb 24 14:50:14 2021 +0000 +++ b/src/njs_fs.c Wed Feb 24 16:57:05 2021 +0000 @@ -1373,8 +1373,8 @@ njs_fs_rmtree(njs_vm_t *vm, const char * static const char * -njs_fs_path(njs_vm_t *vm, char *storage, const njs_value_t *src, - const char *prop_name) +njs_fs_path(njs_vm_t *vm, char storage[NJS_MAX_PATH + 1], + const njs_value_t *src, const char *prop_name) { u_char *p; njs_str_t str; From ping.zhao at intel.com Thu Feb 25 06:59:15 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Thu, 25 Feb 2021 06:59:15 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <7463caa5-76d0-f6f8-e9b6-0c0b3fe1077c@nginx.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> Message-ID: Hi Mikhail, I tried with CentOS 8.1.1911 + fedora-kernel-5.10.10-200.fc33, and with your test steps & scripts: 1. Created 90k files on nvme SSD with each size 100KB. 2. Created separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx 3. Limit Nginx to 2GB: echo 2G > /sys/fs/cgroup/memory/nginx/memory.limit_in_bytes 4. Clear cache: echo 3 > /proc/sys/vm/drop_caches 5. Start nginx: cgexec -g memory:nginx 6. Tested with wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... Io_uring can achieved 1.9+GB/s usr sys idl wai stl| read writ| recv send| in out | int csw 1 2 97 0 0|1923M 0 |7369k 2136M| 0 0 | 263k 119k 1 2 97 0 0|1911M 0 |7329k 2123M| 0 0 | 262k 119k 1 2 97 0 0|1910M 3592k|7318k 2118M| 0 0 | 264k 117k 1 2 97 0 0|1923M 200k|7353k 2138M| 0 0 | 265k 118k 1 2 97 0 0|1929M 0 |7376k 2142M| 0 0 | 264k 118k 1 2 97 0 0|1924M 32k|7352k 2140M| 0 0 | 265k 118k 1 2 97 0 0|1913M 0 |7320k 2122M| 0 0 | 263k 117k 1 2 97 0 0|1921M 3544k|7336k 2132M| 0 0 | 264k 118k 1 2 97 0 0|1933M 0 |7353k 2146M| 0 0 | 264k 120k Libaio is 260+MB/s usr sys idl wai stl| read writ| recv send| in out | int csw 0 0 98 1 0| 267M 0 |1022k 293M| 0 0 | 41k 12k 0 0 98 1 0| 279M 740k|1093k 314M| 0 0 | 42k 12k 1 0 98 1 0| 268M 0 |1013k 294M| 0 0 | 41k 12k 0 0 98 1 0| 261M 0 |1002k 294M| 0 0 | 41k 12k 1 0 98 1 0| 285M 0 |1057k 310M| 0 0 | 43k 13k 0 0 98 1 0| 276M 4096B|1038k 307M| 0 0 | 42k 13k 0 0 98 1 0| 273M 780k|1019k 303M| 0 0 | 42k 12k 1 0 98 1 0| 275M 0 |1016k 305M| 0 0 | 42k 12k 0 0 98 1 0| 254M 0 | 976k 294M| 0 0 | 40k 12k 0 0 98 1 0| 265M 0 | 975k 293M| 0 0 | 41k 12k 0 0 98 1 0| 269M 0 | 976k 295M| 0 0 | 41k 12k Comparing with your dstat data that disk read keeps at 250M/s, is there anything locked the disk io bw? Regards, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Tuesday, February 9, 2021 9:31 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx 3. Limit memory to 80 Mb, for example: echo 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. For example, with 100kb files and 1 worker process: free -lh total used free shared buff/cache available Mem: 15Gi 212Mi 14Gi 13Mi 318Mi 14Gi dstat/libaio 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 dstat/io_uring 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 As you can see, libaio even faster a bit. 09.02.2021 11:36, Zhao, Ping ?????: > Hi Mikhail, > > The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. > > If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. > > memory > free -lh > total used free shared buff/cache available > Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi > > libaio: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 > 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 > 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 > 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 > 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 > 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 > 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 > 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 > > Io_uring: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 > 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 > 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 > 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 > 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 > > I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. > > Memory: > free -lh > total used free shared buff/cache available > Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi > > Libaio: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k > 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k > 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k > > Io_uring: > ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k > 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k > 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k > 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k > 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k > 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k > 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k > > Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Tuesday, February 9, 2021 1:17 AM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. > > I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. > > As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: > > a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. > > b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). > > I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? > > Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. > > Thanks in advance! > > 07.02.2021 05:16, Zhao, Ping ?????: >> Hi Mikhail, >> >> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >> >> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> sendfile 70MB/s 260MB/s 700MB/s >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> sendfile 250MB/s 900MB/s 1.6GB/s >> >> BR, >> Ping >> >> -----Original Message----- >> From: Zhao, Ping >> Sent: Friday, February 5, 2021 2:43 PM >> To: nginx-devel at nginx.org >> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Mikhail, >> >> Added 'sendfile on' & 'aio off' test result with previous table: >> >> Following is the test result with 100KB and 1MB: (4KB to be test) >> >> Nginx worker_processes 1: >> 4k 100k 1M >> Io_uring 220MB/s 1GB/s 1.3GB/s >> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >> sendfile tbt 260MB/s 700MB/s >> >> >> Nginx worker_processes 4: >> 4k 100k 1M >> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >> libaio 250MB/s 900MB/s 2.0GB/s >> sendfile tbt 900MB/s 1.6GB/s >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Mikhail Isachenkov >> Sent: Thursday, February 4, 2021 4:55 PM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> My test is much simpler than yours. I created >> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >> These files does not change during test. >> >> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >> >> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >> >> Thanks in advance! >> >> 04.02.2021 10:08, Zhao, Ping ?????: >>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>> >>> -----Original Message----- >>> From: Zhao, Ping >>> Sent: Thursday, February 4, 2021 10:33 AM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Mikhail, >>> >>> I didn't see this error in my log. Following is my OS/Kernel: >>> CentOS: 8.1.1911 >>> Kernel: 5.7.19 >>> Liburing: liburing-1.0.7-3.el8.x86_64, >>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>> >>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>> >>> My nginx reported this error before: >>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>> Which is fixed by my 2nd patch(Jan 25) already. >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Wednesday, February 3, 2021 10:11 PM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Ping Zhao, >>> >>> When I try to repeat this test, I've got a huge number of these errors: >>> >>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>> "/usr/local/html/64746" failed (11: Resource temporarily >>> unavailable) while sending response to client, client: 127.0.0.1, server: >>> localhost, >>> request: "GET /64746 HTTP/1.1", host: "localhost" >>> >>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>> >>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>> >>> 25.01.2021 11:24, Zhao, Ping ?????: >>>> Hello, add a small update to correct the length when part of request already received in previous. >>>> This case may happen when using io_uring and throughput increased. >>>> >>>> # HG changeset patch >>>> # User Ping Zhao # Date 1611566408 18000 >>>> # Mon Jan 25 04:20:08 2021 -0500 >>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>> Correct length calculation when part of request received. >>>> >>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>> @@ -531,6 +531,14 @@ >>>> >>>> size = ngx_buf_size(src); >>>> size = ngx_min(size, dst->end - dst->pos); >>>> +#if (NGX_HAVE_FILE_IOURING) >>>> + /* >>>> + * check if already received part of the request in previous, >>>> + * calculate the remain length >>>> + */ >>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>> + size = size - (dst->last - dst->pos); #endif >>>> >>>> sendfile = ctx->sendfile && !ctx->directio; >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Zhao, Ping >>>> Sent: Thursday, January 21, 2021 9:44 AM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Vladimir, >>>> >>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>> >>>> user nobody; >>>> daemon off; >>>> worker_processes 1; >>>> error_log error.log ; >>>> events { >>>> worker_connections 65535; >>>> use epoll; >>>> } >>>> >>>> http { >>>> include mime.types; >>>> default_type application/octet-stream; >>>> access_log on; >>>> aio on; >>>> sendfile off; >>>> directio 2k; >>>> >>>> # Cache Configurations >>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>> >>>> >>>> To better measure the disk io performance data, I do the following steps: >>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>> echo 2G > memory.limit_in_bytes >>>> use ' cgexec -g memory:nginx' to start Nginx. >>>> >>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>> >>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>> >>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>> extract the cache files in nvme cache disk. Use iostat to track the >>>> io data. The data should be align with NIC bw since all data should >>>> be from cache disk.(need exclude memory as cache storage impact) >>>> >>>> Following is the test result: >>>> >>>> Nginx worker_processes 1: >>>> 4k 100k 1M >>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>> >>>> >>>> Nginx worker_processes 4: >>>> 4k 100k 1M >>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>> libaio 250MB/s 900MB/s 2.0GB/s >>>> >>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>> >>>> Regards, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Vladimir Homutov >>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>> It depends on if disk io is the performance hot spot or not. If >>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB length >>>>> 1 Nginx thread it's hard to see performance difference because >>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>> performance bottle neck, both libaio and io_uring have the same >>>>> performance. If you increase request size or Nginx threads number, >>>>> for example 1MB length or Nginx thread number 4. In this case, >>>>> disk io became the performance bottle neck, you will see io_uring performance improvement. >>>> >>>> Can you please provide full test results with specific nginx configuration? >>>> >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From mikhail.isachenkov at nginx.com Thu Feb 25 11:01:04 2021 From: mikhail.isachenkov at nginx.com (Mikhail Isachenkov) Date: Thu, 25 Feb 2021 14:01:04 +0300 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> Message-ID: <3d737faa-a8f6-ae8f-fce3-54089fecd1c3@nginx.com> Hi Zhao Ping, Looks like general-purpose AWS EC2 instances does not optimized to high random I/O even with NVMe SSD; I'll try to test it again on bare-metal, storage-optimized instance. How many 4k random iops your storage can handle? (I'd like to run test on the instance with the same storage performance, according to https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/storage-optimized-instances.html#i2-instances-diskperf). Thanks in advance! 25.02.2021 09:59, Zhao, Ping ?????: > Hi Mikhail, > > I tried with CentOS 8.1.1911 + fedora-kernel-5.10.10-200.fc33, and with your test steps & scripts: > > 1. Created 90k files on nvme SSD with each size 100KB. > 2. Created separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx > 3. Limit Nginx to 2GB: echo 2G > /sys/fs/cgroup/memory/nginx/memory.limit_in_bytes > 4. Clear cache: echo 3 > /proc/sys/vm/drop_caches > 5. Start nginx: cgexec -g memory:nginx > 6. Tested with wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... > > Io_uring can achieved 1.9+GB/s > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 2 97 0 0|1923M 0 |7369k 2136M| 0 0 | 263k 119k > 1 2 97 0 0|1911M 0 |7329k 2123M| 0 0 | 262k 119k > 1 2 97 0 0|1910M 3592k|7318k 2118M| 0 0 | 264k 117k > 1 2 97 0 0|1923M 200k|7353k 2138M| 0 0 | 265k 118k > 1 2 97 0 0|1929M 0 |7376k 2142M| 0 0 | 264k 118k > 1 2 97 0 0|1924M 32k|7352k 2140M| 0 0 | 265k 118k > 1 2 97 0 0|1913M 0 |7320k 2122M| 0 0 | 263k 117k > 1 2 97 0 0|1921M 3544k|7336k 2132M| 0 0 | 264k 118k > 1 2 97 0 0|1933M 0 |7353k 2146M| 0 0 | 264k 120k > > Libaio is 260+MB/s > usr sys idl wai stl| read writ| recv send| in out | int csw > 0 0 98 1 0| 267M 0 |1022k 293M| 0 0 | 41k 12k > 0 0 98 1 0| 279M 740k|1093k 314M| 0 0 | 42k 12k > 1 0 98 1 0| 268M 0 |1013k 294M| 0 0 | 41k 12k > 0 0 98 1 0| 261M 0 |1002k 294M| 0 0 | 41k 12k > 1 0 98 1 0| 285M 0 |1057k 310M| 0 0 | 43k 13k > 0 0 98 1 0| 276M 4096B|1038k 307M| 0 0 | 42k 13k > 0 0 98 1 0| 273M 780k|1019k 303M| 0 0 | 42k 12k > 1 0 98 1 0| 275M 0 |1016k 305M| 0 0 | 42k 12k > 0 0 98 1 0| 254M 0 | 976k 294M| 0 0 | 40k 12k > 0 0 98 1 0| 265M 0 | 975k 293M| 0 0 | 41k 12k > 0 0 98 1 0| 269M 0 | 976k 295M| 0 0 | 41k 12k > > Comparing with your dstat data that disk read keeps at 250M/s, is there anything locked the disk io bw? > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail Isachenkov > Sent: Tuesday, February 9, 2021 9:31 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. > > 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. > 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx 3. Limit memory to 80 Mb, for example: echo > 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes > 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... > > I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. > > For example, with 100kb files and 1 worker process: > > free -lh > total used free shared buff/cache > available > Mem: 15Gi 212Mi 14Gi 13Mi 318Mi > 14Gi > > dstat/libaio > 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 > 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 > 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 > 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 > 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 > 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 > 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 > 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 > 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 > dstat/io_uring > 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k > 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 > 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k > 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 > 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k > 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 > 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 > 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 > 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 > > As you can see, libaio even faster a bit. > > 09.02.2021 11:36, Zhao, Ping ?????: >> Hi Mikhail, >> >> The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. >> >> If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. >> >> memory >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi >> >> libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 >> 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 >> 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 >> 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 >> 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 >> 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 >> 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 >> 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 >> 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 >> 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 >> 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 >> 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 >> >> I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. >> >> Memory: >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi >> >> Libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k >> 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k >> 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k >> 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k >> 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k >> 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k >> 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k >> 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k >> >> Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. >> >> BR, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Mikhail >> Isachenkov >> Sent: Tuesday, February 9, 2021 1:17 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. >> >> I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. >> >> As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: >> >> a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. >> >> b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). >> >> I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? >> >> Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. >> >> Thanks in advance! >> >> 07.02.2021 05:16, Zhao, Ping ?????: >>> Hi Mikhail, >>> >>> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >>> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >>> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >>> >>> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile 70MB/s 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile 250MB/s 900MB/s 1.6GB/s >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: Zhao, Ping >>> Sent: Friday, February 5, 2021 2:43 PM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Mikhail, >>> >>> Added 'sendfile on' & 'aio off' test result with previous table: >>> >>> Following is the test result with 100KB and 1MB: (4KB to be test) >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile tbt 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile tbt 900MB/s 1.6GB/s >>> >>> Regards, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Thursday, February 4, 2021 4:55 PM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Zhao Ping, >>> >>> My test is much simpler than yours. I created >>> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >>> These files does not change during test. >>> >>> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >>> >>> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >>> >>> Thanks in advance! >>> >>> 04.02.2021 10:08, Zhao, Ping ?????: >>>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>>> >>>> -----Original Message----- >>>> From: Zhao, Ping >>>> Sent: Thursday, February 4, 2021 10:33 AM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Mikhail, >>>> >>>> I didn't see this error in my log. Following is my OS/Kernel: >>>> CentOS: 8.1.1911 >>>> Kernel: 5.7.19 >>>> Liburing: liburing-1.0.7-3.el8.x86_64, >>>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>>> >>>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>>> >>>> My nginx reported this error before: >>>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>>> Which is fixed by my 2nd patch(Jan 25) already. >>>> >>>> BR, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Mikhail Isachenkov >>>> Sent: Wednesday, February 3, 2021 10:11 PM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Ping Zhao, >>>> >>>> When I try to repeat this test, I've got a huge number of these errors: >>>> >>>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>>> "/usr/local/html/64746" failed (11: Resource temporarily >>>> unavailable) while sending response to client, client: 127.0.0.1, server: >>>> localhost, >>>> request: "GET /64746 HTTP/1.1", host: "localhost" >>>> >>>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>>> >>>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>>> >>>> 25.01.2021 11:24, Zhao, Ping ?????: >>>>> Hello, add a small update to correct the length when part of request already received in previous. >>>>> This case may happen when using io_uring and throughput increased. >>>>> >>>>> # HG changeset patch >>>>> # User Ping Zhao # Date 1611566408 18000 >>>>> # Mon Jan 25 04:20:08 2021 -0500 >>>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>>> Correct length calculation when part of request received. >>>>> >>>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>>> @@ -531,6 +531,14 @@ >>>>> >>>>> size = ngx_buf_size(src); >>>>> size = ngx_min(size, dst->end - dst->pos); >>>>> +#if (NGX_HAVE_FILE_IOURING) >>>>> + /* >>>>> + * check if already received part of the request in previous, >>>>> + * calculate the remain length >>>>> + */ >>>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>>> + size = size - (dst->last - dst->pos); #endif >>>>> >>>>> sendfile = ctx->sendfile && !ctx->directio; >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Zhao, Ping >>>>> Sent: Thursday, January 21, 2021 9:44 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Vladimir, >>>>> >>>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>>> >>>>> user nobody; >>>>> daemon off; >>>>> worker_processes 1; >>>>> error_log error.log ; >>>>> events { >>>>> worker_connections 65535; >>>>> use epoll; >>>>> } >>>>> >>>>> http { >>>>> include mime.types; >>>>> default_type application/octet-stream; >>>>> access_log on; >>>>> aio on; >>>>> sendfile off; >>>>> directio 2k; >>>>> >>>>> # Cache Configurations >>>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>>> >>>>> >>>>> To better measure the disk io performance data, I do the following steps: >>>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>>> echo 2G > memory.limit_in_bytes >>>>> use ' cgexec -g memory:nginx' to start Nginx. >>>>> >>>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>>> >>>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>>> >>>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>>> extract the cache files in nvme cache disk. Use iostat to track the >>>>> io data. The data should be align with NIC bw since all data should >>>>> be from cache disk.(need exclude memory as cache storage impact) >>>>> >>>>> Following is the test result: >>>>> >>>>> Nginx worker_processes 1: >>>>> 4k 100k 1M >>>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>>> >>>>> >>>>> Nginx worker_processes 4: >>>>> 4k 100k 1M >>>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>>> libaio 250MB/s 900MB/s 2.0GB/s >>>>> >>>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>>> >>>>> Regards, >>>>> Ping >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Vladimir Homutov >>>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>>> It depends on if disk io is the performance hot spot or not. If >>>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB length >>>>>> 1 Nginx thread it's hard to see performance difference because >>>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>>> performance bottle neck, both libaio and io_uring have the same >>>>>> performance. If you increase request size or Nginx threads number, >>>>>> for example 1MB length or Nginx thread number 4. In this case, >>>>>> disk io became the performance bottle neck, you will see io_uring performance improvement. >>>>> >>>>> Can you please provide full test results with specific nginx configuration? >>>>> >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> >>>> >>>> -- >>>> Best regards, >>>> Mikhail Isachenkov >>>> NGINX Professional Services >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From xeioex at nginx.com Thu Feb 25 16:14:24 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 25 Feb 2021 16:14:24 +0000 Subject: [njs] Fixed for-in iteration of typed array values. Message-ID: details: https://hg.nginx.org/njs/rev/67b45ebbb6e4 branches: changeset: 1613:67b45ebbb6e4 user: Artem S. Povalyukhin date: Thu Feb 25 10:06:18 2021 +0300 description: Fixed for-in iteration of typed array values. diffstat: src/njs_object.c | 6 ++++++ src/test/njs_unit_test.c | 3 +++ 2 files changed, 9 insertions(+), 0 deletions(-) diffs (29 lines): diff -r 804afbc89677 -r 67b45ebbb6e4 src/njs_object.c --- a/src/njs_object.c Wed Feb 24 16:57:05 2021 +0000 +++ b/src/njs_object.c Thu Feb 25 10:06:18 2021 +0300 @@ -444,6 +444,12 @@ njs_object_enumerate_value(njs_vm_t *vm, kind); break; + case NJS_TYPED_ARRAY: + ret = njs_object_enumerate_typed_array(vm, + (njs_typed_array_t *) object, + items, kind); + break; + case NJS_OBJECT_STRING: obj_val = (njs_object_value_t *) object; diff -r 804afbc89677 -r 67b45ebbb6e4 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Feb 24 16:57:05 2021 +0000 +++ b/src/test/njs_unit_test.c Thu Feb 25 10:06:18 2021 +0300 @@ -2834,6 +2834,9 @@ static njs_unit_test_t njs_test[] = "for (var a in o) {arr.push(a)}; arr"), njs_str("b") }, + { njs_str("var a = []; for (var k in new Uint8Array([1,2,3])) { a.push(k); }; a"), + njs_str("0,1,2") }, + /* switch. */ { njs_str("switch"), From mdounin at mdounin.ru Thu Feb 25 20:47:53 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 25 Feb 2021 20:47:53 +0000 Subject: [nginx] Contrib: vim syntax, default highlighting (ticket #2141). Message-ID: details: https://hg.nginx.org/nginx/rev/dea93b6dce94 branches: changeset: 7782:dea93b6dce94 user: Maxim Dounin date: Thu Feb 25 23:42:25 2021 +0300 description: Contrib: vim syntax, default highlighting (ticket #2141). Using default highlighting makes it possible to easily overrule highlighting specified in the syntax file, see ":highlight-default" in vim help for details. diffstat: contrib/vim/syntax/nginx.vim | 38 +++++++++++++++++++------------------- 1 files changed, 19 insertions(+), 19 deletions(-) diffs (49 lines): diff -r 51e6a665523c -r dea93b6dce94 contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Sat Feb 20 18:03:04 2021 +0300 +++ b/contrib/vim/syntax/nginx.vim Thu Feb 25 23:42:25 2021 +0300 @@ -2414,26 +2414,26 @@ syn keyword ngxDirectiveThirdParty conta " highlight -hi link ngxComment Comment -hi link ngxParamComment Comment -hi link ngxListenComment Comment -hi link ngxVariable Identifier -hi link ngxVariableString PreProc -hi link ngxString String -hi link ngxListenString String +hi def link ngxComment Comment +hi def link ngxParamComment Comment +hi def link ngxListenComment Comment +hi def link ngxVariable Identifier +hi def link ngxVariableString PreProc +hi def link ngxString String +hi def link ngxListenString String -hi link ngxBoolean Boolean -hi link ngxDirectiveBlock Statement -hi link ngxDirectiveImportant Type -hi link ngxDirectiveListen Type -hi link ngxDirectiveControl Keyword -hi link ngxDirectiveError Constant -hi link ngxDirectiveDeprecated Error -hi link ngxDirective Identifier -hi link ngxDirectiveThirdParty Special -hi link ngxDirectiveThirdPartyDeprecated Error +hi def link ngxBoolean Boolean +hi def link ngxDirectiveBlock Statement +hi def link ngxDirectiveImportant Type +hi def link ngxDirectiveListen Type +hi def link ngxDirectiveControl Keyword +hi def link ngxDirectiveError Constant +hi def link ngxDirectiveDeprecated Error +hi def link ngxDirective Identifier +hi def link ngxDirectiveThirdParty Special +hi def link ngxDirectiveThirdPartyDeprecated Error -hi link ngxListenOptions Keyword -hi link ngxListenOptionsDeprecated Error +hi def link ngxListenOptions Keyword +hi def link ngxListenOptionsDeprecated Error let b:current_syntax = "nginx" From ping.zhao at intel.com Fri Feb 26 01:22:03 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Fri, 26 Feb 2021 01:22:03 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <3d737faa-a8f6-ae8f-fce3-54089fecd1c3@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> <3d737faa-a8f6-ae8f-fce3-54089fecd1c3@nginx.com> Message-ID: Hi Mikhail, My Nvme SSD reports 562k IOPS with bs 4k, 128 depth using io_uring. ./fio -name=fiotest -filename=/dev/nvme2n1 -iodepth=128 -thread -rw=randread -ioengine=io_uring -sqthread_poll=1 -direct=1 -bs=4k -size=10G -numjobs=1 -runtime=600 -group_reporting Jobs: 1 (f=1): [r(1)][100.0%][r=2173MiB/s][r=556k IOPS][eta 00m:00s] fiotest: (groupid=0, jobs=1): err= 0: pid=23828: Fri Feb 26 03:55:40 2021 read: IOPS=562k, BW=2196MiB/s (2303MB/s)(10.0GiB/4663msec) BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Thursday, February 25, 2021 7:01 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, Looks like general-purpose AWS EC2 instances does not optimized to high random I/O even with NVMe SSD; I'll try to test it again on bare-metal, storage-optimized instance. How many 4k random iops your storage can handle? (I'd like to run test on the instance with the same storage performance, according to https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/storage-optimized-instances.html#i2-instances-diskperf). Thanks in advance! 25.02.2021 09:59, Zhao, Ping ?????: > Hi Mikhail, > > I tried with CentOS 8.1.1911 + fedora-kernel-5.10.10-200.fc33, and with your test steps & scripts: > > 1. Created 90k files on nvme SSD with each size 100KB. > 2. Created separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx > 3. Limit Nginx to 2GB: echo 2G > > /sys/fs/cgroup/memory/nginx/memory.limit_in_bytes > 4. Clear cache: echo 3 > /proc/sys/vm/drop_caches 5. Start nginx: > cgexec -g memory:nginx 6. Tested with wrk on client: ./wrk -d 30 -t > 100 -c 1000 -s add_random.lua http://... > > Io_uring can achieved 1.9+GB/s > usr sys idl wai stl| read writ| recv send| in out | int csw > 1 2 97 0 0|1923M 0 |7369k 2136M| 0 0 | 263k 119k > 1 2 97 0 0|1911M 0 |7329k 2123M| 0 0 | 262k 119k > 1 2 97 0 0|1910M 3592k|7318k 2118M| 0 0 | 264k 117k > 1 2 97 0 0|1923M 200k|7353k 2138M| 0 0 | 265k 118k > 1 2 97 0 0|1929M 0 |7376k 2142M| 0 0 | 264k 118k > 1 2 97 0 0|1924M 32k|7352k 2140M| 0 0 | 265k 118k > 1 2 97 0 0|1913M 0 |7320k 2122M| 0 0 | 263k 117k > 1 2 97 0 0|1921M 3544k|7336k 2132M| 0 0 | 264k 118k > 1 2 97 0 0|1933M 0 |7353k 2146M| 0 0 | 264k 120k > > Libaio is 260+MB/s > usr sys idl wai stl| read writ| recv send| in out | int csw > 0 0 98 1 0| 267M 0 |1022k 293M| 0 0 | 41k 12k > 0 0 98 1 0| 279M 740k|1093k 314M| 0 0 | 42k 12k > 1 0 98 1 0| 268M 0 |1013k 294M| 0 0 | 41k 12k > 0 0 98 1 0| 261M 0 |1002k 294M| 0 0 | 41k 12k > 1 0 98 1 0| 285M 0 |1057k 310M| 0 0 | 43k 13k > 0 0 98 1 0| 276M 4096B|1038k 307M| 0 0 | 42k 13k > 0 0 98 1 0| 273M 780k|1019k 303M| 0 0 | 42k 12k > 1 0 98 1 0| 275M 0 |1016k 305M| 0 0 | 42k 12k > 0 0 98 1 0| 254M 0 | 976k 294M| 0 0 | 40k 12k > 0 0 98 1 0| 265M 0 | 975k 293M| 0 0 | 41k 12k > 0 0 98 1 0| 269M 0 | 976k 295M| 0 0 | 41k 12k > > Comparing with your dstat data that disk read keeps at 250M/s, is there anything locked the disk io bw? > > Regards, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Tuesday, February 9, 2021 9:31 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. > > 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. > 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx > 3. Limit memory to 80 Mb, for example: echo > 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes > 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... > > I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. > > For example, with 100kb files and 1 worker process: > > free -lh > total used free shared buff/cache > available > Mem: 15Gi 212Mi 14Gi 13Mi 318Mi > 14Gi > > dstat/libaio > 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 > 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 > 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 > 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 > 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 > 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 > 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 > 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 > 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 > dstat/io_uring > 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k > 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 > 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k > 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 > 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k > 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 > 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 > 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 > 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 > > As you can see, libaio even faster a bit. > > 09.02.2021 11:36, Zhao, Ping ?????: >> Hi Mikhail, >> >> The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. >> >> If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. >> >> memory >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi >> >> libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 >> 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 >> 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 >> 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 >> 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 >> 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 >> 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 >> 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 >> 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 >> 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 >> 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 >> 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 >> >> I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. >> >> Memory: >> free -lh >> total used free shared buff/cache available >> Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi >> >> Libaio: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k >> 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k >> 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k >> >> Io_uring: >> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k >> 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k >> 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k >> 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k >> 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k >> 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k >> 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k >> >> Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. >> >> BR, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Mikhail Isachenkov >> Sent: Tuesday, February 9, 2021 1:17 AM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. >> >> I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. >> >> As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: >> >> a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. >> >> b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). >> >> I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? >> >> Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. >> >> Thanks in advance! >> >> 07.02.2021 05:16, Zhao, Ping ?????: >>> Hi Mikhail, >>> >>> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >>> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >>> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >>> >>> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile 70MB/s 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile 250MB/s 900MB/s 1.6GB/s >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: Zhao, Ping >>> Sent: Friday, February 5, 2021 2:43 PM >>> To: nginx-devel at nginx.org >>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Mikhail, >>> >>> Added 'sendfile on' & 'aio off' test result with previous table: >>> >>> Following is the test result with 100KB and 1MB: (4KB to be test) >>> >>> Nginx worker_processes 1: >>> 4k 100k 1M >>> Io_uring 220MB/s 1GB/s 1.3GB/s >>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>> sendfile tbt 260MB/s 700MB/s >>> >>> >>> Nginx worker_processes 4: >>> 4k 100k 1M >>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>> libaio 250MB/s 900MB/s 2.0GB/s >>> sendfile tbt 900MB/s 1.6GB/s >>> >>> Regards, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Thursday, February 4, 2021 4:55 PM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Zhao Ping, >>> >>> My test is much simpler than yours. I created >>> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >>> These files does not change during test. >>> >>> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >>> >>> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >>> >>> Thanks in advance! >>> >>> 04.02.2021 10:08, Zhao, Ping ?????: >>>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>>> >>>> -----Original Message----- >>>> From: Zhao, Ping >>>> Sent: Thursday, February 4, 2021 10:33 AM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Mikhail, >>>> >>>> I didn't see this error in my log. Following is my OS/Kernel: >>>> CentOS: 8.1.1911 >>>> Kernel: 5.7.19 >>>> Liburing: liburing-1.0.7-3.el8.x86_64, >>>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>>> >>>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>>> >>>> My nginx reported this error before: >>>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>>> Which is fixed by my 2nd patch(Jan 25) already. >>>> >>>> BR, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Mikhail Isachenkov >>>> Sent: Wednesday, February 3, 2021 10:11 PM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Ping Zhao, >>>> >>>> When I try to repeat this test, I've got a huge number of these errors: >>>> >>>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>>> "/usr/local/html/64746" failed (11: Resource temporarily >>>> unavailable) while sending response to client, client: 127.0.0.1, server: >>>> localhost, >>>> request: "GET /64746 HTTP/1.1", host: "localhost" >>>> >>>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>>> >>>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>>> >>>> 25.01.2021 11:24, Zhao, Ping ?????: >>>>> Hello, add a small update to correct the length when part of request already received in previous. >>>>> This case may happen when using io_uring and throughput increased. >>>>> >>>>> # HG changeset patch >>>>> # User Ping Zhao # Date 1611566408 18000 >>>>> # Mon Jan 25 04:20:08 2021 -0500 >>>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>>> Correct length calculation when part of request received. >>>>> >>>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>>> @@ -531,6 +531,14 @@ >>>>> >>>>> size = ngx_buf_size(src); >>>>> size = ngx_min(size, dst->end - dst->pos); >>>>> +#if (NGX_HAVE_FILE_IOURING) >>>>> + /* >>>>> + * check if already received part of the request in previous, >>>>> + * calculate the remain length >>>>> + */ >>>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>>> + size = size - (dst->last - dst->pos); #endif >>>>> >>>>> sendfile = ctx->sendfile && !ctx->directio; >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Zhao, Ping >>>>> Sent: Thursday, January 21, 2021 9:44 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Vladimir, >>>>> >>>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>>> >>>>> user nobody; >>>>> daemon off; >>>>> worker_processes 1; >>>>> error_log error.log ; >>>>> events { >>>>> worker_connections 65535; >>>>> use epoll; >>>>> } >>>>> >>>>> http { >>>>> include mime.types; >>>>> default_type application/octet-stream; >>>>> access_log on; >>>>> aio on; >>>>> sendfile off; >>>>> directio 2k; >>>>> >>>>> # Cache Configurations >>>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>>> >>>>> >>>>> To better measure the disk io performance data, I do the following steps: >>>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>>> echo 2G > memory.limit_in_bytes >>>>> use ' cgexec -g memory:nginx' to start Nginx. >>>>> >>>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>>> >>>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>>> >>>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>>> extract the cache files in nvme cache disk. Use iostat to track >>>>> the io data. The data should be align with NIC bw since all data >>>>> should be from cache disk.(need exclude memory as cache storage >>>>> impact) >>>>> >>>>> Following is the test result: >>>>> >>>>> Nginx worker_processes 1: >>>>> 4k 100k 1M >>>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>>> >>>>> >>>>> Nginx worker_processes 4: >>>>> 4k 100k 1M >>>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>>> libaio 250MB/s 900MB/s 2.0GB/s >>>>> >>>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>>> >>>>> Regards, >>>>> Ping >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Vladimir Homutov >>>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>>> It depends on if disk io is the performance hot spot or not. If >>>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB >>>>>> length >>>>>> 1 Nginx thread it's hard to see performance difference because >>>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>>> performance bottle neck, both libaio and io_uring have the same >>>>>> performance. If you increase request size or Nginx threads >>>>>> number, for example 1MB length or Nginx thread number 4. In this >>>>>> case, disk io became the performance bottle neck, you will see io_uring performance improvement. >>>>> >>>>> Can you please provide full test results with specific nginx configuration? >>>>> >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> >>>> >>>> -- >>>> Best regards, >>>> Mikhail Isachenkov >>>> NGINX Professional Services >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From mikhail.isachenkov at nginx.com Fri Feb 26 08:41:10 2021 From: mikhail.isachenkov at nginx.com (Mikhail Isachenkov) Date: Fri, 26 Feb 2021 11:41:10 +0300 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> <3d737faa-a8f6-ae8f-fce3-54089fecd1c3@nginx.com> Message-ID: <89fb913c-1262-3419-88a3-feaad6f43deb@nginx.com> Hi Zhao Ping, I created i3en.6xlarge instance, 2 SSDs with 250k iops each (in raid0) and reproduced your results. Please find dstat output below. 1 worker, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 4 4 92 0 0|1412M 0 |5742k 1484M| 0 0 | 244k 87k 1 worker, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 1 1 95 3 0| 276M 0 |1386k 289M| 0 0 | 50k 8961 4 workers, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 6 6 18 70 0|1349M 0 |7240k 1445M| 0 0 | 296k 120k 4 workers, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 3 2 82 13 0| 890M 0 |3570k 931M| 0 0 | 139k 31k I ran test on i3.metal instance too (with 8 SSD in raid0), results are different but io_uring still faster: 1 worker, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 1 2 97 0 0|1372M 0 |5845k 1442M| 0 0 | 168k 51k 1 worker, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 1 1 98 0 0| 972M 20k|4083k 1023M| 0 0 | 126k 2014 4 workers, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 3 4 92 0 0|2211M 0 |9314k 2346M| 0 0 | 251k 198k 4 workers, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 3 3 94 0 0|1867M 0 | 10M 1995M| 0 0 | 220k 38k There is no difference between libaio and io_uring with a large number of worker processes (>=12). 26.02.2021 04:22, Zhao, Ping ?????: > Hi Mikhail, > > My Nvme SSD reports 562k IOPS with bs 4k, 128 depth using io_uring. > > ./fio -name=fiotest -filename=/dev/nvme2n1 -iodepth=128 -thread -rw=randread -ioengine=io_uring -sqthread_poll=1 -direct=1 -bs=4k -size=10G -numjobs=1 -runtime=600 -group_reporting > > Jobs: 1 (f=1): [r(1)][100.0%][r=2173MiB/s][r=556k IOPS][eta 00m:00s] > fiotest: (groupid=0, jobs=1): err= 0: pid=23828: Fri Feb 26 03:55:40 2021 > read: IOPS=562k, BW=2196MiB/s (2303MB/s)(10.0GiB/4663msec) > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail Isachenkov > Sent: Thursday, February 25, 2021 7:01 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > Looks like general-purpose AWS EC2 instances does not optimized to high random I/O even with NVMe SSD; I'll try to test it again on bare-metal, storage-optimized instance. > > How many 4k random iops your storage can handle? (I'd like to run test on the instance with the same storage performance, according to https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/storage-optimized-instances.html#i2-instances-diskperf). > > Thanks in advance! > > 25.02.2021 09:59, Zhao, Ping ?????: >> Hi Mikhail, >> >> I tried with CentOS 8.1.1911 + fedora-kernel-5.10.10-200.fc33, and with your test steps & scripts: >> >> 1. Created 90k files on nvme SSD with each size 100KB. >> 2. Created separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx >> 3. Limit Nginx to 2GB: echo 2G > >> /sys/fs/cgroup/memory/nginx/memory.limit_in_bytes >> 4. Clear cache: echo 3 > /proc/sys/vm/drop_caches 5. Start nginx: >> cgexec -g memory:nginx 6. Tested with wrk on client: ./wrk -d 30 -t >> 100 -c 1000 -s add_random.lua http://... >> >> Io_uring can achieved 1.9+GB/s >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 2 97 0 0|1923M 0 |7369k 2136M| 0 0 | 263k 119k >> 1 2 97 0 0|1911M 0 |7329k 2123M| 0 0 | 262k 119k >> 1 2 97 0 0|1910M 3592k|7318k 2118M| 0 0 | 264k 117k >> 1 2 97 0 0|1923M 200k|7353k 2138M| 0 0 | 265k 118k >> 1 2 97 0 0|1929M 0 |7376k 2142M| 0 0 | 264k 118k >> 1 2 97 0 0|1924M 32k|7352k 2140M| 0 0 | 265k 118k >> 1 2 97 0 0|1913M 0 |7320k 2122M| 0 0 | 263k 117k >> 1 2 97 0 0|1921M 3544k|7336k 2132M| 0 0 | 264k 118k >> 1 2 97 0 0|1933M 0 |7353k 2146M| 0 0 | 264k 120k >> >> Libaio is 260+MB/s >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 0 0 98 1 0| 267M 0 |1022k 293M| 0 0 | 41k 12k >> 0 0 98 1 0| 279M 740k|1093k 314M| 0 0 | 42k 12k >> 1 0 98 1 0| 268M 0 |1013k 294M| 0 0 | 41k 12k >> 0 0 98 1 0| 261M 0 |1002k 294M| 0 0 | 41k 12k >> 1 0 98 1 0| 285M 0 |1057k 310M| 0 0 | 43k 13k >> 0 0 98 1 0| 276M 4096B|1038k 307M| 0 0 | 42k 13k >> 0 0 98 1 0| 273M 780k|1019k 303M| 0 0 | 42k 12k >> 1 0 98 1 0| 275M 0 |1016k 305M| 0 0 | 42k 12k >> 0 0 98 1 0| 254M 0 | 976k 294M| 0 0 | 40k 12k >> 0 0 98 1 0| 265M 0 | 975k 293M| 0 0 | 41k 12k >> 0 0 98 1 0| 269M 0 | 976k 295M| 0 0 | 41k 12k >> >> Comparing with your dstat data that disk read keeps at 250M/s, is there anything locked the disk io bw? >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of Mikhail >> Isachenkov >> Sent: Tuesday, February 9, 2021 9:31 PM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. >> >> 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. >> 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx >> 3. Limit memory to 80 Mb, for example: echo >> 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes >> 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... >> >> I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. >> >> For example, with 100kb files and 1 worker process: >> >> free -lh >> total used free shared buff/cache >> available >> Mem: 15Gi 212Mi 14Gi 13Mi 318Mi >> 14Gi >> >> dstat/libaio >> 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 >> 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 >> 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 >> 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 >> 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 >> 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 >> 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 >> 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 >> 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 >> dstat/io_uring >> 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k >> 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 >> 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k >> 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 >> 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k >> 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 >> 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 >> 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 >> 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 >> >> As you can see, libaio even faster a bit. >> >> 09.02.2021 11:36, Zhao, Ping ?????: >>> Hi Mikhail, >>> >>> The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. >>> >>> If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. >>> >>> memory >>> free -lh >>> total used free shared buff/cache available >>> Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi >>> >>> libaio: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 >>> 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 >>> 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 >>> 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 >>> 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 >>> 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 >>> 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 >>> 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 >>> >>> Io_uring: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 >>> 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 >>> 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 >>> 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 >>> 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 >>> >>> I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. >>> >>> Memory: >>> free -lh >>> total used free shared buff/cache available >>> Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi >>> >>> Libaio: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k >>> 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k >>> 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k >>> 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k >>> 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k >>> >>> Io_uring: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k >>> 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k >>> 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k >>> 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k >>> 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k >>> 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k >>> 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k >>> >>> Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Tuesday, February 9, 2021 1:17 AM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Zhao Ping, >>> >>> First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. >>> >>> I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. >>> >>> As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: >>> >>> a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. >>> >>> b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). >>> >>> I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? >>> >>> Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. >>> >>> Thanks in advance! >>> >>> 07.02.2021 05:16, Zhao, Ping ?????: >>>> Hi Mikhail, >>>> >>>> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >>>> kernel 5.8.0 which doesn't has this problem. I can confirm there's a >>>> regression of aws patch(linux-aws_5.8.0-1010.10.diff) >>>> >>>> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >>>> >>>> Nginx worker_processes 1: >>>> 4k 100k 1M >>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>> sendfile 70MB/s 260MB/s 700MB/s >>>> >>>> >>>> Nginx worker_processes 4: >>>> 4k 100k 1M >>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>> libaio 250MB/s 900MB/s 2.0GB/s >>>> sendfile 250MB/s 900MB/s 1.6GB/s >>>> >>>> BR, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: Zhao, Ping >>>> Sent: Friday, February 5, 2021 2:43 PM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Mikhail, >>>> >>>> Added 'sendfile on' & 'aio off' test result with previous table: >>>> >>>> Following is the test result with 100KB and 1MB: (4KB to be test) >>>> >>>> Nginx worker_processes 1: >>>> 4k 100k 1M >>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>> sendfile tbt 260MB/s 700MB/s >>>> >>>> >>>> Nginx worker_processes 4: >>>> 4k 100k 1M >>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>> libaio 250MB/s 900MB/s 2.0GB/s >>>> sendfile tbt 900MB/s 1.6GB/s >>>> >>>> Regards, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Mikhail Isachenkov >>>> Sent: Thursday, February 4, 2021 4:55 PM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Zhao Ping, >>>> >>>> My test is much simpler than yours. I created >>>> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >>>> These files does not change during test. >>>> >>>> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >>>> >>>> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >>>> >>>> Thanks in advance! >>>> >>>> 04.02.2021 10:08, Zhao, Ping ?????: >>>>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>>>> >>>>> -----Original Message----- >>>>> From: Zhao, Ping >>>>> Sent: Thursday, February 4, 2021 10:33 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Mikhail, >>>>> >>>>> I didn't see this error in my log. Following is my OS/Kernel: >>>>> CentOS: 8.1.1911 >>>>> Kernel: 5.7.19 >>>>> Liburing: liburing-1.0.7-3.el8.x86_64, >>>>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>>>> >>>>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>>>> >>>>> My nginx reported this error before: >>>>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>>>> Which is fixed by my 2nd patch(Jan 25) already. >>>>> >>>>> BR, >>>>> Ping >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Mikhail Isachenkov >>>>> Sent: Wednesday, February 3, 2021 10:11 PM >>>>> To: nginx-devel at nginx.org >>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Ping Zhao, >>>>> >>>>> When I try to repeat this test, I've got a huge number of these errors: >>>>> >>>>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>>>> "/usr/local/html/64746" failed (11: Resource temporarily >>>>> unavailable) while sending response to client, client: 127.0.0.1, server: >>>>> localhost, >>>>> request: "GET /64746 HTTP/1.1", host: "localhost" >>>>> >>>>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>>>> >>>>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>>>> >>>>> 25.01.2021 11:24, Zhao, Ping ?????: >>>>>> Hello, add a small update to correct the length when part of request already received in previous. >>>>>> This case may happen when using io_uring and throughput increased. >>>>>> >>>>>> # HG changeset patch >>>>>> # User Ping Zhao # Date 1611566408 18000 >>>>>> # Mon Jan 25 04:20:08 2021 -0500 >>>>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>>>> Correct length calculation when part of request received. >>>>>> >>>>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>>>> @@ -531,6 +531,14 @@ >>>>>> >>>>>> size = ngx_buf_size(src); >>>>>> size = ngx_min(size, dst->end - dst->pos); >>>>>> +#if (NGX_HAVE_FILE_IOURING) >>>>>> + /* >>>>>> + * check if already received part of the request in previous, >>>>>> + * calculate the remain length >>>>>> + */ >>>>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>>>> + size = size - (dst->last - dst->pos); #endif >>>>>> >>>>>> sendfile = ctx->sendfile && !ctx->directio; >>>>>> >>>>>> -----Original Message----- >>>>>> From: nginx-devel On Behalf Of >>>>>> Zhao, Ping >>>>>> Sent: Thursday, January 21, 2021 9:44 AM >>>>>> To: nginx-devel at nginx.org >>>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>>> >>>>>> Hi Vladimir, >>>>>> >>>>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>>>> >>>>>> user nobody; >>>>>> daemon off; >>>>>> worker_processes 1; >>>>>> error_log error.log ; >>>>>> events { >>>>>> worker_connections 65535; >>>>>> use epoll; >>>>>> } >>>>>> >>>>>> http { >>>>>> include mime.types; >>>>>> default_type application/octet-stream; >>>>>> access_log on; >>>>>> aio on; >>>>>> sendfile off; >>>>>> directio 2k; >>>>>> >>>>>> # Cache Configurations >>>>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>>>> >>>>>> >>>>>> To better measure the disk io performance data, I do the following steps: >>>>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>>>> echo 2G > memory.limit_in_bytes >>>>>> use ' cgexec -g memory:nginx' to start Nginx. >>>>>> >>>>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>>>> >>>>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>>>> >>>>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>>>> extract the cache files in nvme cache disk. Use iostat to track >>>>>> the io data. The data should be align with NIC bw since all data >>>>>> should be from cache disk.(need exclude memory as cache storage >>>>>> impact) >>>>>> >>>>>> Following is the test result: >>>>>> >>>>>> Nginx worker_processes 1: >>>>>> 4k 100k 1M >>>>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>>>> >>>>>> >>>>>> Nginx worker_processes 4: >>>>>> 4k 100k 1M >>>>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>>>> libaio 250MB/s 900MB/s 2.0GB/s >>>>>> >>>>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>>>> >>>>>> Regards, >>>>>> Ping >>>>>> >>>>>> -----Original Message----- >>>>>> From: nginx-devel On Behalf Of >>>>>> Vladimir Homutov >>>>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>>>> To: nginx-devel at nginx.org >>>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>>> >>>>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>>>> It depends on if disk io is the performance hot spot or not. If >>>>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB >>>>>>> length >>>>>>> 1 Nginx thread it's hard to see performance difference because >>>>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>>>> performance bottle neck, both libaio and io_uring have the same >>>>>>> performance. If you increase request size or Nginx threads >>>>>>> number, for example 1MB length or Nginx thread number 4. In this >>>>>>> case, disk io became the performance bottle neck, you will see io_uring performance improvement. >>>>>> >>>>>> Can you please provide full test results with specific nginx configuration? >>>>>> >>>>>> _______________________________________________ >>>>>> nginx-devel mailing list >>>>>> nginx-devel at nginx.org >>>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>>> _______________________________________________ >>>>>> nginx-devel mailing list >>>>>> nginx-devel at nginx.org >>>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>>> _______________________________________________ >>>>>> nginx-devel mailing list >>>>>> nginx-devel at nginx.org >>>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>>> >>>>> >>>>> -- >>>>> Best regards, >>>>> Mikhail Isachenkov >>>>> NGINX Professional Services >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> >>>> >>>> -- >>>> Best regards, >>>> Mikhail Isachenkov >>>> NGINX Professional Services >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services From ping.zhao at intel.com Sat Feb 27 12:48:04 2021 From: ping.zhao at intel.com (Zhao, Ping) Date: Sat, 27 Feb 2021 12:48:04 +0000 Subject: [PATCH] Add io_uring support in AIO(async io) module In-Reply-To: <89fb913c-1262-3419-88a3-feaad6f43deb@nginx.com> References: <95886c3353dc80a3da21.1610629151@cdn001.sh.intel.com> <41619d1d-133b-9a0c-21f3-06965a4d9b1a@nginx.com> <443b30a2-dbb7-f72f-da2e-b459e1619aa3@nginx.com> <1c2a277b-58d7-524a-23e1-3c193ccc7f7d@nginx.com> <3d737faa-a8f6-ae8f-fce3-54089fecd1c3@nginx.com> <89fb913c-1262-3419-88a3-feaad6f43deb@nginx.com> Message-ID: Hi Mikhail, Yes, io_uring can help Nginx achieve same performance with lower resource cost. This is the key improvement of io_uring I think. It can't break through the HW limitation. BR, Ping -----Original Message----- From: nginx-devel On Behalf Of Mikhail Isachenkov Sent: Friday, February 26, 2021 4:41 PM To: nginx-devel at nginx.org Subject: Re: [PATCH] Add io_uring support in AIO(async io) module Hi Zhao Ping, I created i3en.6xlarge instance, 2 SSDs with 250k iops each (in raid0) and reproduced your results. Please find dstat output below. 1 worker, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 4 4 92 0 0|1412M 0 |5742k 1484M| 0 0 | 244k 87k 1 worker, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 1 1 95 3 0| 276M 0 |1386k 289M| 0 0 | 50k 8961 4 workers, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 6 6 18 70 0|1349M 0 |7240k 1445M| 0 0 | 296k 120k 4 workers, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 3 2 82 13 0| 890M 0 |3570k 931M| 0 0 | 139k 31k I ran test on i3.metal instance too (with 8 SSD in raid0), results are different but io_uring still faster: 1 worker, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 1 2 97 0 0|1372M 0 |5845k 1442M| 0 0 | 168k 51k 1 worker, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 1 1 98 0 0| 972M 20k|4083k 1023M| 0 0 | 126k 2014 4 workers, io_uring: usr sys idl wai stl| read writ| recv send| in out | int csw 3 4 92 0 0|2211M 0 |9314k 2346M| 0 0 | 251k 198k 4 workers, libaio: usr sys idl wai stl| read writ| recv send| in out | int csw 3 3 94 0 0|1867M 0 | 10M 1995M| 0 0 | 220k 38k There is no difference between libaio and io_uring with a large number of worker processes (>=12). 26.02.2021 04:22, Zhao, Ping ?????: > Hi Mikhail, > > My Nvme SSD reports 562k IOPS with bs 4k, 128 depth using io_uring. > > ./fio -name=fiotest -filename=/dev/nvme2n1 -iodepth=128 -thread > -rw=randread -ioengine=io_uring -sqthread_poll=1 -direct=1 -bs=4k > -size=10G -numjobs=1 -runtime=600 -group_reporting > > Jobs: 1 (f=1): [r(1)][100.0%][r=2173MiB/s][r=556k IOPS][eta 00m:00s] > fiotest: (groupid=0, jobs=1): err= 0: pid=23828: Fri Feb 26 03:55:40 2021 > read: IOPS=562k, BW=2196MiB/s (2303MB/s)(10.0GiB/4663msec) > > BR, > Ping > > -----Original Message----- > From: nginx-devel On Behalf Of Mikhail > Isachenkov > Sent: Thursday, February 25, 2021 7:01 PM > To: nginx-devel at nginx.org > Subject: Re: [PATCH] Add io_uring support in AIO(async io) module > > Hi Zhao Ping, > > Looks like general-purpose AWS EC2 instances does not optimized to high random I/O even with NVMe SSD; I'll try to test it again on bare-metal, storage-optimized instance. > > How many 4k random iops your storage can handle? (I'd like to run test on the instance with the same storage performance, according to https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/storage-optimized-instances.html#i2-instances-diskperf). > > Thanks in advance! > > 25.02.2021 09:59, Zhao, Ping ?????: >> Hi Mikhail, >> >> I tried with CentOS 8.1.1911 + fedora-kernel-5.10.10-200.fc33, and with your test steps & scripts: >> >> 1. Created 90k files on nvme SSD with each size 100KB. >> 2. Created separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx >> 3. Limit Nginx to 2GB: echo 2G > >> /sys/fs/cgroup/memory/nginx/memory.limit_in_bytes >> 4. Clear cache: echo 3 > /proc/sys/vm/drop_caches 5. Start nginx: >> cgexec -g memory:nginx 6. Tested with wrk on client: ./wrk -d 30 -t >> 100 -c 1000 -s add_random.lua http://... >> >> Io_uring can achieved 1.9+GB/s >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 1 2 97 0 0|1923M 0 |7369k 2136M| 0 0 | 263k 119k >> 1 2 97 0 0|1911M 0 |7329k 2123M| 0 0 | 262k 119k >> 1 2 97 0 0|1910M 3592k|7318k 2118M| 0 0 | 264k 117k >> 1 2 97 0 0|1923M 200k|7353k 2138M| 0 0 | 265k 118k >> 1 2 97 0 0|1929M 0 |7376k 2142M| 0 0 | 264k 118k >> 1 2 97 0 0|1924M 32k|7352k 2140M| 0 0 | 265k 118k >> 1 2 97 0 0|1913M 0 |7320k 2122M| 0 0 | 263k 117k >> 1 2 97 0 0|1921M 3544k|7336k 2132M| 0 0 | 264k 118k >> 1 2 97 0 0|1933M 0 |7353k 2146M| 0 0 | 264k 120k >> >> Libaio is 260+MB/s >> usr sys idl wai stl| read writ| recv send| in out | int csw >> 0 0 98 1 0| 267M 0 |1022k 293M| 0 0 | 41k 12k >> 0 0 98 1 0| 279M 740k|1093k 314M| 0 0 | 42k 12k >> 1 0 98 1 0| 268M 0 |1013k 294M| 0 0 | 41k 12k >> 0 0 98 1 0| 261M 0 |1002k 294M| 0 0 | 41k 12k >> 1 0 98 1 0| 285M 0 |1057k 310M| 0 0 | 43k 13k >> 0 0 98 1 0| 276M 4096B|1038k 307M| 0 0 | 42k 13k >> 0 0 98 1 0| 273M 780k|1019k 303M| 0 0 | 42k 12k >> 1 0 98 1 0| 275M 0 |1016k 305M| 0 0 | 42k 12k >> 0 0 98 1 0| 254M 0 | 976k 294M| 0 0 | 40k 12k >> 0 0 98 1 0| 265M 0 | 975k 293M| 0 0 | 41k 12k >> 0 0 98 1 0| 269M 0 | 976k 295M| 0 0 | 41k 12k >> >> Comparing with your dstat data that disk read keeps at 250M/s, is there anything locked the disk io bw? >> >> Regards, >> Ping >> >> -----Original Message----- >> From: nginx-devel On Behalf Of >> Mikhail Isachenkov >> Sent: Tuesday, February 9, 2021 9:31 PM >> To: nginx-devel at nginx.org >> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >> >> Hi Zhao Ping, >> >> Unfortunately, I still couldn't reproduce these results. Maybe you could point me where I'm wrong? Please find my steps below and configuration/lua script for wrk attached. >> >> 1. Create 90k files on SSD on Amazon EC2 instance. I created 1k, 100k, 1M files. >> 2. Create separate cgroup 'nginx': mkdir /sys/fs/cgroup/memory/nginx >> 3. Limit memory to 80 Mb, for example: echo >> 80M>/sys/fs/cgroup/memory/nginx/memory.limit_in_bytes >> 4. Disable limit for locked memory: ulimit -l unlimited 5. Start nginx: cgexec -g memory:nginx /usr/local/sbin/nginx 6. Run wrk on client: ./wrk -d 30 -t 100 -c 1000 -s add_random.lua http://... >> >> I tried different values for limit_in_bytes (from 80M to 2G) and different file sizes -- 1k, 100k, 1M. In fact, maximum bandwidth is the same with libaio and io_uring. >> >> For example, with 100kb files and 1 worker process: >> >> free -lh >> total used free shared buff/cache >> available >> Mem: 15Gi 212Mi 14Gi 13Mi 318Mi >> 14Gi >> >> dstat/libaio >> 5 6 73 17 0| 251M 0 |1253k 265M| 0 0 | 33k 1721 >> 4 4 73 17 0| 250M 0 |1267k 264M| 0 0 | 33k 1739 >> 6 5 72 16 0| 250M 924k|1308k 270M| 0 0 | 34k 2017 >> 5 5 72 17 0| 250M 0 |1277k 258M| 0 0 | 34k 1945 >> 5 5 73 17 0| 250M 0 |1215k 263M| 0 0 | 33k 1720 >> 5 5 72 16 0| 250M 0 |1311k 267M| 0 0 | 34k 1721 >> 5 5 73 16 0| 250M 0 |1280k 264M| 0 0 | 34k 1718 >> 6 6 72 16 0| 250M 24k|1362k 268M| 0 0 | 35k 1825 >> 5 5 73 17 0| 250M 0 |1342k 262M| 0 0 | 34k 1726 >> dstat/io_uring >> 5 6 60 29 0| 250M 0 |1079k 226M| 0 0 | 36k 10k >> 5 6 64 25 0| 251M 0 | 906k 204M| 0 0 | 32k 8607 >> 4 6 62 27 0| 250M 0 |1034k 221M| 0 0 | 35k 10k >> 5 6 63 26 0| 250M 20k| 909k 209M| 0 0 | 32k 8595 >> 4 6 62 27 0| 250M 0 |1003k 217M| 0 0 | 35k 10k >> 4 5 61 28 0| 250M 0 |1019k 226M| 0 0 | 35k 9700 >> 4 5 62 27 0| 250M 0 | 948k 210M| 0 0 | 32k 8433 >> 4 6 61 28 0| 250M 0 |1094k 216M| 0 0 | 35k 9811 >> 5 6 62 26 0| 250M 0 |1083k 226M| 0 0 | 35k 9479 >> >> As you can see, libaio even faster a bit. >> >> 09.02.2021 11:36, Zhao, Ping ?????: >>> Hi Mikhail, >>> >>> The performance improvement of Io_uring vs. libaio locates at disk io interface. So it needs exclude other factors when test, such as memory cache storage which is much faster than disk io. >>> >>> If I didn't use memory limitation, libaio and io_uring network bandwidth is very close because both of them use memory as cache file location, so we can't see the disk io change from it. In following data, as example, it used 17G memory as cache, network speed is same of io_uring and libaio, both of them has very few disk io load, which means very low io_uring/libaio usage. >>> >>> memory >>> free -lh >>> total used free shared buff/cache available >>> Mem: 376Gi 3.2Gi 356Gi 209Mi 17Gi 370Gi >>> >>> libaio: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 1 1 99 0 0|4097B 80k|4554k 104M| 0 0 | 77k 1344 >>> 1 1 98 0 0|8192B 104k|9955k 236M| 0 0 | 151k 1449 >>> 1 1 97 0 0| 56k 32k| 10M 241M| 0 0 | 148k 1652 >>> 2 1 97 0 0| 16k 16k|9552k 223M| 0 0 | 142k 1366 >>> 1 1 97 0 0| 16k 24k|9959k 234M| 0 0 | 146k 1570 >>> 1 1 97 0 0| 0 1064k| 10M 237M| 0 0 | 150k 1472 >>> 2 1 97 0 0| 16k 48k|9650k 227M| 0 0 | 143k 1555 >>> 2 1 97 0 0| 12k 16k|9185k 216M| 0 0 | 139k 1304 >>> >>> Io_uring: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 2 1 97 0 0| 0 0 |9866k 232M| 0 0 | 148k 1286 >>> 2 1 97 0 0| 0 0 |9388k 220M| 0 0 | 144k 1345 >>> 2 1 97 0 0| 0 0 |9080k 213M| 0 0 | 137k 1388 >>> 2 1 97 0 0| 0 0 |9611k 226M| 0 0 | 144k 1615 >>> 1 1 97 0 0| 0 232k|9830k 231M| 0 0 | 147k 1524 >>> >>> I used a Intel Xeon server Platinum 8280L CPU @ 2.70GHz, with 376G memory, 50G network. If I limit nginx memory to 2GB, the cache memory will be about 2.6G and won't increase during test. And disk io speed is close to network speed which means this can shows the disk io change of libaio vs. io_uring. This shows io_uring performance improvement. My previous data is based on this configuration. >>> >>> Memory: >>> free -lh >>> total used free shared buff/cache available >>> Mem: 376Gi 3.2Gi 370Gi 141Mi 2.6Gi 370Gi >>> >>> Libaio: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 1 0 98 1 0| 60M 0 |2925k 68M| 0 0 | 50k 16k >>> 1 0 98 1 0| 60M 8192B|2923k 68M| 0 0 | 50k 16k >>> 1 0 98 1 0| 61M 0 |2923k 68M| 0 0 | 50k 16k >>> 0 0 98 1 0| 60M 0 |2929k 68M| 0 0 | 50k 16k >>> 1 0 98 1 0| 60M 264k|2984k 69M| 0 0 | 51k 16k >>> >>> Io_uring: >>> ----total-usage---- -dsk/total- -net/total- ---paging-- ---system-- >>> usr sys idl wai stl| read writ| recv send| in out | int csw >>> 1 2 93 4 0| 192M 8192B|7951k 187M| 0 0 | 146k 90k >>> 1 2 93 4 0| 196M 0 |7953k 187M| 0 0 | 144k 89k >>> 1 2 93 4 0| 191M 300k|7854k 185M| 0 0 | 145k 87k >>> 1 2 94 3 0| 186M 8192B|7861k 185M| 0 0 | 143k 86k >>> 1 2 94 3 0| 180M 16k|7995k 188M| 0 0 | 146k 86k >>> 2 1 94 3 0| 163M 16k|7273k 171M| 0 0 | 133k 80k >>> 1 1 94 3 0| 173M 1308k|7995k 188M| 0 0 | 144k 83k >>> >>> Considering that server memory won't be always enough for cache storage when traffic increased and then Nginx will use disk as cache storage. In this case, io_uring will shows big performance improvement than libaio on disk io interface. This is the value of this patch. >>> >>> BR, >>> Ping >>> >>> -----Original Message----- >>> From: nginx-devel On Behalf Of >>> Mikhail Isachenkov >>> Sent: Tuesday, February 9, 2021 1:17 AM >>> To: nginx-devel at nginx.org >>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>> >>> Hi Zhao Ping, >>> >>> First of all, thank you for pointing me to AWS patch -- on Fedora 33 with 5.10 kernel I don't see any errors now. >>> >>> I've tested patch on Amazon EC2 NVMe SSD (and found this drive pretty fast!). Server is i3en.xlarge, client is c5n.2xlarge instance type, with up to 25 Gigabit network. >>> >>> As in previous test, I've created a number of 100kb files, but try to reach them via proxy_cache as on your stand. After warming up disk cache, I've got the following results: >>> >>> a) with 4 worker processes, I've got 3Gb/sec in all tests regardless of sendfile/libaio/io_uring. >>> >>> b) with 1 worker process, sendfile is faster (up to 1.9 Gb/sec) than libaio (1.40 Gb/sec) and io_uring (up to 1.45 Gb/sec). >>> >>> I didn't use any memory limitations, but I ran 'echo 3 > /proc/sys/vm/drop_caches' before each pass. When I try to limit memory to 2G with cgroups, results are generally the same. Maybe 2G is not enough? >>> >>> Could you please run the test for ~60 seconds, and run 'dstat' on other console? I'd like to check disk and network bandwidth at the same timestamps and compare them to mine. >>> >>> Thanks in advance! >>> >>> 07.02.2021 05:16, Zhao, Ping ?????: >>>> Hi Mikhail, >>>> >>>> I reproduced your problem with kernel 5.8.0-1010-aws. And I tried >>>> kernel 5.8.0 which doesn't has this problem. I can confirm there's >>>> a regression of aws patch(linux-aws_5.8.0-1010.10.diff) >>>> >>>> Updated 'sendfile on' & 'aio off' test result with 4KB data which is almost same as libaio: >>>> >>>> Nginx worker_processes 1: >>>> 4k 100k 1M >>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>> sendfile 70MB/s 260MB/s 700MB/s >>>> >>>> >>>> Nginx worker_processes 4: >>>> 4k 100k 1M >>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>> libaio 250MB/s 900MB/s 2.0GB/s >>>> sendfile 250MB/s 900MB/s 1.6GB/s >>>> >>>> BR, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: Zhao, Ping >>>> Sent: Friday, February 5, 2021 2:43 PM >>>> To: nginx-devel at nginx.org >>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Mikhail, >>>> >>>> Added 'sendfile on' & 'aio off' test result with previous table: >>>> >>>> Following is the test result with 100KB and 1MB: (4KB to be test) >>>> >>>> Nginx worker_processes 1: >>>> 4k 100k 1M >>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>> sendfile tbt 260MB/s 700MB/s >>>> >>>> >>>> Nginx worker_processes 4: >>>> 4k 100k 1M >>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>> libaio 250MB/s 900MB/s 2.0GB/s >>>> sendfile tbt 900MB/s 1.6GB/s >>>> >>>> Regards, >>>> Ping >>>> >>>> -----Original Message----- >>>> From: nginx-devel On Behalf Of >>>> Mikhail Isachenkov >>>> Sent: Thursday, February 4, 2021 4:55 PM >>>> To: nginx-devel at nginx.org >>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>> >>>> Hi Zhao Ping, >>>> >>>> My test is much simpler than yours. I created >>>> /usr/local/html/(11111...99999) files on SSD (100 kb size) and wrote small lua script for wrk that adds 5 random digits to request. There are no such errors without patch with aio enabled. >>>> These files does not change during test. >>>> >>>> I'll try to reproduce this on CentOS 8 -- which repository do you use to install 5.x kernel? >>>> >>>> Also, could you please run the test with 'sendfile on' and 'aio off' to get reference numbers for sendfile too? >>>> >>>> Thanks in advance! >>>> >>>> 04.02.2021 10:08, Zhao, Ping ?????: >>>>> Another possible cause is that "/usr/local/html/64746" was changed/removed when other user tried to read it. >>>>> >>>>> -----Original Message----- >>>>> From: Zhao, Ping >>>>> Sent: Thursday, February 4, 2021 10:33 AM >>>>> To: nginx-devel at nginx.org >>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Mikhail, >>>>> >>>>> I didn't see this error in my log. Following is my OS/Kernel: >>>>> CentOS: 8.1.1911 >>>>> Kernel: 5.7.19 >>>>> Liburing: liburing-1.0.7-3.el8.x86_64, >>>>> liburing-devel-1.0.7-3.el8.x86_64 (from yum repo) >>>>> >>>>> Regarding the error: 11: Resource temporarily unavailable. It's probably that too many read "/usr/local/html/64746" at one time which is still locked by previous read. I tried to repro this error with single file but it seems nginx auto store the signal file in memory and I don't see error. How do you perform the test? I want to repro this if possible. >>>>> >>>>> My nginx reported this error before: >>>>> 2021/01/04 05:04:29 [alert] 50769#50769: *11498 pread() read only 7101 of 15530 from "/mnt/cache1/17/68aae9d816ec02340ee617b7ee52a117", client: 11.11.11.3, server: _, request: "GET /_100kobject?version=cdn003191&thread=64 HTTP/1.1", host: "11.11.11.1:8080" >>>>> Which is fixed by my 2nd patch(Jan 25) already. >>>>> >>>>> BR, >>>>> Ping >>>>> >>>>> -----Original Message----- >>>>> From: nginx-devel On Behalf Of >>>>> Mikhail Isachenkov >>>>> Sent: Wednesday, February 3, 2021 10:11 PM >>>>> To: nginx-devel at nginx.org >>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>> >>>>> Hi Ping Zhao, >>>>> >>>>> When I try to repeat this test, I've got a huge number of these errors: >>>>> >>>>> 2021/02/03 10:22:48 [crit] 30018#30018: *2 aio read >>>>> "/usr/local/html/64746" failed (11: Resource temporarily >>>>> unavailable) while sending response to client, client: 127.0.0.1, server: >>>>> localhost, >>>>> request: "GET /64746 HTTP/1.1", host: "localhost" >>>>> >>>>> I tested this patch on Ubuntu 20.10 (5.8.0-1010-aws kernel version) and Fedora 33 (5.10.11-200.fc33.x86_64) with the same result. >>>>> >>>>> Did you get any errors in error log with patch applied? Which OS/kernel did you use for testing? Did you perform any specific tuning before running? >>>>> >>>>> 25.01.2021 11:24, Zhao, Ping ?????: >>>>>> Hello, add a small update to correct the length when part of request already received in previous. >>>>>> This case may happen when using io_uring and throughput increased. >>>>>> >>>>>> # HG changeset patch >>>>>> # User Ping Zhao # Date 1611566408 18000 >>>>>> # Mon Jan 25 04:20:08 2021 -0500 >>>>>> # Node ID f2c91860b7ac4b374fff4353a830cd9427e1d027 >>>>>> # Parent 1372f9ee2e829b5de5d12c05713c307e325e0369 >>>>>> Correct length calculation when part of request received. >>>>>> >>>>>> diff -r 1372f9ee2e82 -r f2c91860b7ac src/core/ngx_output_chain.c >>>>>> --- a/src/core/ngx_output_chain.c Wed Jan 13 11:10:05 2021 -0500 >>>>>> +++ b/src/core/ngx_output_chain.c Mon Jan 25 04:20:08 2021 -0500 >>>>>> @@ -531,6 +531,14 @@ >>>>>> >>>>>> size = ngx_buf_size(src); >>>>>> size = ngx_min(size, dst->end - dst->pos); >>>>>> +#if (NGX_HAVE_FILE_IOURING) >>>>>> + /* >>>>>> + * check if already received part of the request in previous, >>>>>> + * calculate the remain length >>>>>> + */ >>>>>> + if(dst->last > dst->pos && size > (dst->last - dst->pos)) >>>>>> + size = size - (dst->last - dst->pos); #endif >>>>>> >>>>>> sendfile = ctx->sendfile && !ctx->directio; >>>>>> >>>>>> -----Original Message----- >>>>>> From: nginx-devel On Behalf Of >>>>>> Zhao, Ping >>>>>> Sent: Thursday, January 21, 2021 9:44 AM >>>>>> To: nginx-devel at nginx.org >>>>>> Subject: RE: [PATCH] Add io_uring support in AIO(async io) module >>>>>> >>>>>> Hi Vladimir, >>>>>> >>>>>> No special/extra configuration needed, but need check if 'aio on' and 'sendfile off' is correctly set. This is my Nginx config for reference: >>>>>> >>>>>> user nobody; >>>>>> daemon off; >>>>>> worker_processes 1; >>>>>> error_log error.log ; >>>>>> events { >>>>>> worker_connections 65535; >>>>>> use epoll; >>>>>> } >>>>>> >>>>>> http { >>>>>> include mime.types; >>>>>> default_type application/octet-stream; >>>>>> access_log on; >>>>>> aio on; >>>>>> sendfile off; >>>>>> directio 2k; >>>>>> >>>>>> # Cache Configurations >>>>>> proxy_cache_path /mnt/cache0 levels=2 keys_zone=nginx-cache0:400m max_size=1400g inactive=4d use_temp_path=off; ...... >>>>>> >>>>>> >>>>>> To better measure the disk io performance data, I do the following steps: >>>>>> 1. To exclude other impact, and focus on disk io part.(This patch only impact disk aio read process) Use cgroup to limit Nginx memory usage. Otherwise Nginx may also use memory as cache storage and this may cause test result not so straight.(since most cache hit in memory, disk io bw is low, like my previous mail found which didn't exclude the memory cache impact) >>>>>> echo 2G > memory.limit_in_bytes >>>>>> use ' cgexec -g memory:nginx' to start Nginx. >>>>>> >>>>>> 2. use wrk -t 100 -c 1000, with random 25000 http requests. >>>>>> My previous test used -t 200 connections, comparing with -t 1000, libaio performance drop more when connections numbers increased from 200 to 1000, but io_uring doesn't. It's another advantage of io_uring. >>>>>> >>>>>> 3. First clean the cache disk and run the test for 30 minutes to let Nginx store the cache files to nvme disk as much as possible. >>>>>> >>>>>> 4. Rerun the test, this time Nginx will use ngx_file_aio_read to >>>>>> extract the cache files in nvme cache disk. Use iostat to track >>>>>> the io data. The data should be align with NIC bw since all data >>>>>> should be from cache disk.(need exclude memory as cache storage >>>>>> impact) >>>>>> >>>>>> Following is the test result: >>>>>> >>>>>> Nginx worker_processes 1: >>>>>> 4k 100k 1M >>>>>> Io_uring 220MB/s 1GB/s 1.3GB/s >>>>>> Libaio 70MB/s 250MB/s 600MB/s(with -c 200, 1.0GB/s) >>>>>> >>>>>> >>>>>> Nginx worker_processes 4: >>>>>> 4k 100k 1M >>>>>> Io_uring 800MB/s 2.5GB/s 2.6GB/s(my nvme disk io maximum bw) >>>>>> libaio 250MB/s 900MB/s 2.0GB/s >>>>>> >>>>>> So for small request, io_uring has huge improvement than libaio. In previous mail, because I didn't exclude the memory cache storage impact, most cache file is stored in memory, very few are from disk in case of 4k/100k. The data is not correct.(for 1M, because the cache is too big to store in memory, it wat in disk) Also I enabled directio option "directio 2k" this time to avoid this. >>>>>> >>>>>> Regards, >>>>>> Ping >>>>>> >>>>>> -----Original Message----- >>>>>> From: nginx-devel On Behalf Of >>>>>> Vladimir Homutov >>>>>> Sent: Wednesday, January 20, 2021 12:43 AM >>>>>> To: nginx-devel at nginx.org >>>>>> Subject: Re: [PATCH] Add io_uring support in AIO(async io) module >>>>>> >>>>>> On Tue, Jan 19, 2021 at 03:32:30AM +0000, Zhao, Ping wrote: >>>>>>> It depends on if disk io is the performance hot spot or not. If >>>>>>> yes, io_uring shows improvement than libaio. With 4KB/100KB >>>>>>> length >>>>>>> 1 Nginx thread it's hard to see performance difference because >>>>>>> iostat is only around ~10MB/100MB per second. Disk io is not the >>>>>>> performance bottle neck, both libaio and io_uring have the same >>>>>>> performance. If you increase request size or Nginx threads >>>>>>> number, for example 1MB length or Nginx thread number 4. In this >>>>>>> case, disk io became the performance bottle neck, you will see io_uring performance improvement. >>>>>> >>>>>> Can you please provide full test results with specific nginx configuration? >>>>>> >>>>>> _______________________________________________ >>>>>> nginx-devel mailing list >>>>>> nginx-devel at nginx.org >>>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>>> _______________________________________________ >>>>>> nginx-devel mailing list >>>>>> nginx-devel at nginx.org >>>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>>> _______________________________________________ >>>>>> nginx-devel mailing list >>>>>> nginx-devel at nginx.org >>>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>>> >>>>> >>>>> -- >>>>> Best regards, >>>>> Mikhail Isachenkov >>>>> NGINX Professional Services >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>>> >>>> >>>> -- >>>> Best regards, >>>> Mikhail Isachenkov >>>> NGINX Professional Services >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> >>> >>> -- >>> Best regards, >>> Mikhail Isachenkov >>> NGINX Professional Services >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> >> >> -- >> Best regards, >> Mikhail Isachenkov >> NGINX Professional Services >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > -- > Best regards, > Mikhail Isachenkov > NGINX Professional Services > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Best regards, Mikhail Isachenkov NGINX Professional Services _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel