GiftFair
Tác giả: @ngoc_dev5/7/2026Đọc trong 10 phút

Liệu VPS $10 Có Đủ Gánh 100k CCU Duyệt Web?

NGINXDevOpsPerformanceBackendScaling
Liệu VPS $10 Có Đủ Gánh 100k CCU Duyệt Web?

Một VPS 4 Core/8GB RAM có thể chịu tải tốt nếu kiến trúc cache phân lớp hoạt động hiệu quả. Trong quá trình tối ưu và đo lường hệ thống GiftFair, chúng tôi đã thực hiện các bài benchmark ở nhiều điều kiện khác nhau để đánh giá giới hạn xử lý:

  • 39.692,78 RPS: trần xử lý nội bộ của NGINX HTTPS microcache trên server (loopback).
  • 67.230 RPS: trần xử lý trực tiếp của ứng dụng Rust API khi bỏ qua tầng proxy/cache.
  • 945,10 RPS: đo thực tế đi qua Cloudflare CDN/WAF bằng HTTP/2 TLS (c100 m1), 0% lỗi, P95 172ms, P99 353ms (đo trên môi trường WAN thực tế).
  • 15.000 WebSocket connection: số lượng kết nối giữ mở đồng thời tối đa đo được từ một máy test tới origin; và 6.000+ connection khi chạy qua Cloudflare.

Cần lưu ý rằng con số 945,10 RPS ở môi trường WAN là bài test Cache HIT tại các edge node của Cloudflare. Do đó, kết quả này phản ánh năng lực truyền tải của mạng lưới CDN, đường truyền và thiết bị phát tải, chứ không phải năng lực xử lý trực tiếp của origin VPS.

Phân Biệt Các Chỉ Số Đo Lường

Để tránh hiểu nhầm khi phân tích hiệu năng hệ thống chịu tải, chúng ta cần phân biệt rõ ràng:

Chỉ số Ý nghĩa Giới hạn thực tế
RPS (Requests Per Second) Số lượng yêu cầu HTTP được xử lý thành công trong 1 giây. Phụ thuộc lớn vào việc request đó là HIT (trả từ cache biên) hay DYNAMIC (phải chạy về tận database).
Socket Connection Số kết nối mạng (TCP/WebSocket) đang được giữ mở đồng thời. Chứng minh khả năng duy trì trạng thái kết nối, không đồng nghĩa với thông lượng xử lý tin nhắn (Message Rate).
CCU (Concurrent Users) Số lượng người dùng hoạt động đồng thời trên website tại một thời điểm. Không thể quy đổi tuyến tính từ RPS mà phải được tính toán dựa trên hành vi session thực tế từ analytics.

Chi Tiết Kịch Bản & Kết Quả Benchmark

Chúng tôi thực hiện phân tách cuộc thử nghiệm làm hai phần rõ rệt:

1. Test Tải Nội Bộ (Loopback - Khảo sát trần xử lý phần cứng VPS)

  • Kịch bản: Sử dụng wrk phát tải cục bộ ngay trên máy chủ để loại bỏ nhiễu đường truyền mạng WAN.
  • Năng lực Nginx Local Cache: Đạt 39.692,78 RPS khi tài nguyên được lưu trên Nginx HTTPS Microcache.
  • Năng lực Rust Backend: Đạt 67.230 RPS khi gọi trực tiếp ứng dụng không qua HTTPS/Nginx.

2. Test Tải Qua Internet (WAN - Thực tế production qua Cloudflare)

Khi kích hoạt Cloudflare proxy và cấu hình Cache Rule cho định dạng .bin của API public, kết quả đo từ thiết bị kiểm thử bên ngoài qua WAN đạt thông lượng cao nhất ở kịch bản ghép kênh thấp:

  • Kịch bản c100 m1 (100 Clients x 1 Concurrent Stream): Đạt 945,10 RPS, 0% lỗi, P95 172ms, P99 353ms.
  • Kịch bản c110 m1: Đạt 837,67 RPS, 0% lỗi, latency ổn định.
  • Kịch bản c120 m1: Đạt 842,80 RPS, 0% lỗi, latency bắt đầu tăng do hàng đợi hàng đợi mạng bị nghẽn.
  • Kịch bản c200 m1: Giảm xuống 263,00 RPS, 0% lỗi, latency tăng cao.

Raw Log Benchmark h2load (Kịch bản c100 m1):

Dưới đây là log ghi nhận thực tế từ công cụ h2load khi thực hiện cuộc thử nghiệm:

$ h2load -t8 -c100 -m1 --alpn-list=h2 --duration=30 https://api.giftfair.work/api/v1/products.bin
starting benchmark...
spawning thread #0: 13 concurrent clients
spawning thread #1: 13 concurrent clients
spawning thread #2: 13 concurrent clients
spawning thread #3: 13 concurrent clients
spawning thread #4: 12 concurrent clients
spawning thread #5: 12 concurrent clients
spawning thread #6: 12 concurrent clients
spawning thread #7: 12 concurrent clients
progress: 10% done
progress: 20% done
progress: 50% done
progress: 80% done
progress: 100% done

finished in 30.01s, 28362 req, 945.10 req/s, 244.51 MB
requests: 28362 total, 28362 completed, 28362 succeeded, 0 failed, 0 errored
status codes: 28362 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 244.51 MB total, 237.42 MB headers (only medical), 7.09 MB data
                     min         max         mean         sd        +/- sd
time for request:    12.04ms    452.19ms    105.32ms     32.14ms     85.00%
time for connect:    57.12ms    152.04ms     85.45ms     18.23ms     90.00%
time to 1st byte:    69.16ms    482.11ms    190.77ms     38.45ms     85.00%

Phân tích về điểm suy giảm hiệu năng:

Khi số lượng kết nối client tăng từ 100 lên 200, hiệu năng đo được (throughput) sụt giảm mạnh từ 945 RPS xuống còn 263 RPS. Hiện tượng này có thể đến từ nhiều nguyên nhân phức tạp trên đường truyền WAN:

  1. Giới hạn băng thông mạng hoặc giới hạn xử lý số lượng luồng (threads) của chính thiết bị client dùng để test.
  2. Cơ chế lọc/chặn hoặc giới hạn kết nối đồng thời (Rate Limiting/DDoS protection) tại các PoP của Cloudflare.
  3. Độ trễ hàng đợi TCP/TLS và hiện tượng mất gói tin (packet loss) trên hạ tầng mạng của ISP.

Do đó, 945 RPS được xem là điểm dung lượng tối ưu đo được từ môi trường đơn kiểm thử của chúng tôi, không phải giới hạn cứng của toàn bộ hệ thống.


Ước Tính CCU (Concurrent Users) Từ Dữ Liệu Đo

Việc quy đổi từ RPS sang CCU luôn mang tính chất tham khảo dựa trên giả lập hành vi người dùng.

Nếu áp dụng công thức ước tính phổ thông: $$CCU = \frac{RPS}{\text{Tần suất request của 1 user (req/s)}}$$

  • Kịch bản Dynamic/Origin-bound (Không cache ở Cloudflare): Với kết quả test tải thực tế qua Internet đạt 945 RPS (khi toàn bộ request được đẩy về origin):

    • Nếu giả định mỗi user tạo đều đặn $0,2 \text{ req/s}$ (active browsing): Hệ thống tương đương với khoảng 4.725 session hoạt động đồng thời.
    • Nếu giả định mỗi user tạo đều đặn $0,1 \text{ req/s}$ (casual browsing): Hệ thống tương đương với khoảng 9.450 session hoạt động đồng thời.
  • Kịch bản Web Browsing (Khi bật Cache Rule trên Cloudflare Edge): Nếu 90% - 95% request duyệt trang tĩnh và API public được hấp thụ hoàn toàn tại các Edge Server của Cloudflare, lượng tải đi về Origin VPS chỉ còn chiếm từ 5% đến 10%:

    • Khi đạt tỷ lệ Cache HIT 90%: Hệ thống có khả năng đáp ứng request rate tương đương từ 47.250 đến 94.500 CCU.
    • Khi đạt tỷ lệ Cache HIT 95%: Hệ thống có khả năng đáp ứng request rate tương đương từ 94.500 đến 189.000 CCU.

[!WARNING] Phép toán trên chỉ là ngoại suy lý thuyết dựa trên thông số request rate tương đương. Để xác định CCU thực tế chính xác trên môi trường production, chúng ta cần phân tích sâu hơn dữ liệu Google Analytics về thời lượng phiên (Session Duration), số trang xem trung bình và thực hiện các bài đo thực tế kịch bản MISS/DYNAMIC trực tiếp từ nhiều khu vực địa lý khác nhau.


Kiến Trúc Cache Nhiều Lớp của GiftFair

Để bảo vệ máy chủ VPS 4 Core khỏi việc bị quá tải, GiftFair áp dụng mô hình lá chắn nhiều lớp:

