1. Content Delivery Network (CDN)
1.1. Khái niệm
CDN = mạng server (edge POP — Point of Presence) phân tán toàn cầu, cache content gần user. Request đi đến edge gần nhất thay vì origin xa.
1.2. Lợi ích
- Latency thấp — user APAC hit POP Singapore (~30ms) thay vì origin Virginia (~250ms).
- Giảm tải origin — 90%+ traffic phục vụ từ edge cache.
- Bandwidth tiết kiệm — cache hit không qua network origin.
- DDoS protection — edge hấp thụ traffic spike.
- Geographic redundancy — 1 region down, edge khác phục vụ.
1.3. Cache control
# Static asset — cache lâu, immutable URL versioning
Cache-Control: public, max-age=31536000, immutable
# /static/app.v123.js — đổi nội dung = đổi URL
# HTML — cache ngắn vì có thể đổi
Cache-Control: public, max-age=300, must-revalidate
# Personalized API response — không cache hoặc private
Cache-Control: private, max-age=60
# private = chỉ browser cache, không CDN/proxy
# Sensitive — không cache
Cache-Control: no-store
1.4. CDN tools
- Cloudflare — phổ biến, free tier mạnh, edge compute (Workers).
- AWS CloudFront — tích hợp AWS ecosystem.
- Fastly — programmable VCL, low TTFB.
- Akamai — enterprise, lâu đời.
- Bunny.net — affordable, performance tốt.
1.5. CDN cho dynamic content
Truyền thống CDN cache static. Hiện đại có thể cache dynamic ngắn hạn:
- Edge SWR (Cloudflare, Vercel) — stale-while-revalidate ở edge.
- Edge SSR — render trang ở edge (Cloudflare Workers, Vercel Edge Functions).
- API caching — GET response với cache-friendly header.
1.6. Cache invalidation
# Cloudflare API:
curl -X POST "https://api.cloudflare.com/client/v4/zones/<id>/purge_cache" \
-H "Authorization: Bearer $TOKEN" \
-d '{"files":["https://example.com/api/products"]}'
# Hoặc purge by tag:
curl -X POST ... -d '{"tags":["product-list"]}'
Pattern: tag CDN cache với Cache-Tag header → bulk purge khi data đổi.
2. Rate Limiting
Giới hạn request từ 1 client để: tránh abuse, công bằng giữa user, bảo vệ backend.
2.1. Bốn thuật toán
2.1.a. Fixed Window
Đếm request trong window cố định (vd: mỗi phút). Reset mỗi window.
// Window: 1 phút, max 100 req
async function fixedWindow(userId: string) {
const window = Math.floor(Date.now() / 60_000); // window key
const key = `rl:${userId}:${window}`;
const count = await redis.incr(key);
if (count === 1) await redis.expire(key, 60);
if (count > 100) throw new Error('Rate limit exceeded');
}
Vấn đề: "burst boundary" — user request 100 lần ở giây 59 + 100 lần ở giây 1 phút sau = 200 request trong 2 giây.
2.1.b. Sliding Window Log
Lưu timestamp mọi request. Đếm request trong N giây gần nhất.
async function slidingLog(userId: string, limit = 100, windowMs = 60_000) {
const key = `rl:${userId}`;
const now = Date.now();
const cutoff = now - windowMs;
// Xóa entry cũ
await redis.zremrangebyscore(key, '-inf', cutoff);
// Đếm trong window
const count = await redis.zcard(key);
if (count >= limit) throw new Error('Rate limit exceeded');
// Add request mới
await redis.zadd(key, now, `${now}-${Math.random()}`);
await redis.expire(key, Math.ceil(windowMs / 1000));
}
(+) Chính xác. (−) Tốn memory (lưu mọi timestamp).
2.1.c. Sliding Window Counter
Compromise giữa fixed (rẻ) và log (chính xác). Weight 2 window kế nhau:
// Tại giây 30 của window hiện tại:
// rate = (count_previous_window * 30/60) + count_current_window
// Smooth giữa 2 window cố định
2.1.d. Token Bucket
Mỗi user có "bucket" với N token. Mỗi request tốn 1 token. Token tự refill rate R/s. Cho phép burst đến N nhưng sustained rate = R.
async function tokenBucket(userId: string, capacity = 100, refillRatePerSec = 10) {
const key = `tb:${userId}`;
const now = Date.now();
// Lua script atomic — Redis EVAL
const lua = `
local key = KEYS[1]
local cap = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local data = redis.call('HMGET', key, 'tokens', 'last')
local tokens = tonumber(data[1]) or cap
local last = tonumber(data[2]) or now
local elapsed = math.max(0, now - last) / 1000
tokens = math.min(cap, tokens + elapsed * rate)
if tokens < 1 then return 0 end
tokens = tokens - 1
redis.call('HMSET', key, 'tokens', tokens, 'last', now)
redis.call('EXPIRE', key, 3600)
return 1
`;
const allowed = await redis.eval(lua, 1, key, capacity, refillRatePerSec, now);
if (!allowed) throw new Error('Rate limit exceeded');
}
Token Bucket là phổ biến nhất production. AWS, Stripe đều dùng.
2.1.e. Leaky Bucket
Queue với fixed leak rate. Request quá fast → queue đầy → reject. Smooth rate output.
Tương tự token bucket nhưng output rate cố định — không cho burst.
2.2. So sánh
| Algorithm | Memory | Burst | Use case |
|---|---|---|---|
| Fixed Window | Rất ít | Có boundary issue | Đơn giản, OK cho rough limit |
| Sliding Log | Cao (mọi timestamp) | Smooth | Cần chính xác cao |
| Sliding Counter | Ít | Smooth approximation | Production sweet spot |
| Token Bucket | Ít | Cho burst đến capacity | API rate limit (Stripe, AWS) |
| Leaky Bucket | Ít | Smooth output rate | Network shaping, queue |
2.3. Distributed rate limiting
Multiple instance share state qua Redis. Atomic operation (INCR, Lua script) đảm bảo accuracy.
Vấn đề: Redis hot key cho heavy user. Giải:
- Shard rate limit theo userId.
- Sample-based (chỉ count 1/10 request, multiply).
- Two-tier: per-instance counter + sync với Redis định kỳ.
2.4. HTTP response
HTTP/1.1 429 Too Many Requests
Retry-After: 60 # client retry sau 60s
X-RateLimit-Limit: 100 # max
X-RateLimit-Remaining: 0 # còn lại
X-RateLimit-Reset: 1709337600 # Unix timestamp khi reset
2.5. Rate limit theo gì?
- IP address — cho anonymous request. Cẩn thận NAT (nhiều user share IP).
- API key / userId — cho authenticated.
- Endpoint-specific — login khắt khe hơn search.
- Tier-based — free user 100/h, pro user 10000/h.
3. API Gateway
3.1. Vai trò
Single entry point cho tất cả API. Đứng giữa client và microservice.
Gateway xử lý "cross-cutting concerns":
- Authn / Authz — verify JWT, OAuth.
- Rate limiting.
- Request/Response transformation — REST ↔ gRPC.
- Routing — path → service.
- Caching.
- Logging / Metrics.
- Versioning — /v1/, /v2/.
- Aggregation — 1 client request → query nhiều service, gộp response.
3.2. BFF — Backend For Frontend
Pattern: 1 gateway riêng cho mỗi client type (web, mobile, public API). BFF gọi nhiều microservice và assemble response phù hợp với UI.
Web ──────────► BFF Web ──────► User svc
└─► Product svc
└─► Cart svc
Mobile ───────► BFF Mobile ──► (same services, optimized payload)
3rd-party ────► Public API GW ─► (rate-limited, restricted)
3.3. Tools
- Kong — open-source, plugin system phong phú.
- AWS API Gateway — managed, tích hợp Lambda.
- Apigee (Google) — enterprise.
- Tyk — open-source.
- Envoy + custom config — flexible.
- nginx + Lua / OpenResty — DIY.
3.4. Anti-pattern: God Gateway
Gateway tích hợp business logic → biến thành monolith trá hình. Quy tắc: gateway chỉ làm infrastructure concern — auth, rate limit, route. Business logic ở service.
4. DDoS Protection
Distributed Denial-of-Service — attacker phối hợp nhiều máy gửi flood traffic làm app sập.
4.1. Phân loại
- Volumetric (L3/L4) — flood bandwidth. UDP flood, ICMP flood, amplification (DNS, NTP).
- Protocol (L4) — exploit protocol. SYN flood, Ping of Death.
- Application (L7) — request hợp lệ nhưng đắt (heavy SQL, scrape data). Khó phát hiện hơn.
4.2. Defense layers
- CDN edge absorption — Cloudflare, AWS Shield. Edge có hàng Tbps capacity, hấp thụ volumetric attack.
- Rate limiting — per IP, per session, per endpoint.
- Geographic filtering — block country bạn không phục vụ.
- Challenge — CAPTCHA, JS challenge khi suspect bot.
- Anycast — distribute attack tự nhiên qua nhiều POP.
- Anomaly detection — ML model phát hiện pattern bất thường.
- Capacity buffer — autoscale up khi traffic tăng.
4.3. AWS Shield Standard / Advanced
- Standard: free, tự động, bảo vệ L3/L4.
- Advanced: $3000/month, bảo vệ L7, hỗ trợ chuyên gia, refund khi attack.
4.4. Phòng tránh ở app code
- Pagination max size — không cho query 1M record/request.
- Query timeout (statement_timeout Postgres).
- Connection pool max — không vô hạn.
- Idempotency check.
- Negative cache — tránh ai đó request id không tồn tại spam DB.
5. WAF — Web Application Firewall
Filter HTTP request theo rule. Chặn request độc hại trước khi đến app.
5.1. Bảo vệ những gì
- SQL Injection — pattern
' OR 1=1,UNION SELECT. - XSS —
<script>,onerror=. - CSRF — referer check.
- Path traversal —
../../../etc/passwd. - Bot — User-Agent suspicious, signature.
- Account takeover — credential stuffing.
5.2. OWASP Core Rule Set
Bộ rule open-source phổ biến. Tools (ModSecurity, Cloudflare WAF, AWS WAF) đều support.
5.3. Trade-off
- (+) Block known attack pattern tự động.
- (−) False positive — block request hợp lệ.
- (−) Chỉ chặn known pattern; zero-day vẫn lọt.
Quy tắc: WAF là 1 layer; không phải solution duy nhất. Combine với input validation, prepared statement (cho SQLi), CSP (cho XSS).
6. Edge Authentication
Verify auth token ở edge thay vì để mỗi service. Tiết kiệm latency, centralize auth logic.
6.1. JWT validation at edge
Stateless: edge có public key, verify JWT signature. Không cần round-trip về central auth service.
// Cloudflare Worker / Lambda@Edge
export default {
async fetch(request: Request) {
const auth = request.headers.get('Authorization');
if (!auth?.startsWith('Bearer ')) return new Response('401', { status: 401 });
const token = auth.slice(7);
try {
const payload = await jwtVerify(token, PUBLIC_KEY);
// Forward request với userId trong header
const newReq = new Request(request);
newReq.headers.set('X-User-Id', payload.sub);
return fetch(newReq);
} catch {
return new Response('401', { status: 401 });
}
},
};
6.2. Trade-off
- (+) Latency thấp — verify ở edge gần user.
- (+) Backend service không cần verify lại (trust X-User-Id header từ edge).
- (−) Stateless JWT không thể "logout immediate" — phải đợi expire.
- (−) JWT lớn hơn session ID nhiều → bandwidth.
- (−) Compromise key = compromise toàn hệ.
Pattern thực dụng: Short-lived JWT (15 phút) + refresh token (lâu hơn, có thể revoke ở DB).
6.3. mTLS giữa service
Mutual TLS — client và server đều có cert. Service Mesh (Istio, Linkerd) handle tự động qua sidecar.
Lợi: zero-trust network — kể cả attacker đã vào internal network, không gọi được service mà không có cert.
7. Secret Management
Database password, API key, encryption key — KHÔNG hardcode trong code, KHÔNG commit git.
7.1. Anti-patterns
- Secret trong git repo (kể cả .env không gitignore).
- Secret trong Dockerfile.
- Secret trong Slack message / email.
- Secret trong log file.
- Cùng secret cho dev/staging/prod.
7.2. Tools
- HashiCorp Vault — open-source, feature đầy đủ, dynamic secrets.
- AWS Secrets Manager / Parameter Store — managed, tích hợp IAM.
- GCP Secret Manager.
- Azure Key Vault.
- Doppler, Infisical — SaaS, simpler.
- Kubernetes Secrets — base64 (NOT encryption!), thường dùng with KMS.
7.3. Best practices
- Rotation — đổi secret định kỳ (90 ngày). Tools support automated rotation.
- Least privilege — service chỉ access secret cần thiết.
- Audit log — mọi access đến secret được log.
- Encryption at rest — secret luôn encrypted khi lưu.
- Encryption in transit — TLS giữa app và secret store.
- Short-lived — dynamic secrets (Vault sinh password 1h cho DB).
7.4. Detect leak
- git-secrets, truffleHog — pre-commit hook scan secret.
- GitHub Secret Scanning — auto detect commit có pattern API key.
- Snyk, SonarQube — CI scan.
Khi secret leak: rotate immediate, không "thôi để cho qua". Attacker monitor public repo.
8. Observability at Scale
Đã đề cập tracing ở Ch6. Đây tổng hợp 3 pillars + best practice ở scale.
8.1. Three pillars
- Logs — text events, structured (JSON). Tools: ELK, Loki, Splunk, Datadog Logs.
- Metrics — numeric time-series. Tools: Prometheus, InfluxDB, Datadog, Grafana.
- Traces — request path. Tools: Jaeger, Tempo, Honeycomb, Datadog APM.
8.2. Cost control
Logs ở scale tốn nhiều: 1M req/day × 1KB/req = 1GB/day, nhân 30 service. Đắt khi dùng SaaS.
Strategies:
- Log levels — INFO/WARN/ERROR ở prod; DEBUG chỉ khi cần.
- Sampling — log 1% successful + 100% errors.
- Retention tier — hot 7 ngày, cold 90 ngày, archive 1 năm.
- Self-host — Loki/Grafana cho cost-conscious team.
- Cardinality control — metric label phải bounded (KHÔNG put userId làm label).
8.3. Structured logging
// ❌ Plain text
logger.info(`User ${userId} created order ${orderId}`);
// ✓ Structured JSON
logger.info('order.created', {
user_id: userId,
order_id: orderId,
amount: order.total,
trace_id: ctx.traceId,
});
Lợi: queryable. {level=error AND trace_id=xxx}. Faceted search.
8.4. Correlation ID
Mỗi request có unique ID propagate qua mọi service. Log mọi service kèm ID này → search 1 request flow.
app.use((req, res, next) => {
req.traceId = req.header('X-Trace-Id') || crypto.randomUUID();
res.setHeader('X-Trace-Id', req.traceId);
next();
});
// Mọi log:
logger.info('event', { traceId: req.traceId, ... });
Tốt nhất: tích hợp với OpenTelemetry → trace_id tự động trong log.
8.5. Metrics quan trọng — Golden Signals (Google SRE)
- Latency — P50, P95, P99 (cả success và error).
- Traffic — request/s.
- Errors — rate of 5xx, 4xx.
- Saturation — CPU, memory, disk, queue depth.
8.6. Alerting
Alert based on SLO violation, không noise:
- Error rate > 1% trong 5 phút → page on-call.
- P99 > 1s trong 10 phút → warning.
- Disk > 80% → warning.
- Disk > 95% → page.
- Replication lag > 30s → warning.
Alert fatigue là enemy. 1 alert <-> 1 actionable problem.
9. Bài tập
- Setup Cloudflare cho 1 static site: cache control header, Cache-Tag, purge by tag.
- Implement 4 thuật toán rate limiting trong Node.js + Redis. Đo memory, accuracy, performance khác biệt.
- Token Bucket atomic với Lua script: chi tiết. Test với concurrent request đồng thời, đảm bảo không over-allow.
- Setup Kong API Gateway local: route /users/* → user-service, /orders/* → order-service. Thêm plugin: rate limit, JWT auth, request logging.
- Phòng thủ cơ bản:
- Setup CSP cho 1 web app (đã học Networking Ch10).
- Add rate limit cho /login (5 attempt/15 phút per IP).
- JWT verify ở edge với Cloudflare Worker.
- Secret management: cài Vault local, store DB password, app fetch dynamic secret. Test rotation.
- Setup Prometheus + Grafana cho 1 service Node.js. Expose 4 golden signals. Tạo dashboard + alert khi error rate > 1%.
- OpenTelemetry: integrate vào 2 service Node.js. Trace request cross-service. Visualize trên Jaeger.
10. Quiz
Quiz cuối Chương 7
CDN giải vấn đề chính:
Token Bucket rate limiter:
Fixed Window rate limiting có vấn đề "burst boundary":
API Gateway xử lý cross-cutting concerns:
DDoS L7 (application layer) khó phát hiện hơn L3/L4 vì:
JWT validation at edge tradeoff chính:
Secret management best practice:
Google SRE "Four Golden Signals" cho monitoring:
Hoàn thành Chương 7. Tiếp theo: Chương 8 — Design Case Studies →