perf(api): 为所有API服务添加HTTP连接池配置防止资源泄漏
为Claude、OpenAI、Gemini、Qwen等API服务添加HTTP/HTTPS agent配置,设置keepAlive、maxSockets等参数以限制连接池大小,避免资源泄漏问题。同时统一了各服务的axios配置方式,提高网络请求的稳定性和性能。
This commit is contained in:
parent
b364341f67
commit
1c46bb547b
7 changed files with 149 additions and 11 deletions
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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}`
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 会自动处理
|
||||
};
|
||||
|
||||
// 禁用系统代理
|
||||
|
|
|
|||
Loading…
Reference in a new issue