fix: 修复并发计数器在请求异常时不能正确减少的问题

- 增强事件监听机制
  - 监听 req 的 close 和 aborted 事件
  - 监听 res 的 finish 和 error 事件
  - 使用标志位确保只减少一次计数

- 改进日志记录
  - 增加并发计数增减的详细日志
  - 记录请求关闭和中断事件

- 确保计数器安全性
  - 使用 Lua 脚本原子操作防止负数
  - 优化 Redis 操作逻辑

- 增强管理界面
  - API Keys 列表显示当前并发数
  - 并发数超过 0 时用橙色标记
  - 显示当前并发数/限制数格式

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
shaw
2025-07-16 10:21:17 +08:00
parent e2c9f26135
commit 08f93e9872
4 changed files with 62 additions and 18 deletions

View File

@@ -724,6 +724,7 @@ class RedisClient {
// 设置过期时间为5分钟防止计数器永远不清零
await this.client.expire(key, 300);
logger.database(`🔢 Incremented concurrency for key ${apiKeyId}: ${count}`);
return count;
} catch (error) {
logger.error('❌ Failed to increment concurrency:', error);
@@ -735,14 +736,28 @@ class RedisClient {
async decrConcurrency(apiKeyId) {
try {
const key = `concurrency:${apiKeyId}`;
const count = await this.client.decr(key);
// 如果计数降到0或以下删除键
if (count <= 0) {
await this.client.del(key);
return 0;
}
// 使用Lua脚本确保原子性操作防止计数器变成负数
const luaScript = `
local key = KEYS[1]
local current = tonumber(redis.call('get', key) or "0")
if current <= 0 then
redis.call('del', key)
return 0
else
local new_value = redis.call('decr', key)
if new_value <= 0 then
redis.call('del', key)
return 0
else
return new_value
end
end
`;
const count = await this.client.eval(luaScript, 1, key);
logger.database(`🔢 Decremented concurrency for key ${apiKeyId}: ${count}`);
return count;
} catch (error) {
logger.error('❌ Failed to decrement concurrency:', error);