npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

proxy-pool-manager

v1.0.8

Published

proxy manager

Readme

Proxy Manager SDK

一个功能强大的代理管理器 SDK,提供代理管理、HTTP 请求封装、自动代理轮换和健康检查等功能。

✨ 特性

  • 🪶 轻量级模式:无需 MongoDB,仅使用请求和队列功能
  • 🔄 智能代理管理:支持从 MongoDB 加载代理,自动验证和轮换(可选)
  • 🌐 HTTP 请求封装:内置 HTTP 客户端,支持自动代理切换或直接指定代理
  • 📊 代理健康检查:自动检测代理可用性,支持自定义检测规则(可选)
  • 🎯 多种代理策略:支持顺序、随机、故障转移三种策略
  • 📦 批量操作:支持批量插入和管理代理
  • 🔍 日志系统:基于 Winston 的完整日志记录
  • 异步队列:高效的异步任务处理机制
  • 🛡️ 类型安全:完整的 TypeScript 类型定义

📦 安装

npm install proxy-pool-manager

🚀 快速开始

轻量级模式(推荐,无需 MongoDB)

如果你只需要使用 HTTP 请求和队列功能,不需要代理管理,可以使用轻量级模式:

import { createProxyRequest } from 'proxy-pool-manager';

// 创建轻量级 SDK 实例(不连接 MongoDB)
const sdk = await createProxyRequest({
  maxRetries: 3,
  timeout: 30,
  logLevel: 'info'
});

// 发送 GET 请求
const response = await sdk.get('https://api.example.com/data', {
  params: { page: 1 }
});

// 在请求中直接指定代理(可选)
const responseWithProxy = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  proxy: 'http://proxy.example.com:8080',  // 直接指定代理
  timeout: 10
});

console.log(response.data);

轻量级模式 + 代理数组(支持异常时自动轮换)

如果你需要代理管理但不想连接 MongoDB,可以传入代理数组:

import { createProxyRequest } from 'proxy-pool-manager';

// 创建轻量级 SDK 实例 + 代理数组(不连接 MongoDB)
const sdk = await createProxyRequest({
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'sequential',  // 顺序策略
  maxRetries: 3,
  timeout: 30,
  logLevel: 'info'
});

// 发送请求,会自动使用代理管理器选择的代理
// 如果代理失败,会自动轮换到下一个代理并重试
const response = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  timeout: 10
});

console.log('当前使用的代理:', sdk.getCurrentProxy());
console.log('可用代理列表:', sdk.getAvailableProxies());

完整模式(包含代理管理功能)

如果需要代理管理功能(自动轮换、健康检查等),需要提供 MongoDB 连接:

import { createProxyRequest } from 'proxy-pool-manager';

// 创建完整 SDK 实例(包含代理管理)
const sdk = await createProxyRequest({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  proxyStrategy: 'sequential',
  logLevel: 'info',
  timeout: 30,
  proxyCheckOptions: {
    mainUrl: 'http://example.com/check',
    timeout: 10,
  }
});

// 发送 GET 请求(自动使用代理管理器选择的代理)
const response = await sdk.get('https://api.example.com/data', {
  params: { page: 1 }
});

// 或者为特定请求指定代理(优先级高于自动选择)
const responseWithSpecificProxy = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  proxy: 'http://specific-proxy.com:8080',  // 请求级代理优先
  timeout: 10
});

console.log(response.data);

完整模式 + 代理数组(支持异常时自动轮换)

如果需要代理管理功能,并且想预先设置代理列表:

import { createProxyRequest } from 'proxy-pool-manager';

// 创建完整 SDK 实例 + 代理数组(连接 MongoDB)
const sdk = await createProxyRequest({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'failover',  // 故障转移策略
  maxRetries: 3,
  timeout: 30,
  proxyCheckOptions: {
    mainUrl: 'http://example.com/check',
    timeout: 10,
  }
});

// 代理会被保存到 MongoDB,并支持自动轮换
// 如果请求失败,会自动轮换到下一个代理并重试
const response = await sdk.get('https://api.example.com/data');

添加代理

// 添加单个代理
await sdk.addProxy('proxy.example.com:8080:username:password');

// 批量添加代理
const count = await sdk.bulkInsertProxies([
  'proxy1.example.com:8080:user1:pass1',
  'proxy2.example.com:8080:user2:pass2',
  'proxy3.example.com:8080:user3:pass3',
]);

console.log(`成功添加 ${count} 个代理`);

HTTP 请求方法

// GET 请求
const getResponse = await sdk.get('https://api.example.com/users', {
  params: { page: 1, limit: 10 }
});

// POST 请求
const postResponse = await sdk.post('https://api.example.com/users', {
  data: { name: 'John', email: '[email protected]' },
  headers: { 'Content-Type': 'application/json' }
});

// PUT 请求
const putResponse = await sdk.put('https://api.example.com/users/1', {
  data: { name: 'Jane' }
});

// DELETE 请求
const deleteResponse = await sdk.delete('https://api.example.com/users/1');

// PATCH 请求
const patchResponse = await sdk.patch('https://api.example.com/users/1', {
  data: { status: 'active' }
});

// 自定义请求
const customResponse = await sdk.request({
  url: 'https://api.example.com/custom',
  method: 'POST',
  options: {
    data: { custom: 'data' },
    timeout: 60,
    proxy: 'specific-proxy.com:8080' // 使用特定代理
  }
});

📖 API 文档

ProxyRequestSDK

主 SDK 类,提供统一的 API 接口。

构造函数选项

interface SDKOptions {
  mongoUri?: string;                    // MongoDB 连接 URI(可选,启用代理管理时需要)
  maxRetries?: number;                  // 最大重试次数,默认 3
  timeout?: number;                     // 请求超时时间(秒),默认 30
  proxyStrategy?: ProxyStrategy;        // 代理策略,默认 'sequential'
  logLevel?: LogLevel;                  // 日志级别,默认 'info'
  instanceId?: string;                  // 实例 ID,用于多实例场景
  proxies?: string[];                   // 代理数组,支持异常时自动轮换
  proxy?: string;                       // 单个代理
  retryDelay?: number;                   // 重试间隔(毫秒),默认使用指数退避策略
  retryDelayBase?: number;              // 指数退避的基础延迟(毫秒),默认 1000
  retryDelayMultiplier?: number;        // 指数退避的倍数,默认 2
  proxyCheckEnabled?: boolean;          // 是否启用代理检查,默认 true
  proxyLimit?: number;                  // 代理加载限制,0 表示不加载,默认 0
  proxyCheckOptions?: {                 // 代理检查配置(启用代理管理时需要)
    mainUrl: string;                   // 代理检查主 URL(启用代理管理时必需)
    testUrls?: string[];                // 额外的测试 URL
    timeout?: number;                  // 检查超时时间(秒)
    successStatusCodes?: number[];     // 成功状态码列表
    checkInterval?: number;            // 检查间隔(毫秒)
    maxConsecutiveFails?: number;      // 最大连续失败次数
    maxResponseTime?: number;          // 最大响应时间(毫秒)
  };
}

配置说明:

  • 轻量级模式:不提供 mongoUriproxyCheckOptions,SDK 将以轻量级模式运行,不连接 MongoDB,不初始化代理管理功能
  • 轻量级模式 + 代理数组:提供 proxiesproxy 但不提供 mongoUri,SDK 将以轻量级模式运行,代理仅存储在内存中,支持异常时自动轮换
  • 完整模式:提供 mongoUriproxyCheckOptions,SDK 将启用代理管理功能
  • 完整模式 + 代理数组:同时提供 mongoUriproxies,代理会被保存到 MongoDB,并支持异常时自动轮换
  • 禁用代理检查:设置 proxyCheckEnabled: false 可禁用代理检查
  • 不加载代理:设置 proxyLimit: 0 可不从数据库加载代理

方法

请求方法
  • get<T>(url: string, params?: Record<string, string>, options?: RequestOptions): Promise<HttpResponse<T>>
  • post<T>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>
  • put<T>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>
  • delete<T>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>
  • patch<T>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>
  • request<T>(config: RequestConfig): Promise<HttpResponse<T>>
代理管理方法(仅在启用代理管理功能时可用)
  • addProxy(proxyUrl: string): Promise<ProxyItem | null> - 添加代理
  • deleteProxy(proxyUrl: string): Promise<boolean> - 删除代理
  • getAvailableProxies(): string[] - 获取可用代理列表
  • getCurrentProxy(): string | null - 获取当前使用的代理
  • rotateProxy(): Promise<string | null> - 轮换到下一个代理
  • setProxyStrategy(strategy: ProxyStrategy): void - 设置代理策略
  • checkProxy(proxy?: string): Promise<boolean> - 检查代理可用性
  • triggerProxyCheck(): Promise<void> - 触发代理检查
  • getProxyDetails(proxyUrl: string): ProxyItem | undefined - 获取代理详情
  • hasProxyManagement(): boolean - 检查是否启用了代理管理功能
批量操作
  • bulkInsertProxies(proxyUrls: string[]): Promise<number> - 批量插入代理
