Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: memory leak when collecting response body chunks #2346

Open
shreemaan-abhishek opened this issue Aug 2, 2024 · 1 comment
Open

bug: memory leak when collecting response body chunks #2346

shreemaan-abhishek opened this issue Aug 2, 2024 · 1 comment

Comments

@shreemaan-abhishek
Copy link

Loading large response body with size > 300 MB into memory causes leak.

The purpose of collecting response body chunks is to record them in logs in the log phase.

Steps to reproduce:

  • use the following nginx.conf:
worker_processes 1;
error_log logs/error.log warn;

events {
    worker_connections 1024;
}

http {

    server {
        listen       8080;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;

            body_filter_by_lua_block {

                local body_buffer
                local chunk, eof = ngx.arg[1], ngx.arg[2]

                local ctx = ngx.ctx
                if not ctx._body_buffer then
                    ctx._body_buffer = {}
                end

                if type(chunk) == "string" and chunk ~= "" then
                    body_buffer = ctx._body_buffer
                    if not body_buffer then
                        body_buffer = {
                            chunk,
                            n = 1
                        }
                        ctx._body_buffer = body_buffer
                    else
                        local n = (body_buffer.n or 1) + 1
                        body_buffer.n = n
                        body_buffer[n] = chunk
                    end
                end

                if eof then
                    body_buffer = ctx._body_buffer
                    if not body_buffer then
                        return chunk
                    end

                    body_buffer = table.concat(body_buffer, "", 1, body_buffer.n)
                    ctx._body_buffer = nil
                end

            }
        }
    }

    upstream backend {
        server 192.168.253.1:8081;
    }
}
  • the upstream should respond with a response body of size >= 300MB.
  • start openresty
  • check memory usage using top
    image
  • send a request:
curl http://127.0.0.1:8080/ --output tmpfile
  • top command output will clearly show memory usage spike that doesn't get freed but the usage keeps on increasing upon further requests
    image

version:

nginx version: openresty/1.25.3.1
built by gcc 13.2.0 (Ubuntu 13.2.0-23ubuntu4)
built with OpenSSL 3.0.13 30 Jan 2024
TLS SNI support enabled
configure arguments: --prefix=/usr/local/openresty/nginx --with-debug --with-cc-opt='-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC -O2 -DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC -O2 -DNGX_LUA_ABORT_AT_PANIC' --add-module=../ngx_devel_kit-0.3.3 --add-module=../echo-nginx-module-0.63 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2 --add-module=../set-misc-nginx-module-0.33 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.09 --add-module=../srcache-nginx-module-0.33 --add-module=../ngx_lua-0.10.26 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.37 --add-module=../array-var-nginx-module-0.06 --add-module=../memc-nginx-module-0.20 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.9 --add-module=../rds-json-nginx-module-0.16 --add-module=../rds-csv-nginx-module-0.09 --add-module=../ngx_stream_lua-0.0.14 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --with-stream --without-pcre2 --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_ssl_module
@zhuizhuhaomeng
Copy link
Contributor

zhuizhuhaomeng commented Aug 25, 2024

It appears to be caused by Lua GC not reclaiming the Lua string in time or Lua GC not returning memory to the OS.
Our private library luajit-plus improves memory usage in this case.
Subscribing to OpenResty XRay gives you access to our luajit-plus private library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants