Files
ResourcePool.Docs/docs/src/Icomm.SmartPool.Proxy/README.md
T

19 KiB

Icomm.SmartPool.Proxy

Client SDK for SmartPool proxy management system. Supports both gRPC and HTTP protocols.

📖 Xem tài liệu chi tiết: SDK_DOCUMENTATION.md

📌 Migration note (quan trọng): CLIENT_MIGRATION_NOTES.md

Features

  • Dual Protocol: gRPC (MagicOnion) và HTTP REST API
  • 5 Chiến lược: Random, Round Robin, Least Delay, Adaptive Ranking, Alternative
  • Tối ưu hiệu suất: Keep-alive, Connection pooling, Client caching, Compression
  • Batch Logging: Ghi log hiệu quả với batch processing
  • Fire-and-Forget: Non-blocking logging
  • Compact Response: Giảm payload size ~50-60%

Installation

Prerequisites

Đảm bảo bạn đã cấu hình NuGet source ic trong project:

# Thêm NuGet source (nếu chưa có)
dotnet nuget add source <nuget-feed-url> --name ic

Install via NuGet Package

Cài đặt package từ NuGet repository:

dotnet add package --source ic --version 10.0.1 Icomm.SmartPool.Proxy

Hoặc thêm vào .csproj file:

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

Và cấu hình NuGet source trong nuget.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="ic" value="<nuget-feed-url>" />
  </packageSources>
</configuration>

Quick Start

Configuration

Add to appsettings.json:

{
  "SmartPool": {
    "Protocol": "Grpc",
    "Host": "localhost",
    "Port": 5001,
    "UseSecureConnection": false,
    "DefaultAccessToken": "your-access-token",
    "RequestTimeoutMs": 30000,
    "LogRequestTimeoutMs": 3000,
    "LogRetryMaxBatchSize": 50,
    "LogRetryFlushIntervalMs": 5000
  }
}

Register in DI Container

using Icomm.SmartPool.Proxy.Extensions;

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

Use in Your Code

public class MyService
{
    private readonly ISmartPoolClient _smartPoolClient;

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

    public async Task MakeRequestAsync()
    {
        // Get proxy as IWebProxy (ready for HttpClient)
        var request = new GetProxyRequest
        {
            access_token = "your-token",
            strategy = "least_delay",
            target_domain = "facebook.com",
            ip_version = "v6"
        };
        
        var proxy = await _smartPoolClient.GetProxyAsync(request);

        if (proxy != null)
        {
            var handler = new HttpClientHandler { Proxy = proxy };
            var httpClient = new HttpClient(handler);
            
            var response = await httpClient.GetAsync("https://facebook.com");
            
            // Log usage
            var logRequest = new ProxyUsageLogRequest
            {
                access_token = "your-token",
                proxy_id = 123, // Get from GetRawProxyAsync if needed
                target_domain = "facebook.com",
                status_code = (int)response.StatusCode,
                response_time_ms = 450
            };
            await _smartPoolClient.LogProxyUsageAsync(logRequest);
        }
    }
}

Advanced Usage

Get Raw Proxy Information

var request = new GetProxyRequest
{
    access_token = "your-token",
    strategy = "adaptive_ranking",
    target_domain = "facebook.com",
    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}");
}

Alternative Proxy Strategy

var request = new GetProxyRequest
{
    access_token = "your-token",
    strategy = "alternative",
    referer_proxy = new SmartProxyServer { id = 123 } // Current proxy that failed
};

var alternativeProxy = await _smartPoolClient.GetRawProxyAsync(request);

Strategies

  • random: Random selection
  • round_robin: Balanced distribution (default)
  • least_delay: Fastest proxy (requires target_domain)
  • adaptive_ranking: Highest success rate (requires target_domain)
  • alternative: Similar proxy replacement (requires referer_proxy.id)

Protocol Selection

services.AddSmartPoolClient(options =>
{
    options.Protocol = SmartPoolProtocol.Grpc;
    options.Host = "api.example.com";
    options.Port = 5001;
});

Pros: High performance, binary protocol, streaming support

HTTP

services.AddSmartPoolClient(options =>
{
    options.Protocol = SmartPoolProtocol.Http;
    options.Host = "api.example.com";
    options.Port = 5000;
});

Pros: Standard REST API, easier debugging, firewall-friendly

Error Handling

SDK cung cấp exception handling chi tiết với các exception types tương ứng với error codes từ server:

Exception Types

using Icomm.SmartPool.Proxy.Exceptions;

