From 42c21537323039c76fa140a0e2988a4d544b1e77 Mon Sep 17 00:00:00 2001 From: zhangshumin01 <10682145+Ethan-Zhang-ZH@users.noreply.github.com> Date: Mon, 12 Oct 2026 11:39:05 +0800 Subject: [PATCH 1/2] feat: support backlog in listen via nginx_config Allow an optional `backlog` field per node_listen item, which renders the `backlog=N` parameter of the nginx listen directive. This lets operators size the pending connections queue from config.yaml instead of relying on the default 511, which can overflow under connection spikes when only the host-level net.core.somaxconn is tuned. Fixes part of #14022 Signed-off-by: zhangshumin01 <10682145+Ethan-Zhang-ZH@users.noreply.github.com> --- apisix/cli/ngx_tpl.lua | 2 +- apisix/cli/ops.lua | 16 ++++++++++---- conf/config.yaml.example | 2 ++ t/cli/test_main.sh | 48 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua index e7262a3541d6..6379d7113fa6 100644 --- a/apisix/cli/ngx_tpl.lua +++ b/apisix/cli/ngx_tpl.lua @@ -843,7 +843,7 @@ http { http3 on; {% end %} {% for _, item in ipairs(node_listen) do %} - listen {* item.ip *}:{* item.port *} default_server {% if enable_reuseport then %} reuseport {% end %}; + listen {* item.ip *}:{* item.port *} default_server {% if enable_reuseport then %} reuseport {% end %}{% if item.backlog then %} backlog={* item.backlog *}{% end %}; {% end %} {% if ssl.enable then %} {% for _, item in ipairs(ssl.listen) do %} diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua index 58428421c4d1..71dd042acba4 100644 --- a/apisix/cli/ops.lua +++ b/apisix/cli/ops.lua @@ -524,7 +524,7 @@ Please modify "admin_key" in conf/config.yaml . local ip_port_to_check = {} local function listen_table_insert(listen_table, scheme, ip, port, - enable_http3, enable_ipv6) + enable_http3, enable_ipv6, backlog) if type(ip) ~= "string" then util.die(scheme, " listen ip format error, must be string", "\n") end @@ -545,7 +545,8 @@ Please modify "admin_key" in conf/config.yaml . { ip = ip, port = port, - enable_http3 = enable_http3 + enable_http3 = enable_http3, + backlog = backlog }) ip_port_to_check[addr] = scheme end @@ -559,7 +560,8 @@ Please modify "admin_key" in conf/config.yaml . { ip = ip, port = port, - enable_http3 = enable_http3 + enable_http3 = enable_http3, + backlog = backlog }) ip_port_to_check[addr] = scheme end @@ -581,6 +583,7 @@ Please modify "admin_key" in conf/config.yaml . local port = value.port local enable_ipv6 = false local enable_http2 = value.enable_http2 + local backlog = value.backlog if ip == nil then ip = "0.0.0.0" @@ -599,8 +602,13 @@ Please modify "admin_key" in conf/config.yaml . .. "apisix level.", "\n") end + if backlog ~= nil and (type(backlog) ~= "number" + or backlog <= 0 or backlog % 1 ~= 0) then + util.die("ERROR: backlog in node_listen must be a positive integer.", "\n") + end + listen_table_insert(node_listen, "http", ip, port, - false, enable_ipv6) + false, enable_ipv6, backlog) end end end diff --git a/conf/config.yaml.example b/conf/config.yaml.example index ded74f6ceb20..355ca4712be5 100644 --- a/conf/config.yaml.example +++ b/conf/config.yaml.example @@ -23,6 +23,8 @@ apisix: node_listen: # APISIX listening ports. - 9080 # - port: 9081 + # backlog: 8192 # Set the `backlog` parameter of the listen directive, + # # which caps the pending connections queue. Default is 511. # - ip: 127.0.0.2 # If not set, default to `0.0.0.0` # port: 9082 enable_admin: true # Admin API diff --git a/t/cli/test_main.sh b/t/cli/test_main.sh index 0ae7f2dba855..d52ef09b389d 100755 --- a/t/cli/test_main.sh +++ b/t/cli/test_main.sh @@ -177,6 +177,54 @@ fi echo "passed: support specific IP listen in http and https" +# check support backlog in node_listen + +git checkout conf/config.yaml + +echo " +apisix: + node_listen: + - ip: 127.0.0.1 + port: 9081 + backlog: 8192 + - ip: 127.0.0.2 + port: 9082 +" > conf/config.yaml + +make init + +count_backlog=`grep "listen 127.0.0.1:9081" conf/nginx.conf | grep -c "backlog=8192" || true` +if [ $count_backlog -ne 1 ]; then + echo "failed: failed to support backlog in node_listen" + exit 1 +fi + +count_no_backlog=`grep "listen 127.0.0.2:9082" conf/nginx.conf | grep -c "backlog" || true` +if [ $count_no_backlog -ne 0 ]; then + echo "failed: backlog should not be rendered when it is not configured" + exit 1 +fi + +echo "passed: support backlog in node_listen" + +# check invalid backlog in node_listen + +echo " +apisix: + node_listen: + - ip: 127.0.0.1 + port: 9081 + backlog: abc +" > conf/config.yaml + +out=$(make init 2>&1 || true) +if ! echo "$out" | grep 'backlog in node_listen must be a positive integer'; then + echo "failed: failed to detect invalid backlog in node_listen" + exit 1 +fi + +echo "passed: check invalid backlog in node_listen" + # check deprecated enable_http2 in node_listen echo " apisix: From 9b6af47ddcef23f7959f028cf3630db28cc66c2c Mon Sep 17 00:00:00 2001 From: zhangshumin01 <10682145+Ethan-Zhang-ZH@users.noreply.github.com> Date: Mon, 12 Oct 2026 11:43:21 +0800 Subject: [PATCH 2/2] feat: support if= condition in access_log via nginx_config Allow an optional `access_log_if` field under nginx_config.http, which renders an `if=` parameter on the access_log directive. The condition is evaluated in the log phase and can reference variables declared via http_configuration_snippet (map / split_clients), enabling log sampling or per-status/per-endpoint log exclusion with plain nginx config, without any Lua plugin. Fixes part of #14022 Signed-off-by: zhangshumin01 <10682145+Ethan-Zhang-ZH@users.noreply.github.com> --- apisix/cli/ngx_tpl.lua | 4 ++-- conf/config.yaml.example | 6 ++++++ t/cli/test_access_log.sh | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua index 6379d7113fa6..88429a2d03c0 100644 --- a/apisix/cli/ngx_tpl.lua +++ b/apisix/cli/ngx_tpl.lua @@ -556,9 +556,9 @@ http { uninitialized_variable_warn off; {% if http.access_log_buffer then %} - access_log {* http.access_log *} main buffer={* http.access_log_buffer *} flush=3; + access_log {* http.access_log *} main buffer={* http.access_log_buffer *} flush=3{% if http.access_log_if then %} if={* http.access_log_if *}{% end %}; {% else %} - access_log {* http.access_log *} main buffer=16384 flush=3; + access_log {* http.access_log *} main buffer=16384 flush=3{% if http.access_log_if then %} if={* http.access_log_if *}{% end %}; {% end %} {% end %} open_file_cache max=1000 inactive=60; diff --git a/conf/config.yaml.example b/conf/config.yaml.example index 355ca4712be5..3f2927ac37b7 100644 --- a/conf/config.yaml.example +++ b/conf/config.yaml.example @@ -305,6 +305,12 @@ nginx_config: # Config for render the template to generate n enable_access_log: true # Enable HTTP proxy access logging. access_log: logs/access.log # Location of the access log. access_log_buffer: 16384 # buffer size of access log. + # access_log_if: $loggable # If set, append an `if=` parameter to the + # access_log directive, so requests are logged only when + # the condition is met (e.g. log sampling or excluding + # specific status codes / endpoints). The referenced + # variable must be declared via http_configuration_snippet + # (e.g. `map` or `split_clients`). # available variables: # request_type: traditional_http / ai_chat / ai_stream # llm_time_to_first_token: duration from the start send request to ai server to the first token received diff --git a/t/cli/test_access_log.sh b/t/cli/test_access_log.sh index 180f9ff01ee1..7df62e994c36 100755 --- a/t/cli/test_access_log.sh +++ b/t/cli/test_access_log.sh @@ -315,3 +315,41 @@ if ! grep '127.0.0.1 UDP test_stream_access_log_format' output.log; then exit 1 fi echo "passed: logs are being dumped for stream proxy" + +# check access_log if condition + +git checkout conf/config.yaml + +echo ' +nginx_config: + http: + access_log_if: $loggable + http_configuration_snippet: | + map $status $loggable { + default 1; + } +' > conf/config.yaml + +make init + +count_log_if=$(grep "access_log logs/access.log main buffer=16384 flush=3" conf/nginx.conf | grep -cF 'if=$loggable;' || true) +if [ "$count_log_if" -ne 1 ]; then + echo "failed: access_log if condition is not rendered" + exit 1 +fi + +echo "passed: access_log if condition is ok" + +# check access_log if condition is not rendered by default + +git checkout conf/config.yaml + +make init + +count_no_log_if=$(grep "access_log logs/access.log main" conf/nginx.conf | grep -c "if=" || true) +if [ "$count_no_log_if" -ne 0 ]; then + echo "failed: access_log if condition should not be rendered when it is not configured" + exit 1 +fi + +echo "passed: access_log if condition is not rendered when it is not configured"