openresty / openresty/lua-nginx-module

How to really do non-blocking http requests in log_by_lua (or help me understand what i'm doing wrong ;-)

Open
#1,807 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
11.8k
Forks
2.1k
Avg merge
6h 1m
Merged PRs (30d)
6

Description

My Usecase

I'm building a proxy server that stores optimized versions of response bodies for the next request to be served from cache. This means writing the response body of a proxied request to a temporary file and sending it to a optimizing process (minify, compress images etc.) via a rest api after the proxy request is done. This first / uncached request should not suffer from any overhead so log_by_lua* seemed like a good choice to me.

What i tried

Since ngx.location.capture and ngx.socket.tcp are disabled in log_by_lua* i went with ngx.timer.at

log_by_lua_block {
    -- simulate 1 second http call
    local function sleep(premature)
        local socket = require("socket")
        socket.sleep(1)
    end
    local ok, err = ngx.timer.at(0, sleep)
}

Although running in a "light thread" this will block workers and connections start piling up very quickly. After just a couple of seconds proxy will stop working and nginx throws the slightly misleading error message:

upstream timed out (110: Connection timed out) while connecting to upstream

At this point response time i super slow because nginx seems to be queuing new connections. It can take several seconds just to get server stats:

# time curl localhost/server-status

Active connections: 160
server accepts handled requests
 165403 165403 164827
Reading: 0 Writing: 44 Waiting: 116

real	0m14.835s
user	0m0.000s
sys	0m0.007s
What would work

I can confirm that it's possible to run non-blocking code in log_by_lua* like this:

log_by_lua_block {
    ngx.sleep(2)
}
Help!

I'm wondering if i am missing something here and i don't quite understand why the client connection is not simply closed before running NGX_HTTP_LOG_PHASE. Any hint on how to solve this problem would be highly appreciated.

I'm running nginx/1.17.3 from https://launchpad.net/~nginx/+archive/ubuntu/stable

Thank you.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the log_by_lua_block example with ngx.timer.at, socket.sleep, and ngx.sleep on nginx 1.17.3. Read the log_by_lua* phase and ngx.timer.at behavior, including the stated restrictions on ngx.location.capture and ngx.socket.tcp. Done means establishing whether socket.sleep blocking workers is expected and documenting the supported non-blocking approach or the required module change.

Written by the indexing model from the issue text.

Assessment

Tech stack
lua, nginx
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.