try
{
    var proxy = await _smartPoolClient.GetRawProxyAsync(request);
    // Use proxy...
}
catch (AccessTokenRequiredException)
{
    // Access token không được cung cấp
    Console.WriteLine("Access token is required");
}
catch (AccessTokenInvalidException ex)
{
    // Access token không hợp lệ hoặc không được phân quyền
    Console.WriteLine($"Invalid access token: {ex.AccessToken}");
}
catch (NoAvailableProxiesException ex)
{
    // Không có proxy available cho access token này
    Console.WriteLine($"No proxies available for token: {ex.AccessToken}");
}
catch (NoMatchingProxiesException)
{
    // Không có proxy match với filters (ip_version, protocol, country, etc.)
    Console.WriteLine("No proxies match the specified filters");
}
catch (StrategyNotFoundException ex)
{
    // Strategy không tồn tại
    Console.WriteLine($"Strategy not found: {ex.StrategyName}");
}
catch (RefererProxyRequiredException)
{
    // Alternative strategy cần referer_proxy
    Console.WriteLine("Referer proxy is required for alternative strategy");
}
catch (SmartPoolException ex)
{
    // Các lỗi khác từ SmartPool
    Console.WriteLine($"SmartPool error ({ex.ErrorCode}): {ex.Message}");
}
catch (Exception ex)
{
    // Network errors, timeout, etc.
    Console.WriteLine($"Network error: {ex.Message}");
}

Try Methods (Không Throw Exception)

SDK cung cấp các method Try* để bỏ qua exceptions và trả về null nếu lỗi:

// TryGetRawProxyAsync - không throw exception
var proxy = await _smartPoolClient.TryGetRawProxyAsync(request);
if (proxy != null)
{
    // Sử dụng proxy
    Console.WriteLine($"Proxy: {proxy.host}:{proxy.port}");
}
else
{
    // Xử lý khi không lấy được proxy (silent failure)
    Console.WriteLine("Failed to get proxy");
}

// TryGetProxyAsync - không throw exception
var webProxy = await _smartPoolClient.TryGetProxyAsync(request);
if (webProxy != null)
{
    var handler = new HttpClientHandler { Proxy = webProxy };
    var httpClient = new HttpClient(handler);
    // Use httpClient...
}

Khi nào dùng Try methods:

  • Khi bạn muốn xử lý lỗi một cách silent (không cần biết chi tiết lỗi)
  • Trong retry logic, khi bạn chỉ cần biết success/failure
  • Khi performance quan trọng hơn error details

Health Check

var isHealthy = await _smartPoolClient.PingAsync();
if (!isHealthy)
{
    Console.WriteLine("SmartPool API is not responding");
}

Performance Optimizations

SDK đã được tối ưu với các tính năng:

  • Connection Pooling & Keep-Alive: Giảm latency reconnect từ ~50-100ms xuống ~5ms
  • Client-side Caching: Giảm network calls ~90% khi cache hit
  • Response Compression: Giảm payload size ~30-50%
  • Batch Logging: Giảm N network calls → 1 call
  • Fire-and-Forget: Non-blocking logging, không block main flow

Xem chi tiết trong SDK_DOCUMENTATION.md.

Chi Tiết Các Modes và Cách Hoạt Động

1. Protocol Modes

gRPC Mode (Khuyến nghị)

Cách hoạt động:

  • Sử dụng HTTP/2 với binary protocol (MessagePack)
  • Connection pooling tự động với keep-alive
  • Compression tự động (gzip/deflate)
  • Streaming support cho batch operations

Cấu hình:

{
  "SmartPool": {
    "Protocol": "Grpc",
    "Host": "api.example.com",
    "Port": 5001,
    "UseSecureConnection": true,
    "EnableCompression": true,
    "CompressionAlgorithm": "gzip"
  }
}

Khi nào dùng:

  • High-performance scenarios (scraping, batch processing)
  • Internal services (microservices communication)
  • Khi cần throughput cao
  • Khi có control over network (không bị firewall block HTTP/2)

Ưu điểm:

  • Performance cao hơn HTTP ~30-50%
  • Binary protocol → payload nhỏ hơn
  • Connection pooling tự động
  • Keep-alive giảm latency

Nhược điểm:

  • Cần HTTP/2 support
  • Khó debug hơn (binary format)
  • Có thể bị firewall block

HTTP Mode

Cách hoạt động:

  • Standard HTTP/1.1 REST API
  • JSON serialization
  • Standard HttpClient với connection pooling
  • Dễ debug với browser DevTools

Cấu hình:

{
  "SmartPool": {
    "Protocol": "Http",
    "Host": "api.example.com",
    "Port": 5000,
    "UseSecureConnection": true
  }
}

Khi nào dùng:

  • External clients (web browsers, mobile apps)
  • Khi cần debug dễ dàng
  • Khi firewall chỉ cho phép HTTP
  • Development/testing environments

Ưu điểm:

  • Dễ debug (JSON, có thể test với Postman/curl)
  • Universal support (mọi client đều hỗ trợ HTTP)
  • Firewall-friendly
  • Standard REST API