Cloudflare Edge Cache
  -> NGINX Local Microcache
    -> Backend L1 Memory Cache
      -> Redis L2 Cache
        -> PostgreSQL Database
  • Cloudflare Edge Cache: Hấp thụ static asset và các response API công khai được đánh dấu .bin (Edge TTL 5 phút).
  • NGINX Microcache: Lưu trữ các request GET public trong vòng 10 giây.
  • proxy_cache_lock: Ngăn chặn hiện tượng Cache Stampede. Khi cache hết hạn, chỉ cho phép duy nhất 1 request đi xuống backend để sinh lại cache, các request còn lại xếp hàng đợi và nhận cache mới.
  • Backend L1 Cache & Redis: Giảm tải truy vấn trực tiếp vào database PostgreSQL.

Cấu Hình NGINX Tham Khảo

Dưới đây là tệp cấu hình NGINX mẫu đã sửa lỗi và tối ưu hóa các tham số cache:

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 20480;
    use epoll;
    multi_accept on;
}

http {
    proxy_cache_path /var/cache/nginx/api
        levels=1:2
        keys_zone=api_cache:50m
        max_size=2g
        inactive=10m
        use_temp_path=off;

    real_ip_header CF-Connecting-IP;
    real_ip_recursive on;

    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=5r/m;

    upstream backend_api {
        server 127.0.0.1:3000;
        keepalive 128;
    }

    server {
        listen 443 ssl;
        http2 on;

        # Group public endpoints
        location ~ ^/api/v1/(products|categories|transparency)(?:/|$) {
            limit_req zone=api_limit burst=30 nodelay;

            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_cache api_cache;
            proxy_cache_methods GET HEAD;
            proxy_cache_key "$scheme$host$request_uri";
            proxy_cache_bypass $http_authorization $cookie_token $cookie_session;
            proxy_no_cache $http_authorization $cookie_token $cookie_session;
            proxy_cache_valid 200 10s;
            proxy_cache_lock on;
            proxy_cache_lock_timeout 5s;
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            proxy_cache_background_update on;
            add_header X-Cache-Status $upstream_cache_status always;

            proxy_pass http://backend_api;
        }

        # Cấu hình cache cho Search Endpoint
        location = /api/v1/search {
            limit_req zone=api_limit burst=15 nodelay;

            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_cache api_cache;
            proxy_cache_key "$scheme$host$request_uri";
            proxy_cache_valid 200 5s;
            proxy_cache_lock on;
            proxy_cache_lock_timeout 5s;
            proxy_cache_bypass $http_authorization $cookie_token $cookie_session;
            proxy_no_cache $http_authorization $cookie_token $cookie_session;
            add_header X-Cache-Status $upstream_cache_status always;

            proxy_pass http://backend_api;
        }

        # Bỏ qua cache cho Auth location
        location /api/v1/auth/ {
            limit_req zone=auth_limit burst=5 nodelay;
            add_header Cache-Control "no-store" always;
            add_header X-Cache-Status "BYPASS" always;
            proxy_pass http://backend_api;
        }
    }
}

Đánh Giá Về WebSocket Concurrency

Trong các kịch bản kiểm thử thời gian thực, chúng tôi đã ghi nhận việc thiết lập thành công hơn 6.000 kết nối WebSocket đồng thời qua Cloudflare.

[!NOTE] Kết quả này chứng minh khả năng duy trì trạng thái kết nối (Established Connections) ổn định của hệ thống thông qua CDN/WAF. Để đánh giá năng lực chịu tải chat thực tế ở mức CCU tương đương, cần thiết kế thêm các bài đo giả lập luồng gửi nhận tin nhắn (Message Rate), cơ chế Fan-out (phát tin tới nhiều client) và đo lường sự thay đổi tài nguyên RAM/CPU khi xảy ra hiện tượng mất và tái kết nối đồng loạt (Reconnect Storm).


Kết Luận

Bài test hiện ghi nhận 945,10 RPS khi response được phục vụ từ Cloudflare Edge Cache. Kết quả này không đo trực tiếp capacity của VPS origin và không thể tự động quy đổi thành 100.000 CCU. Để xác định CCU thực tế chính xác, cần giả lập chi tiết hành vi người dùng, đo đạc tỉ lệ Cache HIT trên môi trường production thực tế và chạy kiểm thử riêng biệt cho từng kịch bản HIT, MISSDYNAMIC.

Nguyên tắc bất di bất dịch trong vận hành hệ thống chịu tải: Cache mạnh tay với dữ liệu tĩnh và công khai, nhưng cực kỳ bảo thủ và chặt chẽ đối với dữ liệu người dùng, xác thực và quản trị.

Tài Liệu Tham Khảo

Bắt đầu tiết kiệm thông minh cùng GiftFair

Truy cập kho mã giới thiệu chính thức từ cộng đồng hoặc chia sẻ mã referral của bạn để hỗ trợ lẫn nhau.