581 lines
15 KiB
Markdown
581 lines
15 KiB
Markdown
# 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):**
|
|
```xml
|
|
<PackageReference Include="Icomm.ResourcePool.Abstractions" Version="x.x.x" />
|
|
```
|
|
|
|
**Sau (SmartPool):**
|
|
```xml
|
|
<PackageReference Include="Icomm.SmartPool.Proxy" Version="10.0.1" />
|
|
```
|
|
|
|
### Step 2: Cập Nhật Configuration
|
|
|
|
**Trước (ProxyPool):**
|
|
```json
|
|
{
|
|
"TokenPoolOptions": {
|
|
"Host": "10.9.3.70",
|
|
"Port": 31287,
|
|
"protocol": "Grpc"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Sau (SmartPool):**
|
|
```json
|
|
{
|
|
"SmartPool": {
|
|
"Protocol": "Grpc",
|
|
"Host": "10.9.3.70",
|
|
"Port": 5001,
|
|
"DefaultAccessToken": "your-access-token",
|
|
"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 `DefaultAccessToken` nếu muốn tự động inject vào requests
|
|
|
|
### Step 3: Cập Nhật Service Registration
|
|
|
|
**Trước (ProxyPool - gRPC):**
|
|
```csharp
|
|
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):**
|
|
```csharp
|
|
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;
|
|
options.DefaultAccessToken = "your-access-token";
|
|
});
|
|
```
|
|
|
|
### Step 4: Cập Nhật Code Sử Dụng
|
|
|
|
---
|
|
|
|
## 📝 Code Migration Examples
|
|
|
|
### Example 1: Basic Proxy Request
|
|
|
|
#### ProxyPool (gRPC)
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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)
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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
|
|
```csharp
|
|
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ả `ProxyRequest` → `GetProxyRequest`
|
|
- [ ] Thay thế tất cả `ProxyRequestByFeature` → `GetProxyRequest`
|
|
- [ ] Cập nhật field names từ PascalCase sang snake_case
|
|
- [ ] Cập nhật strategy names (nếu có `least_used` → `alternative`)
|
|
- [ ] Cập nhật `Type` field → `protocol` + `ip_version`
|
|
- [ ] Thay thế `GetProxy()` / `GetProxyV2()` → `GetProxyAsync()` / `GetRawProxyAsync()`
|
|
- [ ] Cập nhật proxy usage logging: `ProxyLogRequest` → `ProxyUsageLogRequest`
|
|
- [ ] 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
|
|
|
|
- [SmartPool SDK Documentation](./docs/src/Icomm.SmartPool.Proxy/README.md)
|
|
- [SmartPool API Documentation](./docs/src/Icomm.API.SmartPool/README.md)
|
|
- [SmartPool Quick Reference](./docs/src/Icomm.SmartPool.Proxy/QUICK_REFERENCE.md)
|
|
|
|
---
|
|
|
|
## 💡 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
|
|
```csharp
|
|
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
|
|
```csharp
|
|
// 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
|
|
```json
|
|
{
|
|
"SmartPool": {
|
|
"EnableClientCache": true,
|
|
"ClientCacheDurationSeconds": 30
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. Use Batch Logging for High Throughput
|
|
```json
|
|
{
|
|
"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](./docs/src/Icomm.SmartPool.Proxy/README.md)
|
|
2. Kiểm tra [Troubleshooting Guide](./docs/src/Icomm.API.SmartPool/README.md#troubleshooting)
|
|
3. Liên hệ team phát triển
|
|
|
|
---
|
|
|
|
**Last Updated**: 2026-01-23
|