perf(api): 为所有API服务添加HTTP连接池配置防止资源泄漏

为Claude、OpenAI、Gemini、Qwen等API服务添加HTTP/HTTPS agent配置,设置keepAlive、maxSockets等参数以限制连接池大小,避免资源泄漏问题。同时统一了各服务的axios配置方式,提高网络请求的稳定性和性能。
This commit is contained in:
hex2077 2025-12-10 15:45:08 +08:00
parent b364341f67
commit 1c46bb547b
7 changed files with 149 additions and 11 deletions

View file

@ -1,4 +1,6 @@
import axios from 'axios';
import * as http from 'http';
import * as https from 'https';
/**
* Claude API Core Service Class.
@ -27,8 +29,24 @@ export class ClaudeApiService {
* @returns {object} Axios instance.
*/
createClient() {
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const axiosConfig = {
baseURL: this.baseUrl,
httpAgent,
httpsAgent,
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json',

View file

@ -308,15 +308,15 @@ export class KiroApiService {
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 200, // 每个主机最多 10 个连接
maxSockets: 100, // 每个主机最多 10 个连接
maxFreeSockets: 5, // 最多保留 5 个空闲连接
timeout: 60000, // 空闲连接 60 秒后关闭
timeout: 120000, // 空闲连接 60 秒后关闭
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 60000,
timeout: 120000,
});
const axiosConfig = {

View file

@ -1,5 +1,6 @@
import { OAuth2Client } from 'google-auth-library';
import * as http from 'http';
import * as https from 'https';
import { promises as fs } from 'fs';
import * as path from 'path';
import * as os from 'os';
@ -9,6 +10,20 @@ import open from 'open';
import { API_ACTIONS, formatExpiryTime } from '../common.js';
import { getProviderModels } from '../provider-models.js';
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
// --- Constants ---
const AUTH_REDIRECT_PORT = 8086;
const CREDENTIALS_DIR = '.antigravity';
@ -210,7 +225,14 @@ function ensureRolesInContents(requestBody) {
export class AntigravityApiService {
constructor(config) {
this.authClient = new OAuth2Client(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET);
// 配置 OAuth2Client 使用自定义的 HTTP agent
this.authClient = new OAuth2Client({
clientId: OAUTH_CLIENT_ID,
clientSecret: OAUTH_CLIENT_SECRET,
transporterOptions: {
agent: httpsAgent,
},
});
this.availableModels = [];
this.isInitialized = false;

View file

@ -1,5 +1,6 @@
import { OAuth2Client } from 'google-auth-library';
import * as http from 'http';
import * as https from 'https';
import { promises as fs } from 'fs';
import * as path from 'path';
import * as os from 'os';
@ -8,6 +9,20 @@ import open from 'open';
import { API_ACTIONS, formatExpiryTime } from '../common.js';
import { getProviderModels } from '../provider-models.js';
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
// --- Constants ---
const AUTH_REDIRECT_PORT = 8085;
const CREDENTIALS_DIR = '.gemini';
@ -177,7 +192,14 @@ async function* apply_anti_truncation_to_stream(service, model, requestBody) {
export class GeminiApiService {
constructor(config) {
this.authClient = new OAuth2Client(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET);
// 配置 OAuth2Client 使用自定义的 HTTP agent
this.authClient = new OAuth2Client({
clientId: OAUTH_CLIENT_ID,
clientSecret: OAUTH_CLIENT_SECRET,
transporterOptions: {
agent: httpsAgent,
},
});
this.availableModels = [];
this.isInitialized = false;

View file

@ -1,4 +1,6 @@
import axios from 'axios';
import * as http from 'http';
import * as https from 'https';
// Assumed OpenAI API specification service for interacting with third-party models
export class OpenAIApiService {
@ -12,8 +14,24 @@ export class OpenAIApiService {
this.useSystemProxy = config?.USE_SYSTEM_PROXY_OPENAI ?? false;
console.log(`[OpenAI] System proxy ${this.useSystemProxy ? 'enabled' : 'disabled'}`);
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const axiosConfig = {
baseURL: this.baseUrl,
httpAgent,
httpsAgent,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`

View file

@ -1,4 +1,6 @@
import axios from 'axios';
import * as http from 'http';
import * as https from 'https';
// OpenAI Responses API specification service for interacting with third-party models
export class OpenAIResponsesApiService {
@ -9,14 +11,39 @@ export class OpenAIResponsesApiService {
this.config = config;
this.apiKey = config.OPENAI_API_KEY;
this.baseUrl = config.OPENAI_BASE_URL || 'https://api.openai.com/v1';
// console.log(`[OpenAIResponsesApiService] Base URL: ${JSON.stringify(config)}`);
this.axiosInstance = axios.create({
this.useSystemProxy = config?.USE_SYSTEM_PROXY_OPENAI ?? false;
console.log(`[OpenAIResponses] System proxy ${this.useSystemProxy ? 'enabled' : 'disabled'}`);
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const axiosConfig = {
baseURL: this.baseUrl,
httpAgent,
httpsAgent,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
}
});
};
// 禁用系统代理以避免HTTPS代理错误
if (!this.useSystemProxy) {
axiosConfig.proxy = false;
}
this.axiosInstance = axios.create(axiosConfig);
}
async callApi(endpoint, body, isRetry = false, retryCount = 0) {

View file

@ -3,6 +3,8 @@ import crypto from 'crypto';
import path from 'node:path';
import { promises as fs, unlinkSync } from 'node:fs';
import * as os from 'os';
import * as http from 'http';
import * as https from 'https';
import open from 'open';
import { EventEmitter } from 'events';
import { randomUUID } from 'node:crypto';
@ -187,13 +189,28 @@ export class QwenApiService {
console.log('[Qwen] Initializing Qwen API Service...');
await this._initializeAuth();
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const axiosConfig = {
baseURL: DEFAULT_QWEN_BASE_URL,
httpAgent,
httpsAgent,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer `,
},
};
// 禁用系统代理
@ -501,8 +518,24 @@ export class QwenApiService {
try {
const { token, endpoint: qwenBaseUrl } = await this.getValidToken();
// 配置 HTTP/HTTPS agent 限制连接池大小,避免资源泄漏
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 5,
timeout: 120000,
});
const axiosConfig = {
baseURL: qwenBaseUrl,
httpAgent,
httpsAgent,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
@ -510,8 +543,6 @@ export class QwenApiService {
'X-DashScope-UserAgent': userAgent,
'X-DashScope-AuthType': 'qwen-oauth',
},
// 添加 HTTPS 代理修复相关配置
httpsAgent: undefined, // axios-https-proxy-fix 会自动处理
};
// 禁用系统代理