Files
ResourcePool.Docs/MIGRATION_GUIDE_PROXYPOOL_TO_SMARTPOOL.md
T

15 KiB

Migration Guide: ProxyPool → SmartPool

Hướng dẫn chi tiết để migrate code client từ ProxyPool (legacy) sang SmartPool (new system).


📋 Tổng Quan

ProxyPool (Legacy System)

  • Không có SDK client, phải tự implement gRPC/HTTP client
  • Field names: PascalCase (AccessToken, Host, Port)
  • Strategies: random, round_robin, least_used, least_delay, least_response_time
  • Không có client-side caching, batch logging, connection pooling tự động
  • Đơn giản, phù hợp cho use cases cơ bản

SmartPool (New System)

  • SDK client với nhiều tính năng tối ưu
  • Field names: snake_case (access_token, host, port)
  • Strategies: round_robin (default), random, least_delay, adaptive_ranking, alternative
  • Client-side caching, batch logging, connection pooling tự động
  • Exception handling chi tiết với typed exceptions
  • Performance cao hơn ~30-50%

🔄 Migration Steps

Step 1: Cài Đặt NuGet Package

Trước (ProxyPool):

<PackageReference Include="Icomm.ResourcePool.Abstractions" Version="x.x.x" />

Sau (SmartPool):

<PackageReference Include="Icomm.SmartPool.Proxy" Version="10.0.1" />

Step 2: Cập Nhật Configuration

Trước (ProxyPool):

{
  "TokenPoolOptions": {
    "Host": "10.9.3.70",
    "Port": 31287,
    "protocol": "Grpc"
  }
}

Sau (SmartPool):

{
  "SmartPool": {
    "Protocol": "Grpc",
    "Host": "10.9.3.70",
    "Port": 5001,
    "UseSecureConnection": false,
    "TimeoutMs": 30000,
    "EnableClientCache": true,
    "ClientCacheDurationSeconds": 30,
    "EnableBatchLogging": true,
    "LogBatchSize": 50,
    "EnableFireAndForgetLogging": true
  }
}

Lưu ý:

  • SmartPool sử dụng port khác (5001 cho gRPC, 5000 cho HTTP)
  • Cần cấu hình ConfigManager:AccessToken nếu muốn tự động inject vào requests

Step 3: Cập Nhật Service Registration

Trước (ProxyPool - gRPC):

using Icomm.ResourcePool.Abstractions;
using MagicOnion.Client;
using Grpc.Net.Client;

// Manual gRPC client setup
var channel = GrpcChannel.ForAddress("http://10.9.3.70:31287");
var client = MagicOnionClient.Create<IProxyService>(channel);

Sau (SmartPool):

using Icomm.SmartPool.Proxy.Extensions;

// In Startup.cs or Program.cs
services.AddSmartPoolClient(configuration);

// Or with explicit options
services.AddSmartPoolClient(configuration, options =>
{
    options.Protocol = SmartPoolProtocol.Grpc;
    options.Host = "10.9.3.70";
    options.Port = 5001;
});

Step 4: Cập Nhật Code Sử Dụng


📝 Code Migration Examples

Example 1: Basic Proxy Request

ProxyPool (gRPC)

using Icomm.ResourcePool.Abstractions;
using Icomm.ResourcePool.Abstractions.Requests;
using Icomm.ResourcePool.Abstractions.Responses;
using MagicOnion.Client;
using Grpc.Net.Client;

var channel = GrpcChannel.ForAddress("http://10.9.3.70:31287");
var client = MagicOnionClient.Create<IProxyService>(channel);

var request = new ProxyRequest
{
    AccessToken = "your-access-token"
};

var response = await client.GetProxy(request);
var proxy = response.Proxy;

// Use proxy
var handler = new HttpClientHandler
{
    Proxy = new WebProxy($"{proxy.Host}:{proxy.Port}")
    {
        Credentials = new NetworkCredential(proxy.AuthUsername, proxy.AuthPassword)
    }
};
var httpClient = new HttpClient(handler);

SmartPool