Nhược điểm:

  • Performance thấp hơn gRPC
  • Payload lớn hơn (JSON vs binary)
  • Không có streaming support

2. Client-Side Caching Mode

Cách hoạt động:

  • Cache proxy results trong memory (MemoryCache)
  • Cache key dựa trên: access_token, strategy, filters (ip_version, protocol, country, target_domain)
  • TTL: ClientCacheDurationSeconds (default: 30s)
  • Sliding expiration: 50% của TTL
  • Max entries: ClientCacheMaxEntries (default: 100)

Flow:

1. Request proxy với filters
2. Check cache → Cache hit? Return cached proxy
3. Cache miss? Call API → Cache result → Return proxy
4. Next request với same filters → Return từ cache (không call API)

Cấu hình:

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

Khi nào dùng:

  • Khi request cùng filters nhiều lần
  • Random/Round-robin strategies (không phụ thuộc vào real-time data)
  • Giảm load cho API server
  • Giảm latency cho client

Khi KHÔNG nên dùng:

  • Least Delay strategy (cần real-time data)
  • Adaptive Ranking strategy (cần real-time data)
  • Khi cần proxy mới mỗi lần request

Ví dụ:

// Request 1: Call API, cache result
var proxy1 = await _client.GetProxyAsync(new GetProxyRequest 
{ 
    strategy = "random",
    ip_version = "v6" 
});

// Request 2: Return từ cache (không call API)
var proxy2 = await _client.GetProxyAsync(new GetProxyRequest 
{ 
    strategy = "random",
    ip_version = "v6" 
});
// proxy1 và proxy2 giống nhau (cùng từ cache)

// Request 3: Khác filters → Call API mới
var proxy3 = await _client.GetProxyAsync(new GetProxyRequest 
{ 
    strategy = "random",
    ip_version = "v4"  // Khác filter
});

3. Logging Modes

Fire-and-Forget Mode

Cách hoạt động:

  • Logging chạy trong background task (không block main thread)
  • Nếu có batch logging → Queue vào channel
  • Nếu không có batch → Fire task riêng
  • Không đợi response từ server

Cấu hình:

{
  "SmartPool": {
    "EnableFireAndForgetLogging": true
  }
}

Khi nào dùng:

  • High-throughput scenarios
  • Khi logging không critical (best-effort)
  • Khi không muốn block main flow
  • Background processing

Ví dụ:

// Non-blocking - không đợi response
await _client.LogProxyUsageAsync(new ProxyUsageLogRequest
{
    proxy_id = 123,
    status_code = 200,
    response_time_ms = 450
});
// Code tiếp tục chạy ngay, không đợi log complete

Batch Logging Mode

Cách hoạt động:

  • Queue log requests vào bounded channel
  • Background task collect logs theo batch
  • Flush khi đạt LogBatchSize hoặc LogBatchFlushIntervalMs
  • Gửi batch đến server

Flow:

1. LogProxyUsageAsync() → Queue vào channel
2. Background task collect logs
3. Khi đủ LogBatchSize (50) hoặc timeout (5s) → Flush batch
4. Gửi batch đến server

Cấu hình:

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

Khi nào dùng:

  • High-throughput scenarios (1000+ requests/second)
  • Khi muốn giảm network calls
  • Khi có nhiều logs cần gửi

Ví dụ:

// Queue 1000 logs
for (int i = 0; i < 1000; i++)
{
    _client.QueueLogProxyUsage(new ProxyUsageLogRequest
    {
        proxy_id = i,
        status_code = 200,
        response_time_ms = 450
    });
}
// Chỉ gửi ~20 batches (50 logs/batch) thay vì 1000 requests

Kết hợp Fire-and-Forget + Batch:

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

→ Logging hoàn toàn non-blocking và batch processing

Synchronous Logging Mode

Cách hoạt động:

  • Đợi response từ server
  • Block cho đến khi log complete
  • Throw exception nếu lỗi

Cấu hình:

{
  "SmartPool": {
    "EnableFireAndForgetLogging": false,
    "EnableBatchLogging": false
  }
}

Khi nào dùng:

  • Khi logging là critical (cần đảm bảo log được gửi)
  • Low-throughput scenarios
  • Debug/testing

Ví dụ:

// Blocking - đợi response
var success = await _client.LogProxyUsageAsync(new ProxyUsageLogRequest
{
    proxy_id = 123,
    status_code = 200
});
if (!success)
{
    // Handle failure
}

4. Connection Pooling & Keep-Alive Mode

Cách hoạt động:

