Skip to content

feat(limit-count): add Redis Sentinel backend, sliding window and delayed sync support#13443

Open
AlinsRan wants to merge 11 commits into
apache:masterfrom
AlinsRan:feat/limit-count-sentinel
Open

feat(limit-count): add Redis Sentinel backend, sliding window and delayed sync support#13443
AlinsRan wants to merge 11 commits into
apache:masterfrom
AlinsRan:feat/limit-count-sentinel

Conversation

@AlinsRan
Copy link
Copy Markdown
Contributor

Summary

This PR enhances the limit-count plugin with three new capabilities:

1. Redis Sentinel backend

Adds a new redis-sentinel policy that connects to Redis through Sentinel for high-availability setups:

  • Automatic master discovery via Sentinel nodes
  • Supports all existing Redis configuration options (username, password, SSL, timeouts)
  • Falls back to local counting when Redis is unavailable

2. Sliding window algorithm

Adds a window_type field (default: fixed) to choose between the existing fixed-window counter and a new sliding-window algorithm:

  • Fixed window: current behavior, resets at each window boundary
  • Sliding window: smoother rate limiting, avoids burst at window boundary
  • Sliding window is implemented in Redis using sorted sets; local sliding window uses a shared-dict implementation

3. Delayed sync (sync_interval)

Adds a sync_interval field for redis, redis-cluster, and redis-sentinel policies:

  • Reduces Redis round-trips on high-traffic routes by syncing counts in batches
  • Falls back to local counting between syncs and reconciles with Redis at each sync interval
  • Set to -1 to disable (default behavior: sync on every request)

Changes

  • New files: limit-count-redis-sentinel.lua, delayed-syncer.lua, util.lua, sliding-window/
  • Updated: init.lua, limit-count-redis.lua, limit-count-redis-cluster.lua, limit-count-local.lua
  • New tests: t/plugin/limit-count-redis-sentinel.t, t/plugin/limit-count-sliding.t, t/plugin/limit-count-redis-delayed-sync.t
  • Updated docs: English and Chinese plugin reference

Compatibility

All existing configurations remain unchanged. New fields are optional with backward-compatible defaults.

AlinsRan and others added 11 commits May 26, 2026 04:37
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add sliding-window and sliding-window/store directories to Makefile
  install targets so luarocks make installs all limit-count submodules
- Convert oneOf 'matches both schemas' error in check_schema to the
  clearer message when both count/time_window and rules are present

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This dict is required by the delayed syncer module and was added
to ngx_tpl.lua but missing from the default config, causing nginx
to fail to start with an invalid configuration.
- Remove debug core.log.info from incoming_delayed in all 3 redis backends
- Add BEGIN block to set REDIS_NODE_0/1 env vars for redis-cluster tests
- Fix sentinel route URI from /hello2 to /echo (no handler for /hello2 exists)
- Fix TEST 4 requests from GET /hello2 to GET /echo
- Fix preprocessor to check grep_error_log before adding no_error_log

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… test conflicts

Use route ID 'limit-count-rules-1' instead of '1' to prevent state collision
with other test files that create route ID '1' and run before this file
alphabetically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… 19/20

After changing route ID from '1' to 'limit-count-rules-1', the etcd key
path changes from /apisix/routes/1 to /apisix/routes/limit-count-rules-1.
Update error_log patterns in TEST 19 and TEST 20 to match the new path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use ngx.say() instead of ngx.print() to include trailing newline
- Remove explicit error_code: 201 check to accept both 200 (update)
  and 201 (create), consistent with other setup tests in this file

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When rules are used with a custom limit_header (e.g. ai-rate-limiting
sets "X-AI-RateLimit-Limit"), the per-rule indexed headers must
preserve that base prefix.

Before: X-1-RateLimit-Limit  (ignored conf.limit_header)
After:  X-AI-1-RateLimit-Limit  (uses conf.limit_header as base)

The fix inserts the rule prefix before "RateLimit-" in the configured
header name via gsub, so any header base is preserved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. enhancement New feature or request labels May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant