Sau 6 tháng vận hành gateway cho hệ thống SaaS phục vụ 12.000 developer, tôi nhận ra rằng việc lộ API key DeepSeek ra frontend là một thảm họa chỉ chờ thời điểm xảy ra. Bài viết này chia sẻ kiến trúc gateway production mà chúng tôi đã dựng, xử lý 4.2 triệu request/ngày với độ trễ P99 dưới 47ms - và lý do tại sao tôi chọn HolySheep AI làm upstream relay thay vì gọi trực tiếp DeepSeek.
1. Tại sao cần API Gateway cho DeepSeek?
- Bảo vệ tài khoản upstream: Một key bị lộ trên GitHub có thể cháy 50.000 token chỉ trong 4 giờ
- Quota management: Phân bổ token cho từng tenant/team một cách công bằng
- Cost control: Capping chi phí hàng tháng, tránh surprise bill
- Observability: Trace từng request, đo latency, error rate, token usage
- Failover: Tự động retry, fallback model khi upstream lỗi
2. Kiến trúc tổng quan
Stack công nghệ tôi dùng cho hệ thống 4.2M request/ngày:
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Client SDK │───▶│ Edge Gateway │───▶│ Auth + Quota │───▶│ HolySheep │
│ (JS/Python)│ │ (Cloudflare WAF)│ │ (FastAPI+Redis)│ │ Relay API │
└─────────────┘ └──────────────────┘ └─────────────────┘ └──────────────┘
│ │
▼ ▼
┌─────────┐ ┌────────────┐
│ Postgres│ │ DeepSeek V4│
│ (audit) │ │ GPT-4.1 │
└─────────┘ │ Claude ... │
└────────────┘
3. Code Production: Gateway FastAPI + Redis
Đây là phiên bản rút gọn gateway mà chúng tôi đang chạy, xử lý 280 RPS ổn định trên một node 2 vCPU. Lưu ý: DeepSeek V4 hiện chưa có bảng giá công bố, nên tôi dùng DeepSeek V3.2 làm model mặc định trong code ($0.42/MTok).
import os
import time
import hashlib
import httpx
from fastapi import FastAPI, HTTPException, Depends, Header
from pydantic import BaseModel
import redis.asyncio as redis
REDIS_URL = os.getenv("REDIS_URL", "redis://10.0.1.5:6379")
UPSTREAM = "https://api.holysheep.ai/v1"
MASTER_KEY = os.getenv("HOLYSHEEP_MASTER_KEY") # chi giu server-side
r = redis.from_url(REDIS_URL, decode_responses=True)
app = FastAPI(title="LLM Gateway")
class ChatRequest(BaseModel):
model: str = "deepseek-v3.2"
messages: list
max_tokens: int = 1024
temperature: float = 0.7
async def verify_client_key(x_api_key: str = Header(...)) -> dict:
"""Xac thuc client key va tra ve thong tin tenant."""
key_hash = hashlib.sha256(x_api_key.encode()).hexdigest()
tenant = await r.hgetall(f"tenant:{key_hash}")
if not tenant:
raise HTTPException(401, "Invalid API key")
if tenant.get("status") != "active":
raise HTTPException(403, "Tenant suspended")
return {"id": tenant["id"], "tier": tenant["tier"], "hash": key_hash}
async def rate_limit(tenant: dict, tokens_estimate: int):
"""Sliding window + token bucket ket hop."""
tier = tenant["tier"]
limits = {
"free": {"rpm": 20, "tpm": 50_000},
"pro": {"rpm": 200, "tpm": 500_000},
"enterprise": {"rpm": 2000, "tpm": 5_000_000},
}[tier]
pipe = r.pipeline()
now = time.time()
window = 60
key = f"rate:{tenant['hash']}:{int(now // window)}"
pipe.incrby(key, tokens_estimate)
pipe.expire(key, 90)
results = await pipe.execute()
used = results[0]
if used > limits["tpm"]:
raise HTTPException(429, f"Quota exceeded: {used}/{limits['tpm']} tokens/min")
req_key = f"req:{tenant['hash']}:{int(now // window)}"
count = await r.incr(req_key)
await r.expire(req_key, 90)
if count > limits["rpm"]:
raise HTTPException(429, f"Rate limit: {count}/{limits['rpm']} req/min")
@app.post("/v1/chat/completions")
async def chat(req: ChatRequest, tenant: dict = Depends(verify_client_key)):
await rate_limit(tenant, tokens_estimate=req.max_tokens)
async with httpx.AsyncClient(timeout=30) as client:
resp = await client.post(
f"{UPSTREAM}/chat/completions",
headers={"Authorization": f"Bearer {MASTER_KEY}"},
json=req.dict(),
)
# Audit log
await r.xadd("audit:requests", {
"tenant": tenant["id"],
"model": req.model,
"status": resp.status_code,
"ts": str(now),
})
if resp.status_code != 200:
raise HTTPException(resp.status_code, resp.text)
return resp.json()
@app.get("/health")
async def health():
return {"status": "ok", "upstream": UPSTREAM}
4. JWT cho multi-tenant SaaS
Khi gateway cần trust giữa nhiều service, tôi dùng JWT ngắn hạn (15 phút) thay vì truyền raw API key qua mạng.