gRPC:

  • HTTP/2 connection pooling tự động
  • Keep-alive ping mỗi KeepAlivePingDelaySeconds (60s)
  • Ping timeout: KeepAlivePingTimeoutSeconds (30s)
  • Connection idle timeout: PooledConnectionIdleTimeoutMinutes (5min)
  • Connection lifetime: PooledConnectionLifetimeMinutes (10min)

HTTP:

  • HttpClient connection pooling
  • Connection idle timeout: PooledConnectionIdleTimeoutMinutes (5min)
  • Connection lifetime: PooledConnectionLifetimeMinutes (10min)

Cấu hình:

{
  "SmartPool": {
    "KeepAlivePingDelaySeconds": 60,
    "KeepAlivePingTimeoutSeconds": 30,
    "PooledConnectionIdleTimeoutMinutes": 5,
    "PooledConnectionLifetimeMinutes": 10,
    "EnableMultipleHttp2Connections": true,
    "ConnectTimeoutSeconds": 5
  }
}

Lợi ích:

  • Giảm latency: Reuse connection thay vì tạo mới (~50-100ms → ~5ms)
  • Giảm overhead: Không cần handshake mỗi request
  • Better throughput: Multiple connections cho parallel requests

Ví dụ:

// Request 1: Tạo connection mới (~50ms)
var proxy1 = await _client.GetProxyAsync();

// Request 2-100: Reuse connection (~5ms mỗi request)
for (int i = 0; i < 100; i++)
{
    var proxy = await _client.GetProxyAsync();
}
// Total time: ~50ms + (99 * 5ms) = ~545ms
// Without pooling: ~100 * 50ms = ~5000ms

5. Compression Mode

Cách hoạt động:

  • gRPC: Compression tự động với gzip/deflate
  • HTTP: Accept-Encoding header
  • Server compress response nếu client support

Cấu hình:

{
  "SmartPool": {
    "EnableCompression": true,
    "CompressionAlgorithm": "gzip"
  }
}

Lợi ích:

  • Giảm payload size ~30-50%
  • Giảm bandwidth usage
  • Faster transfer trên slow networks

Khi nào dùng:

  • Khi bandwidth là bottleneck
  • Mobile networks
  • High-latency networks
  • Khi response size lớn

Trade-off:

  • CPU overhead cho compression/decompression
  • Thường không đáng kể với modern CPUs

Best Practices

1. Protocol Selection

// High-performance internal service → gRPC
services.AddSmartPoolClient(options =>
{
    options.Protocol = SmartPoolProtocol.Grpc;
});

// External client → HTTP
services.AddSmartPoolClient(options =>
{
    options.Protocol = SmartPoolProtocol.Http;
});

2. Caching Strategy

// Random/Round-robin → Enable cache
services.AddSmartPoolClient(options =>
{
    options.EnableClientCache = true;
    options.ClientCacheDurationSeconds = 30;
});

// Least Delay/Adaptive Ranking → Disable cache
services.AddSmartPoolClient(options =>
{
    options.EnableClientCache = false; // Cần real-time data
});

3. Logging Strategy

// High-throughput → Fire-and-forget + Batch
services.AddSmartPoolClient(options =>
{
    options.EnableFireAndForgetLogging = true;
    options.EnableBatchLogging = true;
    options.LogBatchSize = 50;
});

// Critical logging → Synchronous
services.AddSmartPoolClient(options =>
{
    options.EnableFireAndForgetLogging = false;
    options.EnableBatchLogging = false;
});

4. Error Handling Pattern

// Detailed error handling
try
{
    var proxy = await _client.GetRawProxyAsync(request);
}
catch (NoAvailableProxiesException)
{
    // Retry với different token hoặc wait
}
catch (NoMatchingProxiesException)
{
    // Relax filters hoặc use different strategy
}
catch (SmartPoolException ex)
{
    _logger.LogError(ex, "SmartPool error: {ErrorCode}", ex.ErrorCode);
}

// Silent failure
var proxy = await _client.TryGetRawProxyAsync(request);
if (proxy == null)
{
    // Fallback logic
}

5. Retry Pattern với Alternative Strategy

SmartProxyServer? currentProxy = null;
for (int retry = 0; retry < 3; retry++)
{
    try
    {
        var request = retry == 0
            ? new GetProxyRequest { strategy = "least_delay", target_domain = "facebook.com" }
            : new GetProxyRequest 
            { 
                strategy = "alternative",
                referer_proxy = currentProxy 
            };
        
        currentProxy = await _client.GetRawProxyAsync(request);
        
        // Use proxy...
        break; // Success
    }
    catch (NoMatchingProxiesException)
    {
        if (retry == 2) throw; // Last retry failed
        // Continue to next retry
    }
}

Dependencies

  • .NET 10.0
  • MagicOnion.Client 6.1.7
  • Microsoft.Extensions.* 10.0.2

Documentation

License

Internal use only.