统计信息
  • getProxyStats(): Promise<ProxyStats> - 获取代理统计信息
  • getQueueStats(): QueueStats - 获取队列统计信息
工具方法
  • waitForReady(): Promise<void> - 等待初始化完成
  • setLogLevel(level: LogLevel): void - 设置日志级别
  • getLogLevel(): LogLevel - 获取当前日志级别
  • getInstanceId(): string - 获取实例 ID
  • destroy(): Promise<void> - 清理资源

代理策略

支持三种代理选择策略,每种策略都有不同的使用场景和特点:

1. sequential(顺序策略)

特点:

  • 按照代理列表的顺序依次使用代理
  • 每次请求后自动切换到下一个代理
  • 简单、可预测,适合需要均匀分配请求的场景

使用场景:

  • 需要均匀分配请求到各个代理
  • 代理质量相近,不需要特别优化
  • 需要可预测的代理使用顺序

示例:

const sdk = await createProxyRequest({
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'sequential'
});

// 第一次请求使用 proxy1
const response1 = await sdk.get('https://api.example.com/data');
// 第二次请求使用 proxy2
const response2 = await sdk.get('https://api.example.com/data');
// 第三次请求使用 proxy3
const response3 = await sdk.get('https://api.example.com/data');
// 第四次请求又回到 proxy1(循环)

轮换机制:

  • 请求失败时,自动切换到下一个代理并重试
  • 如果所有代理都失败,停止重试

2. random(随机策略)

特点:

  • 从可用代理中随机选择一个使用
  • 避免重复使用同一个代理,直到所有代理都被使用过
  • 适合需要避免代理被过度使用的场景

使用场景:

  • 需要避免某些代理被过度使用
  • 代理质量相近,随机分配即可
  • 需要分散请求负载

示例:

const sdk = await createProxyRequest({
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'random'
});

// 每次请求随机选择一个代理
const response1 = await sdk.get('https://api.example.com/data');
const response2 = await sdk.get('https://api.example.com/data');
const response3 = await sdk.get('https://api.example.com/data');

轮换机制:

  • 随机选择代理,避免重复使用
  • 当所有代理都被使用过后,重置使用记录
  • 请求失败时,从剩余未使用的代理中随机选择并重试

3. failover(故障转移策略)⭐ 推荐

特点:

  • 智能选择最佳可用代理
  • 根据代理的历史表现(失败率、响应时间)自动选择最优代理
  • 优先使用失败率低、响应时间短的代理
  • 适合需要高可用性和性能的场景
  • 不需要 MongoDB:统计信息存储在内存中,实时更新

选择优先级:

  1. 连续失败次数:优先选择连续失败次数最少的代理
  2. 失败率:在连续失败次数相同的情况下,选择失败率最低的代理
  3. 响应时间:在失败率相同的情况下,选择平均响应时间最短的代理

使用场景:

  • 需要高可用性和性能的场景
  • 代理质量差异较大,需要自动选择最优代理
  • 需要自动排除故障代理
  • 对请求成功率要求较高的场景
  • 轻量级模式:不需要 MongoDB,仅使用内存统计

示例:

// 轻量级模式 + failover(不需要 MongoDB)
const sdk1 = await createProxyRequest({
  proxies: [
    'proxy1.example.com:8080:user1:pass1',  // 高质量代理
    'proxy2.example.com:8080:user2:pass2',  // 中等质量代理
    'proxy3.example.com:8080:user3:pass3'   // 低质量代理
  ],
  proxyStrategy: 'failover'  // 不需要 MongoDB,统计信息存储在内存中
});

// 自动选择最优代理(失败率低、响应时间短)
const response = await sdk1.get('https://api.example.com/data');
// 完整模式 + failover(使用 MongoDB 持久化统计信息)
const sdk2 = await createProxyRequest({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'failover',
  proxyCheckOptions: {
    mainUrl: 'http://example.com/check'
  }
});

// 统计信息会被持久化到 MongoDB,重启后仍然保留历史数据
const response = await sdk2.get('https://api.example.com/data');

统计信息说明:

  • 内存模式(不提供 mongoUri):

    • 统计信息存储在内存中,实时更新
    • 重启后统计信息会重置
    • 适合临时使用或单次运行场景
  • 持久化模式(提供 mongoUri):

    • 统计信息会保存到 MongoDB
    • 重启后仍然保留历史数据
    • 适合长期运行或需要历史数据的场景

轮换机制:

  • 请求失败时,自动标记当前代理的失败次数
  • 下次请求时,自动选择表现最好的代理
  • 连续失败超过阈值的代理会被标记为无效,不再使用
  • 代理恢复后(成功请求),会自动重新启用

