Cách cấu hình sticky sessions trong CI/CD để tránh bị chặn
31 tháng 10, 2026
Giới thiệu
Trong môi trường CI/CD, các job scraping thường phải truy cập nhiều trang web, thực hiện collecte dữ liệu và cập nhật thông tin. Khi mỗi job sử dụng IP khác nhau, các hệ thống có thể phát hiện và chặn các request do thay đổi địa chỉ IP quá nhanh. Việc sử dụng session sticky – giữ IP cố định trong suốt quá trình thực hiện – giúp giảm thiểu khả năng bị chặn, duy trì tốc độ và tránh lãng phí tài khoản proxy.
Tại sao sticky sessions trong CI/CD?
1. Tính nhất quán của dữ liệu
Khi một job chạy nhiều request liên tiếp, nếu IP thay đổi giữa các request, các server có thể xem đây là comportment của bot và đưa ra các cơ chế chặn như CAPTCHA, rate‑limit hoặc trả về lỗi 429. Giữ IP cố định cho toàn bộ job giúp các server nhận diện patterns chính xác và giảm lỗi.
2. Giảm chi phí tài khoản proxy
Với session sticky, bạn không cần tạo mới session cho mỗi request, vì vậy số lượng rotate IP giảm đáng kể. Điều này kéo dài thời gian sử dụng của mỗi tài khoản và giảm chi phí khi thanh toán bằng bank transfer, crypto hoặc balance.
3. Tích hợp dễ dàng vào pipeline
Trong CI/CD, các bước build, test và deploy thường chạy trong môi trường cô lập. Khi bạn cấu hình một job để sử dụng một session sticky, toàn bộ pipeline sẽ giữ cùng một IP, tránh xung đột và simplifies log analysis.
Cách thiết lập session sticky
Bước 1: Lấy danh sách session hiện có
Bạn có thể gọi API GET để liệt kê các session hiện tại và chọn một session có trạng thái hoạt động, country mong muốn và mode rotation là sticky.
import requests
# Thay thế các biến placeholder với thông tin thực tế
API_KEY = 'YOUR_API_KEY'
headers = {'Authorization': f'Bearer {API_KEY}'}
resp = requests.get('https://backend-api.ro-proxy.com/api/session', headers=headers)
if resp.status_code == 200:
sessions = resp.json()
# Chọn session có mode sticky và country mong muốn
for s in sessions:
if s['mode'] == 'sticky' and s['country'] == 'VN':
SESSION_ID = s['id']
break
else:
raise Exception('Không thể lấy danh sách session')
Bước 2: Cấu hình proxy trong ứng dụng của bạn
Đối với hầu hết các thư viện HTTP (requests, aiohttp, httpie), bạn chỉ cần chỉ định proxy dạng:
proxy_url = f'http://{USERNAME}:{PASSWORD}@{GATEWAY_HOST}:{HTTP_PORT}'
proxies = {
'http': proxy_url,
'https': proxy_url
}
Trong CI/CD, các biến môi trường thường được truyền vào container, ví dụ:
- GATEWAY_HOST
- HTTP_PORT
- USERNAME
- PASSWORD
- API_KEY
Với RoProxy, mỗi session có một combination duy nhất của địa chỉ gateway, cổng HTTP và thông tin đăng nhập, vì vậy việc thay đổi cổng SOCKS5 không ảnh hưởng đến việc sử dụng session sticky qua HTTP/HTTPS.
Bước 3: Sử dụng session ID trong request
Để duy trì session sticky, bạn có thể gắn session ID vào một header tùy chỉnh, ví dụ X‑Session‑ID. Nhiều API của RoProxy không bắt buộc việc này, nhưng việc truyền session ID giúp các hệ thống phía sau (ví dụ, ứng dụng web) hiểu được request đang thuộc cùng một session.
custom_headers = {
'X-Session-ID': SESSION_ID,
'Authorization': f'Bearer {API_KEY}'
}
Sau đó, thực hiện request như bình thường:
import requests
import time
def fetch_with_retry(url, max_retries=3, base_delay=1.0):
for attempt in range(max_retries):
try:
response = requests.get(url, proxies=proxies, headers=custom_headers, timeout=30)
response.raise_for_status()
return response
except requests.exceptions.RequestException as e:
if attempt < max_retries - 1:
delay = base_delay * (2 ** attempt)
print(f'Attempt {attempt+1} failed: {e}. Retrying in {delay:.1f}s...')
time.sleep(delay)
else:
raise
Kiểm tra trạng thái session trước khi thực hiện
Trong môi trường CI/CD, việc xảy ra lỗi mạng hoặc bị chặn có thể làm session mất hiệu lực. Để tránh thực hiện request với session đã hết hạn, bạn nên kiểm tra trạng thái session trước khi gửi request chính.
def check_session_alive(session_id):
headers = {'Authorization': f'Bearer {API_KEY}'}
resp = requests.get(
f'https://backend-api.ro-proxy.com/api/session/{session_id}',
headers=headers
)
if resp.status_code == 200:
print('Session vẫn hoạt động')
return True
elif resp.status_code == 404:
print('Session không tồn tại')
return False
else:
print(f'Lỗi trả về: {resp.status_code}')
return False
Bạn có thể gọi hàm này ở đầu mỗi job hoặc khi phát hiện lỗi 502/504 đầu tiên. Nếu session không còn alive, hãy thực hiện rotate IP ngay lập tức.
Xử lý lỗi và xoay IP
Phát hiện lỗi 502, 504 hoặc timeout
Khi request trả về mã 502 (Bad Gateway) hoặc 504 (Gateway Timeout), nghĩa là gateway không thể truyền request tới máy chủ đích hoặc không nhận được phản hồi trong thời gian quy định. Hai lỗi này thường do:
- Kết nối TCP bị gián đoạn giữa client và gateway.
- Thời gian timeout quá ngắn khiến server đích không kịp trả lời.
- Xử lý rotation không hoàn thành đúng cách.
Kỹ thuật retry với backoff
Đây là phương pháp cơ bản nhưng rất hiệu quả. Khi gặp lỗi, chờ một khoảng thời gian tăng dần (mở rộng nhân 2) trước khi thử lại. Điều này giảm thiểu hiện tượng retry quá mức và tránh gây tải lên gateway.
def fetch_with_smart_retry(url, session_id, max_retries=3, base_delay=1.0):
for attempt in range(max_retries):
try:
# Kiểm tra session trước khi gửi
if not check_session_alive(session_id):
rotate_ip(session_id)
# Đợi một chút để session mới được kích hoạt
time.sleep(2)
response = requests.get(
url,
proxies=proxies,
headers=custom_headers,
timeout=30
)
response.raise_for_status()
return response
except requests.exceptions.RequestException as e:
if attempt < max_retries - 1:
delay = base_delay * (2 ** attempt)
print(f'Attempt {attempt+1} failed: {e}. Retrying in {delay:.1f}s...')
time.sleep(delay)
else:
raise
Xoay IP ngay khi phát hiện lỗi
Nếu bạn phát hiện rằng session không còn alive (ví dụ trả về 404 hoặc 502), việc xoay IP ngay lập tức thường giải quyết vấn đề.
def rotate_ip_on_error(session_id):
headers = {'Authorization': f'Bearer {API_KEY}'}
resp = requests.post(
f'https://backend-api.ro-proxy.com/api/session/{session_id}/rotate',
headers=headers
)
if resp.status_code == 200:
print('IP đã được xoay mới')
return True
else:
print(f'Xoay IP thất bại: {resp.status_code}')
return False
Bạn có thể gọi hàm này trong khối except của fetch_with_smart_retry, hoặc khi nhận được mã 502/504 từ response.
Áp dụng trong pipeline CI/CD
1. Đặt biến môi trường trong file .gitlab-ci.yml, GitHub Actions hoặc Jenkins
Ví dụ trong GitHub Actions:
jobs:
scrape:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set proxy env
run: |
echo "GATEWAY_HOST=gateway.example.com" >> $GITHUB_ENV
echo "HTTP_PORT=8080" >> $GITHUB_ENV
echo "USERNAME=abc123" >> $GITHUB_ENV
echo "PASSWORD=xyz789" >> $GITHUB_ENV
echo "API_KEY=your_key" >> $GITHUB_ENV
2. Khởi tạo session sticky trong bước setup
Bạn có thể thêm một bước Python để lấy session ID và lưu vào file cache.
- name: Get session ID
run: |
python - <<EOF
import os, json, requests, time
API_KEY = os.getenv('API_KEY')
headers = {'Authorization': f'Bearer {API_KEY}'}
# Lấy danh sách session
resp = requests.get('https://backend-api.ro-proxy.com/api/session', headers=headers)
sessions = resp.json()
for s in sessions:
if s['mode'] == 'sticky' and s['country'] == 'VN':
with open('session_id.txt', 'w') as f:
f.write(s['id'])
print('Session ID saved')
EOF
3. Sử dụng session ID trong script scraping
Trong script Python, đọc session ID từ file và dùng trong các request.
import os, requests, time
# Đọc session ID
with open('session_id.txt') as f:
SESSION_ID = f.read().strip()
# Cấu hình proxy và header tùy chỉnh
GATEWAY_HOST = os.getenv('GATEWAY_HOST')
HTTP_PORT = int(os.getenv('HTTP_PORT'))
USERNAME = os.getenv('USERNAME')
PASSWORD = os.getenv('PASSWORD')
API_KEY = os.getenv('API_KEY')
proxy_url = f'http://{USERNAME}:{PASSWORD}@{GATEWAY_HOST}:{HTTP_PORT}'
proxies = {'http': proxy_url, 'https': proxy_url}
custom_headers = {'X-Session-ID': SESSION_ID, 'Authorization': f'Bearer {API_KEY}'}
# Thực hiện request với retry
response = fetch_with_smart_retry('https://example.com', SESSION_ID)
print('Status code:', response.status_code)
4. Kiểm tra và xử lý lỗi trong pipeline
Nếu script trả về mã không thành công (exit code != 0), pipeline sẽ dừng và thông báo lỗi. Bạn có thể thêm bước cuối cùng để log session ID và trạng thái, giúp team nhanh chóng định vị nguyên nhân.
Kết luận
Việc cấu hình sticky sessions trong CI/CD không chỉ giúp duy trì IP cố định mà còn nâng cao độ tin cậy và giảm chi phí cho các job scraping. Các bước chính bao gồm: lấy danh sách session, chọn session có mode sticky, cấu hình proxy với các placeholder, gắn session ID vào header, và áp dụng retry với backoff cùng cơ chế rotate IP khi session không còn alive. Khi áp dụng đúng cách, pipeline CI/CD sẽ hoạt động ổn định, giảm lỗi chặn và tối ưu hoá tài nguyên proxy.
Với RoProxy, việc quản lý session sticky trở nên ổn định và dễ bảo trì.