using Icomm.SmartPool.Proxy;
using Icomm.SmartPool.Abstractions.Requests;
using System.Net;

public class MyService
{
    private readonly ISmartPoolClient _smartPoolClient;

    public MyService(ISmartPoolClient smartPoolClient)
    {
        _smartPoolClient = smartPoolClient;
    }

    public async Task MakeRequestAsync()
    {
        // Get proxy as IWebProxy (ready to use)
        var request = new GetProxyRequest
        {
            access_token = "your-access-token"
        };
        
        var proxy = await _smartPoolClient.GetProxyAsync(request);

        if (proxy != null)
        {
            var handler = new HttpClientHandler { Proxy = proxy };
            var httpClient = new HttpClient(handler);
            // Use httpClient...
        }
    }
}

Key Changes:

  • Không cần tự setup gRPC channel
  • Method GetProxyAsync() trả về IWebProxy sẵn sàng sử dụng
  • Field names: access_token thay vì AccessToken

Example 2: Proxy Request với Filters

ProxyPool (HTTP REST API)

using RestSharp;
using Icomm.ResourcePool.Abstractions.Requests;
using Icomm.ResourcePool.Abstractions.Responses;

var client = new RestClient("http://10.9.3.70:31249");
var request = new RestRequest("/api/resource-pool/v1/ProxyPool/get-v2", Method.Post);
request.AddJsonBody(new ProxyRequestByFeature
{
    AccessToken = "your-access-token",
    Type = "httpv6",
    Strategy = "least_delay",
    TargetDomain = "facebook.com",
    Country = "VN"
});

var response = await client.ExecuteAsync<ProxyResponse>(request);
var proxy = response.Data.Proxy;

var proxyObj = new WebProxy($"{proxy.Host}:{proxy.Port}")
{
    Credentials = new NetworkCredential(proxy.AuthUsername, proxy.AuthPassword)
};

SmartPool

using Icomm.SmartPool.Proxy;
using Icomm.SmartPool.Abstractions.Requests;

var request = new GetProxyRequest
{
    access_token = "your-access-token",
    strategy = "least_delay",
    target_domain = "facebook.com",
    ip_version = "v6",
    protocol = "http",
    country = "VN"
};

var proxy = await _smartPoolClient.GetProxyAsync(request);

if (proxy != null)
{
    var handler = new HttpClientHandler { Proxy = proxy };
    var httpClient = new HttpClient(handler);
    // Use httpClient...
}

Key Changes:

  • Không cần HTTP client setup
  • Field names: ip_version, protocol thay vì Type
  • Strategy names: least_delay thay vì least_delay (giống nhau)
  • GetProxyAsync() trả về IWebProxy sẵn sàng

Example 3: Get Raw Proxy Information

ProxyPool

var response = await client.GetProxyV2(new ProxyRequestByFeature
{
    AccessToken = "your-access-token",
    Type = "httpv6",
    Strategy = "random",
    Country = "US"
});

var proxy = response.Proxy;
Console.WriteLine($"Proxy: {proxy.Host}:{proxy.Port}");
Console.WriteLine($"Country: {proxy.Country}");
Console.WriteLine($"Auth: {proxy.AuthUsername}:{proxy.AuthPassword}");

SmartPool

var request = new GetProxyRequest
{
    access_token = "your-access-token",
    strategy = "random",
    ip_version = "v6",
    protocol = "http",
    country = "US"
};

var proxyServer = await _smartPoolClient.GetRawProxyAsync(request);

if (proxyServer != null)
{
    Console.WriteLine($"Proxy: {proxyServer.host}:{proxyServer.port}");
    Console.WriteLine($"Country: {proxyServer.country}");
    Console.WriteLine($"Auth: {proxyServer.auth_username}:{proxyServer.auth_password}");
}

Key Changes:

  • Method: GetRawProxyAsync() thay vì GetProxyV2()
  • Field names: host, port, country, auth_username, auth_password (snake_case)

Example 4: Log Proxy Usage

ProxyPool