故障转移流程:

1. 选择最优代理(连续失败次数最少 → 失败率最低 → 响应时间最短)
2. 发送请求
3. 如果失败:
   - 增加代理的失败计数
   - 如果连续失败次数超过阈值,标记为无效
   - 下次请求时自动选择下一个最优代理
4. 如果成功:
   - 重置连续失败次数
   - 更新平均响应时间
   - 如果之前被标记为无效,自动恢复为有效状态

性能优化:

  • 自动排除故障代理,避免重复尝试
  • 优先使用高质量代理,提高成功率
  • 动态调整代理优先级,适应代理质量变化

重要说明:

  • 不需要 MongoDB:failover 策略可以在轻量级模式下使用,统计信息存储在内存中
  • 实时更新:每次请求后,统计信息会立即更新(成功/失败次数、响应时间等)
  • 自动学习:随着请求的进行,系统会自动学习每个代理的质量,并优先使用高质量代理
  • 💡 MongoDB 的作用:如果提供 MongoDB,统计信息会被持久化,重启后仍然保留历史数据,有助于更快地识别高质量代理

重试间隔配置

支持两种重试间隔策略:

1. 指数退避策略(默认)

每次重试前等待时间递增,适合大多数场景:

const sdk = await createProxyRequest({
  maxRetries: 3,
  retryDelayBase: 1000,      // 基础延迟 1000ms(默认)
  retryDelayMultiplier: 2    // 倍数 2(默认)
});

// 重试间隔:第1次 1000ms,第2次 2000ms,第3次 4000ms

计算公式: waitTime = retryDelayBase × retryDelayMultiplier^(attempt-1)

示例:

  • 第1次重试:1000ms × 2^0 = 1000ms
  • 第2次重试:1000ms × 2^1 = 2000ms
  • 第3次重试:1000ms × 2^2 = 4000ms

2. 固定间隔策略

每次重试前等待固定时间,适合需要稳定重试间隔的场景:

const sdk = await createProxyRequest({
  maxRetries: 3,
  retryDelay: 2000  // 每次重试都等待 2000ms
});

// 重试间隔:每次都是 2000ms

使用场景:

  • 指数退避:适合网络不稳定、需要避免服务器压力的场景
  • 固定间隔:适合需要稳定重试节奏、便于调试的场景

自定义配置示例:

// 快速重试(500ms 基础,1.5倍递增)
const sdk1 = await createProxyRequest({
  retryDelayBase: 500,
  retryDelayMultiplier: 1.5
  // 重试间隔:500ms → 750ms → 1125ms
});

// 慢速重试(2000ms 基础,2倍递增)
const sdk2 = await createProxyRequest({
  retryDelayBase: 2000,
  retryDelayMultiplier: 2
  // 重试间隔:2000ms → 4000ms → 8000ms
});

// 固定间隔 3 秒
const sdk3 = await createProxyRequest({
  retryDelay: 3000
  // 重试间隔:每次都是 3000ms
});

日志级别

  • none - 不记录日志
  • error - 仅记录错误
  • warn - 记录警告和错误
  • info - 记录信息、警告和错误(默认)
  • debug - 记录调试信息
  • verbose - 记录所有详细信息

🔧 高级用法

使用场景选择

场景 1:仅需要 HTTP 请求功能(推荐轻量级模式)

// 不需要代理管理,只需要发送 HTTP 请求
const sdk = await createProxyRequest({
  maxRetries: 3,
  timeout: 30,
  logLevel: 'info'
});

// 直接使用,无需 MongoDB
const response = await sdk.get('https://api.example.com/data');

场景 2:需要临时使用代理

// 轻量级模式 + 直接指定代理
const sdk = await createProxyRequest({
  maxRetries: 3,
  timeout: 30
});

// 在请求中直接指定代理
const response = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  proxy: 'http://proxy.example.com:8080:user:pass'  // 直接指定代理
});

场景 2.5:使用代理数组 + 异常时自动轮换(推荐)

// 轻量级模式 + 代理数组(不连接 MongoDB)
const sdk = await createProxyRequest({
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'failover',  // 故障转移策略
  maxRetries: 3,
  timeout: 30
});

// 发送请求,如果代理失败会自动轮换到下一个代理
const response = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  timeout: 10
});

场景 3:需要代理管理功能

// 完整模式,启用代理管理
const sdk = await createProxyRequest({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  proxyCheckOptions: {
    mainUrl: 'http://example.com/check',
    timeout: 10,
  }
});

// 添加代理到管理器
await sdk.addProxy('proxy1.example.com:8080:user1:pass1');

// 自动使用代理管理器选择的代理
const response = await sdk.get('https://api.example.com/data');

场景 4:禁用代理检查,但仍使用代理管理

// 使用代理管理,但禁用代理检查
const sdk = await createProxyRequest({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  proxyCheckEnabled: false,  // 禁用代理检查
  proxyLimit: 0,             // 不加载代理
  proxyCheckOptions: {
    mainUrl: 'http://example.com/check',  // 仍然需要提供(用于后续启用)
  }
});

// 手动添加代理,不进行自动检查
await sdk.addProxy('proxy.example.com:8080:user:pass');

多实例场景

import { initializeServices } from 'proxy-pool-manager';

// 创建多个独立的 SDK 实例
const sdk1 = await initializeServices({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  instanceId: 'instance-1',
  proxyCheckOptions: {
    mainUrl: 'http://example.com/check'
  }
});

const sdk2 = await initializeServices({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  instanceId: 'instance-2',
  proxyCheckOptions: {
    mainUrl: 'http://example.com/check'
  }
});

自定义代理检查

const sdk = await createProxyRequest({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  proxyCheckOptions: {
    mainUrl: 'https://httpbin.org/ip',
    testUrls: [
      'https://api.ipify.org?format=json',
      'https://ipinfo.io/json'
    ],
    timeout: 15,
    successStatusCodes: [200, 201],
    checkInterval: 60000,        // 每分钟检查一次
    maxConsecutiveFails: 3,      // 连续失败3次后标记为无效
    maxResponseTime: 5000         // 最大响应时间5秒
  }
});

代理使用方式

1. 强制直连(noProxy)

当某次请求需要完全不使用代理(包括所有重试)时,可传 noProxy: true。此时无论 createProxyRequest 是否配置了代理、是否传了请求级 proxy,该请求及重试都会直连。

// 本次请求及重试均不走代理
const response = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  noProxy: true,  // 强制直连,优先级高于 proxy
  timeout: 10
});

2. 直接指定代理(轻量级模式和完整模式都支持)

// 为特定请求指定代理
const response = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  proxy: 'http://proxy.example.com:8080:user:pass',  // 直接指定代理
  timeout: 10
});

3. 使用代理数组(支持异常时自动轮换)

// 创建 SDK 时传入代理数组
const sdk = await createProxyRequest({
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'sequential',  // 顺序策略
  maxRetries: 3
});

// 发送请求,会自动使用代理管理器选择的代理
// 如果代理失败,会自动轮换到下一个代理并重试
const response = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  timeout: 10
});

// 查看当前使用的代理
console.log('当前代理:', sdk.getCurrentProxy());
console.log('可用代理:', sdk.getAvailableProxies());

4. 自动使用代理管理器选择的代理(完整模式)

// 先添加代理到管理器
await sdk.addProxy('proxy1.example.com:8080:user1:pass1');
await sdk.addProxy('proxy2.example.com:8080:user2:pass2');

// 不指定代理,自动使用代理管理器选择的代理
const response = await sdk.post('http://your-api.com/request', {
  url: 'https://api.example.com/data',
  method: 'GET',
  // 不指定 proxy,会自动使用 ProxyManager 选择的代理
  timeout: 10
});

5. 代理优先级

代理使用遵循以下优先级:

  1. 强制直连options.noProxy === true)- 最高优先级,该请求及所有重试均不使用代理
  2. 请求级代理options.proxy)- 指定时使用该代理
  3. 代理管理器自动选择 - 如果启用了代理管理且没有指定请求级代理
  4. 无代理 - 如果都没有,则直接请求(不使用代理)

6. 异常时自动轮换

当请求失败时(超时、连接错误等),系统会自动轮换到下一个代理并重试:

const sdk = await createProxyRequest({
  proxies: [
    'proxy1.example.com:8080:user1:pass1',
    'proxy2.example.com:8080:user2:pass2',
    'proxy3.example.com:8080:user3:pass3'
  ],
  proxyStrategy: 'failover',  // 推荐使用故障转移策略
  maxRetries: 3  // 最多重试3次,每次失败会自动轮换代理
});

// 如果 proxy1 失败,会自动尝试 proxy2,再失败会尝试 proxy3
const response = await sdk.get('https://api.example.com/data');

