Skip to content

[BUG] AI token limiter Redis key ignores rule and selector scope #6514

Description

@Aias00

Search before asking

  • I had searched in the issues and found no similar issues.

Apache ShenYu Component

shenyu-plugin

What happened

AiTokenLimiterPlugin builds the Redis counter key only from a fixed prefix and the configured resolver value:

private static final String REDIS_KEY_PREFIX = "SHENYU:AI:TOKENLIMIT:";
...
String cacheKey = REDIS_KEY_PREFIX + getCacheKey(exchange, tokenLimitType, keyName);

getCacheKey(...) returns only request-derived data such as IP, URI, header, parameter, cookie, or context path:

case IP -> Objects.requireNonNull(request.getRemoteAddress()).getHostString();
case URI -> request.getURI().getPath();
case HEADER -> request.getHeaders().getFirst(keyName);
case PARAMETER -> request.getQueryParams().getFirst(keyName);
case COOKIE -> { ... }
default -> exchange.getAttribute(Constants.CONTEXT_PATH);

The rule id, selector id, plugin id, and namespace are not included. Therefore two different AI token limiter rules can share the same Redis counter whenever their resolver value is the same.

For example, two separate rules using aiTokenLimitType=uri for /v1/chat/completions but with different tokenLimit values will both read and increment:

SHENYU:AI:TOKENLIMIT:/v1/chat/completions

Usage from one rule can exhaust the other rule's quota, even if they belong to different selectors/routes.

For comparison, the regular RateLimiterPlugin scopes Redis keys with rule.getId() + resolverKey before passing them to the rate limiter.

Expected behavior

AI token limiter counters should be scoped at least by rule id, and likely also by namespace/selector as needed, before appending the request-derived resolver value. Independent limiter rules should not share Redis counters unless explicitly configured to do so.

How to reproduce

  1. Enable ai-token-limiter.
  2. Configure two different rules for different selectors/routes that both resolve to the same key value, for example aiTokenLimitType=uri and request path /v1/chat/completions.
  3. Set different tokenLimit values for the two rules.
  4. Send requests through the first rule until it records token usage.
  5. Send a request through the second rule.
  6. The second rule reads the same Redis key and is affected by the first rule's token usage.

Debug logs

No response

Environment

Current master branch.

Are you willing to submit a PR?

  • Yes I am willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions