openresty / openresty/lua-nginx-module

100% CPU in shared dict :get()

Open
#2,393 1 comment 0 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

when using a shared dict where all nginx workers repeatedly :get() the same 1-2 keys with a high number of simultaenous requests, some nginx processes seem to get stuck in a deadlock caused by locking causing 100% CPU load even when the number of requests has subsided already (all still existing requests are idle keepalive).

stub_status

Active connections: 102
server accepts handled requests
39308 39308 339293
Reading: 0 Writing: 287 Waiting: 93

strace shows (however it takes up to a minute for this to show/add another line, which is a further indicator this is not in nginx but in userland lua)

futex(0x7f7ad4c37080, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY) = -1 EAGAIN (Resource temporarily unavailable)

https://mailman.nginx.org/pipermail/nginx/2017-September/054687.html reports a similar issue in nginx, however nginx doesn't natively use mutex and the issue could clearly be traced back to lua code

Checking the nginx processes with pstack

#0 0x0000000000438c86 in ngx_shmtx_lock (mtx=0x7f7ad4c37068) at src/core/ngx_shmtx.c:86
#1 0x0000000000527937 in ngx_http_lua_ffi_shdict_get (zone=0xbd5cc0, key=0x7f7ace894b60 "REDACTED-2", key_len=12, value_type=0x7f7ad4099928, str_value_buf=0x7f7ad409c340, str_value_len=0x7f7ad40b8850, num_value=0x7f7ad4093b40, user_flags=0x7f7ad4093b20, get_stale=0, is_stale=0x7f7ad409c300, err=0x7f7ad40bc318) at ../ngx_lua-0.10.26/src/ngx_http_lua_shdict.c:1593
#2 0x00007f7ad635dd19 in ?? ()
#3 0x00007f7ad4093b40 in ?? ()
#4 0x00007f7ad4093b20 in ?? ()
#5 0x0000000000000000 in ?? ()

https://github.com/openresty/lua-nginx-module/blob/master/src/ngx_http_lua_shdict.c#L1568 (-> nginx https://github.com/nginx/nginx/blob/master/src/core/ngx_shmtx.c#L70C1-L70C15) shows that "get" creates a lock.

Is the lock for "get" really necessary? Is there a way to disable it?
Any ideas what could caus this? Is it possibly not related to the :get() at all?

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 with ngx_http_lua_ffi_shdict_get in src/ngx_http_lua_shdict.c and the locking path in nginx's src/core/ngx_shmtx.c. Reproduce the high-concurrency shared-dict :get() workload, then compare pstack and strace behavior as requests subside. Done means determining whether :get() is responsible and documenting a validated cause or fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, lua, nginx
Domain
backend, performance
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.