feat: 优化并发控制和移除冗余限制功能

主要改进:
1. 改进并发控制机制
   - 使用 once 代替 on 避免重复监听
   - 监听多个事件确保可靠性(close、finish)
   - 支持客户端断开时立即释放并发槽位

2. 支持非流式请求的客户端断开处理
   - 客户端断开时立即中断上游请求
   - 避免资源浪费和不必要的 API 调用

3. 移除 requestLimit(请求数限制)功能
   - 移除配置和验证逻辑
   - 保留请求统计用于监控分析

4. 移除速率限制(Rate Limit)功能
   - 移除 RATE_LIMIT_* 配置
   - 简化中间件逻辑
   - 避免与并发控制重复

现在系统仅保留:
- Token 使用量限制
- 并发数限制(更精确的资源控制)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
shaw
2025-07-16 14:40:37 +08:00
parent f9bc2ddb23
commit 567e3b25aa
9 changed files with 62 additions and 108 deletions

View File

@@ -15,7 +15,9 @@ class ClaudeRelayService {
}
// 🚀 转发请求到Claude API
async relayRequest(requestBody, apiKeyData) {
async relayRequest(requestBody, apiKeyData, clientRequest, clientResponse) {
let upstreamRequest = null;
try {
// 生成会话哈希用于sticky会话
const sessionHash = sessionHelper.generateSessionHash(requestBody);
@@ -34,8 +36,37 @@ class ClaudeRelayService {
// 获取代理配置
const proxyAgent = await this._getProxyAgent(accountId);
// 发送请求到Claude API
const response = await this._makeClaudeRequest(processedBody, accessToken, proxyAgent);
// 设置客户端断开监听器
const handleClientDisconnect = () => {
logger.info('🔌 Client disconnected, aborting upstream request');
if (upstreamRequest && !upstreamRequest.destroyed) {
upstreamRequest.destroy();
}
};
// 监听客户端断开事件
if (clientRequest) {
clientRequest.once('close', handleClientDisconnect);
}
if (clientResponse) {
clientResponse.once('close', handleClientDisconnect);
}
// 发送请求到Claude API传入回调以获取请求对象
const response = await this._makeClaudeRequest(
processedBody,
accessToken,
proxyAgent,
(req) => { upstreamRequest = req; }
);
// 移除监听器(请求成功完成)
if (clientRequest) {
clientRequest.removeListener('close', handleClientDisconnect);
}
if (clientResponse) {
clientResponse.removeListener('close', handleClientDisconnect);
}
// 记录成功的API调用
const inputTokens = requestBody.messages ?
@@ -160,7 +191,7 @@ class ClaudeRelayService {
}
// 🔗 发送请求到Claude API
async _makeClaudeRequest(body, accessToken, proxyAgent) {
async _makeClaudeRequest(body, accessToken, proxyAgent, onRequest) {
return new Promise((resolve, reject) => {
const url = new URL(this.claudeApiUrl);
@@ -207,6 +238,11 @@ class ClaudeRelayService {
}
});
});
// 如果提供了 onRequest 回调,传递请求对象
if (onRequest && typeof onRequest === 'function') {
onRequest(req);
}
req.on('error', (error) => {
logger.error('❌ Claude API request error:', error);