var logRequest = new ProxyLogRequest
{
    AccessToken = "your-access-token",
    ProxyId = proxy.Id,
    StatusCode = 200,
    ResponseTimeMs = 450
};

var logClient = new RestClient("http://10.9.3.70:31249");
var logRestRequest = new RestRequest("/api/resource-pool/v1/ProxyPool/used", Method.Post);
logRestRequest.AddJsonBody(logRequest);
await logClient.ExecuteAsync(logRestRequest);

SmartPool

var logRequest = new ProxyUsageLogRequest
{
    access_token = "your-access-token",
    proxy_id = proxyServer.id,
    target_domain = "facebook.com",
    status_code = 200,
    response_time_ms = 450
};

// Synchronous logging
await _smartPoolClient.LogProxyUsageAsync(logRequest);

// Or fire-and-forget (non-blocking)
_client.QueueLogProxyUsage(logRequest);

Key Changes:

  • Request type: ProxyUsageLogRequest thay vì ProxyLogRequest
  • Field names: proxy_id, status_code, response_time_ms (snake_case)
  • Có thêm target_domain field (required)
  • Hỗ trợ fire-and-forget và batch logging

Example 5: Alternative Strategy (Find Similar Proxy)

ProxyPool

var request = new ProxyRequestByFeature
{
    AccessToken = "your-access-token",
    Strategy = "least_used",
    RefererProxy = new ProxyServer { Id = 123 },
    Type = "httpv6",
    Country = "VN"
};

var response = await client.GetProxyV2(request);
var alternativeProxy = response.Proxy;

SmartPool

var request = new GetProxyRequest
{
    access_token = "your-access-token",
    strategy = "alternative",
    referer_proxy = new SmartProxyServer { id = 123 },
    ip_version = "v6",
    protocol = "http",
    country = "VN"
};

var alternativeProxy = await _smartPoolClient.GetRawProxyAsync(request);

Key Changes:

  • Strategy: alternative thay vì least_used
  • Field: referer_proxy.id thay vì RefererProxy.Id

🔀 Field Name Mapping

ProxyPool (PascalCase) SmartPool (snake_case)
AccessToken access_token
Host host
Port port
AuthUsername auth_username
AuthPassword auth_password
Type protocol (và ip_version)
Country country
TargetDomain target_domain
Strategy strategy
RefererProxy referer_proxy
ProxyId proxy_id
StatusCode status_code
ResponseTimeMs response_time_ms

🎯 Strategy Mapping

ProxyPool Strategy SmartPool Strategy Notes
random random Giống nhau
round_robin round_robin Giống nhau (default trong SmartPool)
least_delay least_delay Giống nhau
least_used alternative SmartPool dùng alternative với referer_proxy
least_response_time least_delay Tương đương
N/A adaptive_ranking Mới trong SmartPool

🚨 Breaking Changes

1. Port Numbers

  • ProxyPool: 31287 (gRPC), 31249 (HTTP)
  • SmartPool: 5001 (gRPC), 5000 (HTTP)