轮换机制说明:

  • 只有在使用代理管理器选择的代理时才会轮换(如果请求中直接指定了代理,不会轮换)
  • 支持两种重试间隔策略:
    • 指数退避策略(默认):每次重试前等待时间递增,公式为 retryDelayBase × retryDelayMultiplier^(attempt-1)
      • 默认值:基础延迟 1000ms,倍数 2
      • 示例:第1次重试等待 1000ms,第2次等待 2000ms,第3次等待 4000ms
    • 固定间隔策略:设置 retryDelay 后,每次重试前等待固定时间
      • 示例:设置 retryDelay: 2000,每次重试都等待 2000ms
  • 支持三种代理策略,每种策略的轮换方式不同:
    • sequential:按顺序切换到下一个代理
    • random:从剩余未使用的代理中随机选择
    • failover:自动选择表现最好的代理(推荐)

不同策略的轮换行为:

| 策略 | 首次选择 | 失败后轮换 | 特点 | |------|---------|-----------|------| | sequential | 第一个代理 | 按顺序切换到下一个 | 简单、可预测 | | random | 随机选择 | 从剩余代理中随机选择 | 分散负载 | | failover | 最优代理 | 选择下一个最优代理 | 智能、高效 ⭐ |

故障检测:

系统会自动检测以下类型的错误并触发代理轮换:

  • 连接超时(TimeoutError)
  • 连接被拒绝(ECONNREFUSED)
  • 网络错误(网络相关关键词)
  • HTTP 错误(根据配置)

代理状态管理:

  • 连续失败超过阈值的代理会被标记为无效
  • 无效代理不会参与选择,直到恢复
  • 代理恢复后(成功请求),会自动重新启用

6. 检查代理管理功能状态

// 检查是否启用了代理管理功能
if (sdk.hasProxyManagement()) {
  console.log('代理管理功能已启用');
  // 可以使用代理管理相关方法
  await sdk.addProxy('proxy.example.com:8080');
} else {
  console.log('轻量级模式,仅支持直接指定代理');
  // 只能通过 options.proxy 指定代理
}

代理统计信息

const stats = await sdk.getProxyStats();
console.log({
  total: stats.total,           // 总代理数
  valid: stats.valid,            // 有效代理数
  invalid: stats.invalid,       // 无效代理数
  available: stats.available    // 可用代理数
});

// 获取队列统计
const queueStats = sdk.getQueueStats();
console.log({
  length: queueStats.length,     // 队列长度
  running: queueStats.running,   // 运行中任务数
  concurrency: queueStats.concurrency, // 并发数
  idle: queueStats.idle          // 是否空闲
});

批量插入代理

import { bulkInsertProxyUrls } from 'proxy-pool-manager';

const count = await bulkInsertProxyUrls({
  mongoUri: 'mongodb://localhost:27017/proxy_db',
  proxyUrls: [
    'proxy1.com:8080:user1:pass1',
    'proxy2.com:8080:user2:pass2',
    // ... 更多代理
  ],
  batchSize: 500,      // 每批处理500个
  concurrency: 4,      // 并发4个批次
  logLevel: 'info'
});

console.log(`成功插入 ${count} 个代理`);

📋 异步队列使用

AsyncQueueSingleton 是一个强大的异步任务队列管理器,支持并发控制、优先级任务、多实例等特性。

队列快速开始

import { AsyncQueueSingleton } from 'proxy-pool-manager';

// 创建队列实例
const queue = AsyncQueueSingleton.getInstance('my-queue', {
  concurrency: 3,        // 并发数:同时执行3个任务
  autoStart: true,      // 自动开始执行
  logLevel: 'info',
  onDrain: () => {
    console.log('所有任务完成!');
  },
  onError: (error) => {
    console.error('任务执行错误:', error);
  },
  onSuccess: (result) => {
    console.log('任务成功:', result);
  }
});

// 添加单个任务
const result = await queue.add({ id: 1, name: '任务1' });
console.log('任务结果:', result);

// 批量添加任务
const tasks = [
  { id: 1, name: '任务1' },
  { id: 2, name: '任务2' },
  { id: 3, name: '任务3' }
];
const results = await queue.addBatch(tasks);
console.log('批量任务结果:', results);

自定义任务处理器

// 创建队列并设置自定义处理器
const queue = AsyncQueueSingleton.getInstance('custom-queue', {
  concurrency: 2,
  logLevel: 'debug'
});

// 设置任务处理器
queue.setTaskHandler(async (task: any) => {
  console.log(`处理任务: ${task.name}`);
  
  // 模拟异步操作
  await new Promise(resolve => setTimeout(resolve, task.duration));
  
  // 返回处理结果
  return {
    taskId: task.id,
    status: 'completed',
    timestamp: new Date().toISOString()
  };
});

// 添加任务
const result = await queue.add({ id: 1, name: '处理文件', duration: 1000 });
console.log(result);

