85 lines
2.8 KiB
Markdown
85 lines
2.8 KiB
Markdown
# ClickHouse Connection Fix
|
|
|
|
## Vấn đề
|
|
Lỗi `TOO_MANY_SIMULTANEOUS_QUERIES` (Error Code 202) xảy ra khi có quá nhiều queries đồng thời đến ClickHouse (vượt quá limit 500).
|
|
|
|
### Nguyên nhân
|
|
1. **Connection leak**: Mỗi lần gọi `_clickHouseContext.proxy_logs` tạo một connection mới mà không đóng đúng cách
|
|
2. **Không có connection pooling**: Connections không được reuse
|
|
3. **Không có error handling**: Lỗi ClickHouse làm crash toàn bộ request
|
|
|
|
## Giải pháp đã áp dụng
|
|
|
|
### 1. Sửa ClickHouseContext (ClickHouseContext.cs)
|
|
**Trước:**
|
|
```csharp
|
|
public IDbConnection proxy_logs =>
|
|
new ClickHouseConnection(_configuration.GetConnectionString(nameof(proxy_logs)));
|
|
```
|
|
|
|
**Sau:**
|
|
```csharp
|
|
public IDbConnection CreateConnection()
|
|
{
|
|
return new ClickHouseConnection(_connectionString);
|
|
}
|
|
```
|
|
|
|
**Lợi ích:**
|
|
- Connection được tạo explicitly và có thể dispose đúng cách với `using` statement
|
|
- Connection string được cache trong constructor
|
|
|
|
### 2. Cập nhật ProxyRepository.UsedProxy()
|
|
**Thay đổi:**
|
|
- Sử dụng `CreateConnection()` thay vì property `proxy_logs`
|
|
- Thêm `try-catch` để handle lỗi ClickHouse
|
|
- Catch riêng error code 202 (TOO_MANY_SIMULTANEOUS_QUERIES)
|
|
- Thêm command timeout (5 seconds)
|
|
- Log warning thay vì throw exception để không ảnh hưởng main flow
|
|
|
|
**Code:**
|
|
```csharp
|
|
try
|
|
{
|
|
using var db = _clickHouseContext.CreateConnection();
|
|
|
|
var res = await db.ExecuteAsync(
|
|
@"INSERT INTO requested_logs ...",
|
|
log,
|
|
commandTimeout: 5
|
|
);
|
|
return res > 0;
|
|
}
|
|
catch (ClickHouseServerException ex) when (ex.ErrorCode == 202)
|
|
{
|
|
Log.Warning("ClickHouse too many simultaneous queries. Skipping log.");
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failed to log proxy usage to ClickHouse");
|
|
return false;
|
|
}
|
|
```
|
|
|
|
## Kết quả mong đợi
|
|
1. ✅ Connections được đóng đúng cách sau mỗi query
|
|
2. ✅ Giảm số lượng connections đồng thời
|
|
3. ✅ Lỗi ClickHouse không làm crash service
|
|
4. ✅ Logs được ghi lại để monitoring
|
|
|
|
## Monitoring
|
|
Sau khi deploy, cần theo dõi:
|
|
- Số lượng warnings "ClickHouse too many simultaneous queries" trong logs
|
|
- Số lượng errors "Failed to log proxy usage to ClickHouse"
|
|
- Nếu vẫn còn nhiều warnings, cần xem xét:
|
|
- Tăng `max_concurrent_queries` trong ClickHouse config
|
|
- Implement batch insert thay vì insert từng record
|
|
- Sử dụng queue + background worker để buffer logs
|
|
|
|
## Tối ưu thêm (nếu cần)
|
|
Nếu vẫn gặp vấn đề, có thể implement:
|
|
1. **Batch Insert**: Gom nhiều logs lại insert một lần
|
|
2. **Background Queue**: Sử dụng Channel/BlockingCollection để buffer logs
|
|
3. **Circuit Breaker**: Tạm dừng logging khi ClickHouse quá tải
|