2. API Endpoints

  • ProxyPool: /api/resource-pool/v1/ProxyPool/*
  • SmartPool: /api/smart-pool/v1/SmartProxy/*

3. Request/Response Types

  • ProxyPool: ProxyRequest, ProxyRequestByFeature, ProxyResponse, ProxyServer
  • SmartPool: GetProxyRequest, SmartProxyResponse, SmartProxyServer

4. Field Naming Convention

  • ProxyPool: PascalCase
  • SmartPool: snake_case

5. Protocol Field

  • ProxyPool: Type = "http", "httpv6", "socks"
  • SmartPool: protocol = "http", "socks5" + ip_version = "v4", "v6"

Migration Checklist

  • Cài đặt NuGet package Icomm.SmartPool.Proxy
  • Cập nhật appsettings.json với SmartPool configuration
  • Thay thế service registration từ manual gRPC/HTTP setup sang AddSmartPoolClient()
  • Cập nhật dependency injection: inject ISmartPoolClient thay vì tự tạo client
  • Thay thế tất cả ProxyRequestGetProxyRequest
  • Thay thế tất cả ProxyRequestByFeatureGetProxyRequest
  • Cập nhật field names từ PascalCase sang snake_case
  • Cập nhật strategy names (nếu có least_usedalternative)
  • Cập nhật Type field → protocol + ip_version
  • Thay thế GetProxy() / GetProxyV2()GetProxyAsync() / GetRawProxyAsync()
  • Cập nhật proxy usage logging: ProxyLogRequestProxyUsageLogRequest
  • Cập nhật port numbers trong configuration
  • Test tất cả proxy requests
  • Test error handling với SmartPool exceptions
  • Cập nhật unit tests

🎁 Benefits After Migration

1. Performance Improvements

  • Connection Pooling: Giảm latency reconnect từ ~50-100ms xuống ~5ms
  • Client-side Caching: Giảm network calls ~90% khi cache hit
  • Batch Logging: Giảm N network calls → 1 call
  • Response Compression: Giảm payload size ~30-50%

2. Better Developer Experience

  • Typed exceptions với error codes
  • Try methods (TryGetProxyAsync()) không throw exceptions
  • Fire-and-forget logging (non-blocking)
  • Health check method (PingAsync())

3. Advanced Features

  • adaptive_ranking strategy (mới)
  • alternative strategy với referer proxy
  • Client-side caching tự động
  • Batch logging tự động

📚 Additional Resources


💡 Tips & Best Practices

1. Gradual Migration

  • Có thể migrate từng phần, không cần migrate toàn bộ cùng lúc
  • Có thể chạy song song ProxyPool và SmartPool trong giai đoạn transition

2. Error Handling

using Icomm.SmartPool.Proxy.Exceptions;

try
{
    var proxy = await _smartPoolClient.GetRawProxyAsync(request);
}
catch (AccessTokenRequiredException)
{
    // Handle missing access token
}
catch (NoAvailableProxiesException ex)
{
    // Handle no proxies available
    // Retry with different token or wait
}
catch (NoMatchingProxiesException)
{
    // Handle no matching proxies
    // Relax filters or use different strategy
}
catch (SmartPoolException ex)
{
    // Handle other SmartPool errors
    _logger.LogError(ex, "SmartPool error: {ErrorCode}", ex.ErrorCode);
}

3. Use Try Methods for Silent Failures

// Instead of try-catch, use Try methods
var proxy = await _smartPoolClient.TryGetRawProxyAsync(request);
if (proxy == null)
{
    // Fallback logic
    return;
}
// Use proxy...

4. Enable Client Caching for Better Performance

{
  "SmartPool": {
    "EnableClientCache": true,
    "ClientCacheDurationSeconds": 30
  }
}

5. Use Batch Logging for High Throughput

{
  "SmartPool": {
    "EnableBatchLogging": true,
    "LogBatchSize": 50,
    "LogBatchFlushIntervalMs": 5000,
    "EnableFireAndForgetLogging": true
  }
}

FAQ

Q: Có thể dùng cả ProxyPool và SmartPool cùng lúc không?

A: Có, nhưng không khuyến nghị. Nên migrate hoàn toàn sang SmartPool.

Q: SmartPool có backward compatible với ProxyPool không?

A: Không, SmartPool là hệ thống mới hoàn toàn với API và data model khác.

Q: Làm sao migrate nếu đang dùng HTTP REST API?

A: Có thể tiếp tục dùng HTTP REST API với SmartPool, nhưng khuyến nghị dùng SDK client để có nhiều tính năng tối ưu.

Q: Có cần thay đổi access token không?

A: Không, nhưng cần đảm bảo access token có mapping trong SmartPool system.

Q: Performance có cải thiện bao nhiêu?

A: Tùy use case, thường cải thiện 30-50% nhờ connection pooling, caching, và batch logging.


📞 Support

Nếu gặp vấn đề trong quá trình migration, vui lòng:

  1. Kiểm tra SmartPool Documentation
  2. Kiểm tra Troubleshooting Guide
  3. Liên hệ team phát triển

Last Updated: 2026-01-23