队列控制

const queue = AsyncQueueSingleton.getInstance('control-queue', {
  concurrency: 2,
  autoStart: false  // 手动控制启动
});

// 添加任务(队列已暂停,不会立即执行)
const promise = queue.add({ id: 1, name: '任务1' });

// 暂停队列
queue.pause();
console.log('队列已暂停');

// 恢复队列
queue.resume();
console.log('队列已恢复');

// 等待任务完成
const result = await promise;

优先级任务

const queue = AsyncQueueSingleton.getInstance('priority-queue', {
  concurrency: 2
});

// 普通任务(priority = 0,默认)
await queue.add({ id: 1, name: '普通任务1' }, 0);

// 高优先级任务(priority > 0,会插入到队列前面)
await queue.add({ id: 2, name: '高优先级任务' }, 1);

// 最高优先级任务
await queue.add({ id: 3, name: '紧急任务' }, 2);

队列状态监控

const queue = AsyncQueueSingleton.getInstance('monitor-queue');

// 获取队列统计信息
const stats = queue.stats;
console.log({
  length: stats.length,        // 队列中等待的任务数
  running: stats.running,      // 正在执行的任务数
  concurrency: stats.concurrency, // 并发数
  idle: stats.idle             // 是否空闲
});

// 获取队列长度
console.log('队列长度:', queue.length);

// 获取运行中任务数
console.log('运行中任务:', queue.running);

// 检查队列是否空闲
if (queue.idle) {
  console.log('队列空闲,所有任务已完成');
}

多实例队列

// 创建不同类型的队列实例
const imageQueue = AsyncQueueSingleton.getInstance('image-processing', {
  concurrency: 2,
  taskHandler: async (task) => {
    console.log(`处理图片: ${task.filename}`);
    await new Promise(resolve => setTimeout(resolve, 2000));
    return `图片处理完成: ${task.filename}`;
  }
});

const dataQueue = AsyncQueueSingleton.getInstance('data-processing', {
  concurrency: 5,
  taskHandler: async (task) => {
    console.log(`处理数据: ${task.id}`);
    await new Promise(resolve => setTimeout(resolve, 500));
    return `数据处理完成: ${task.id}`;
  }
});

// 同时使用多个队列
const [imageResults, dataResults] = await Promise.all([
  imageQueue.addBatch(imageTasks),
  dataQueue.addBatch(dataTasks)
]);

// 获取所有实例名称
const instanceNames = AsyncQueueSingleton.getInstanceNames();
console.log('所有队列实例:', instanceNames);

// 获取所有实例的统计信息
const allStats = AsyncQueueSingleton.getAllInstancesStats();
console.log('所有队列统计:', allStats);

动态调整并发数

const queue = AsyncQueueSingleton.getInstance('dynamic-queue', {
  concurrency: 3
});

// 动态更新并发数
queue.updateConcurrency(5);
console.log('并发数已更新为:', queue.stats.concurrency);

泛型支持

// 使用泛型指定返回类型
interface ApiResponse {
  endpoint: string;
  status: string;
  data: any;
}

const apiQueue = AsyncQueueSingleton.getInstance<ApiResponse>('api-queue', {
  concurrency: 3
});

apiQueue.setTaskHandler(async (task: any): Promise<ApiResponse> => {
  // 模拟API请求
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  return {
    endpoint: task.url,
    status: 'success',
    data: { result: 'ok' }
  };
});

const response = await apiQueue.add({ url: '/api/users' });
// response 的类型是 ApiResponse
console.log(response.endpoint, response.status);

实际应用场景

1. API 请求限流

const apiQueue = AsyncQueueSingleton.getInstance('api-rate-limit', {
  concurrency: 5  // 限制同时最多5个API请求
});

apiQueue.setTaskHandler(async (apiCall: any) => {
  const response = await fetch(apiCall.url);
  return await response.json();
});

// 添加多个API请求,自动限流
const results = await apiQueue.addBatch([
  { url: 'https://api.example.com/users' },
  { url: 'https://api.example.com/orders' },
  { url: 'https://api.example.com/products' }
]);

2. 文件批量处理

const fileQueue = AsyncQueueSingleton.getInstance('file-processing', {
  concurrency: 2,
  onDrain: () => console.log('所有文件处理完成')
});

fileQueue.setTaskHandler(async (file: any) => {
  // 处理文件
  await processFile(file);
  return `文件 ${file.name} 处理完成`;
});

const files = [
  { name: 'document1.pdf', size: 1024 },
  { name: 'image1.jpg', size: 2048 }
];

const results = await fileQueue.addBatch(files);

3. 数据库操作队列

const dbQueue = AsyncQueueSingleton.getInstance('database-queue', {
  concurrency: 1  // 串行执行,避免数据库锁冲突
});

dbQueue.setTaskHandler(async (operation: any) => {
  // 执行数据库操作
  await db.execute(operation);
  return `操作完成: ${operation.type}`;
});

await dbQueue.add({ type: 'INSERT', table: 'users', data: {...} });

队列清理

// 销毁指定队列实例
AsyncQueueSingleton.destroyInstance('my-queue');

// 销毁所有队列实例
AsyncQueueSingleton.destroyAllInstances();

AsyncQueue API 参考

静态方法

  • getInstance<T>(name: string, options?: AsyncQueueOptions<T>): AsyncQueueSingleton<T> - 获取或创建队列实例
  • getInstanceNames(): string[] - 获取所有实例名称
  • getAllInstancesStats(): Record<string, QueueStats> - 获取所有实例统计信息
  • hasInstance(name: string): boolean - 检查实例是否存在
  • getExistingInstance<T>(name: string): AsyncQueueSingleton<T> | null - 获取已存在的实例
  • destroyInstance(name: string): void - 销毁指定实例
  • destroyAllInstances(): void - 销毁所有实例

实例方法

  • add(task: Task, priority?: number): Promise<T> - 添加任务
  • addBatch(tasks: Task[], priority?: number): Promise<T[]> - 批量添加任务
  • setTaskHandler(handler: (task: Task) => Promise<T>): void - 设置任务处理器
  • updateConcurrency(newConcurrency: number): void - 更新并发数
  • pause(): this - 暂停队列
  • resume(): this - 恢复队列
  • destroy(): void - 销毁队列
  • setLogLevel(level: LogLevel): void - 设置日志级别
  • getLogLevel(): LogLevel - 获取日志级别
  • getName(): string - 获取实例名称

属性

  • length: number - 队列长度
  • running: number - 运行中任务数
  • idle: boolean - 是否空闲
  • stats: QueueStats - 队列统计信息

配置选项

interface AsyncQueueOptions<T> {
  concurrency?: number;        // 并发数,默认 100
  autoStart?: boolean;          // 自动开始,默认 true
  logLevel?: LogLevel;          // 日志级别
  onDrain?: () => void;         // 队列排空回调
  onError?: (error: Error) => void;  // 错误回调
  onSuccess?: (result: T) => void;   // 成功回调
  taskHandler?: (task: Task) => Promise<T>;  // 任务处理器
}

🗄️ MongoDB 数据结构

代理数据存储在 MongoDB 中,集合结构如下:

interface ProxyDocument {
  url: string;                    // 代理 URL(格式:host:port:username:password)
  totalRequests: number;          // 总请求数
  failCount: number;              // 失败次数
  avgResponseTime: number;        // 平均响应时间(毫秒)
  lastCheckTime: number;          // 最后检查时间(时间戳)
  consecutiveFails: number;       // 连续失败次数
  status: 'valid' | 'invalid';    // 状态
  createdAt: Date;               // 创建时间
  updatedAt: Date;               // 更新时间
}

📝 类型定义

完整的 TypeScript 类型定义已包含在包中:

import type {
  RequestOptions,
  HttpResponse,
  ProxyStrategy,
  ProxyItem,
  ProxyCheckOptions,
  LogLevel
} from 'proxy-pool-manager';

⚠️ 注意事项

  1. 轻量级模式 vs 完整模式

    • 轻量级模式:不提供 mongoUriproxyCheckOptions,不连接 MongoDB,仅使用请求和队列功能
    • 完整模式:提供 mongoUriproxyCheckOptions,启用代理管理功能,需要 MongoDB 连接
  2. MongoDB 连接:仅在启用代理管理功能时需要,确保 MongoDB 服务正在运行且连接 URI 正确

  3. 代理格式:代理 URL 格式为 host:port:username:passwordhttp://host:port:username:password

  4. 代理使用

    • 轻量级模式下,只能通过 options.proxy 直接指定代理
    • 完整模式下,可以自动使用代理管理器选择的代理,也可以直接指定代理(优先级更高)
  5. 初始化等待:SDK 初始化是异步的,使用 waitForReady() 确保初始化完成

  6. 资源清理:使用完毕后调用 destroy() 方法清理资源

  7. 并发限制:代理检查的并发数可通过 maxConcurrentChecks 配置

  8. 禁用功能

    • 设置 proxyCheckEnabled: false 可禁用代理检查
    • 设置 proxyLimit: 0 可不从数据库加载代理