Reading Time: 11 minutes

Bạn đang bắt đầu một dự án web mới.

  • Tính năng? Đã có bản đặc tả.
  • Frontend? Có team dev lo.
  • Backend? Triển khai API chạy ổn rồi.

Nhưng rồi đến một câu hỏi “hóc búa” hơn:

Triển khai ở đâu? Sử dụng mô hình server nào? Load balancer có cần không? Auto scaling hay chạy cố định?

Nghe có vẻ như việc của DevOps, nhưng thực tế, lựa chọn kiến trúc server là bước đi chiến lược ảnh hưởng trực tiếp đến hiệu suất, chi phí và cả khả năng vận hành lâu dài của hệ thống. Không ít sản phẩm gặp rắc rối chỉ vì “build xong mà không biết chạy ở đâu cho phù hợp”.

Trong bài viết này, mình sẽ cùng bạn đi qua 5 mô hình server phổ biến nhất trong triển khai ứng dụng web – từ đơn giản đến phức tạp. Mỗi mô hình đều đi kèm mô tả, ưu điểm, nhược điểm – và đặc biệt là góc nhìn thực tế về việc khi nào thì nên dùng cái nào.

Thiết lập mọi thứ trên một máy chủ

Hầu hết các dự án web đều bắt đầu từ đây.

Mô hình đơn giản nhất – toàn bộ hệ thống được “nhét gọn” vào một máy chủ duy nhất: web server, ứng dụng backend, cơ sở dữ liệu. Một biến thể phổ biến của thiết lập này là ngăn xếp LAMP , viết tắt của Linux, Apache, MySQL và PHP, trên một máy chủ duy nhất

Nghe có vẻ mạo hiểm? Nhưng không hẳn là vậy.

Đây thực sự là lựa chọn hợp lý cho các web demo, hoặc sản phẩm nội bộ với lượng truy cập thấp. Nó giúp bạn tiết kiệm chi phí, dễ quản lý, và triển khai cực nhanh – chỉ cần một script là có thể chạy toàn bộ hệ thống trong vài phút.

Tuy nhiên, như bạn có thể đoán, mô hình này không có khả năng mở rộng tốt. Khi traffic tăng hoặc hệ thống phức tạp hơn, việc tất cả tài nguyên “giành nhau” như CPU, Bộ nhớ, I/O, v.v trên cùng một máy sẽ nhanh chóng dẫn đến nghẽn cổ chai, lỗi dịch vụ, và mất tính sẵn sàng. Sau đây là hình ảnh minh họa về việc sử dụng một máy chủ duy nhất:

Ưu điểm:

  • Cài đặt nhanh chóng, dễ triển khai.
  • Chi phí thấp – chỉ cần một máy chủ.
  • Dễ quản lý với team nhỏ, không cần DevOps chuyên sâu.

Nhược điểm:

  • Không có tính dự phòng – máy chết là toàn bộ hệ thống.
  • Khó mở rộng – scale ngang hay dọc đều gặp giới hạn.
  • Khó tách biệt các dịch vụ nếu cần tối ưu hoặc bảo trì riêng.

Vậy việc tách cơ sở dữ liệu riêng có thể giải quyết được các nhược điểm của mô hình này chúng ta đi sang mô hình tiếp theo

Thiết lập một máy chủ cơ sở dữ liệu riêng biệt

Sau một thời gian sử dụng mô hình “gói gọn mọi thứ trong một máy”, bạn sẽ bắt đầu nhận ra điểm nghẽn thường xuyên nhất chính là… cơ sở dữ liệu. Hệ thống quản lý cơ sở dữ liệu (DBMS) có thể được tách biệt khỏi phần còn lại của môi trường để loại bỏ sự tranh chấp tài nguyên giữa ứng dụng và cơ sở dữ liệu, đồng thời tăng cường bảo mật bằng cách xóa cơ sở dữ liệu khỏi DMZ hoặc internet công cộng.

Trong mô hình này, bạn vẫn giữ backend, frontend và các thành phần còn lại trên một server, nhưng di chuyển database sang một server khác, chuyên biệt cho việc lưu trữ và truy vấn dữ liệu.

Thiết lập này phức tạp hơn một chút so với một máy chủ đơn. Các vấn đề về hiệu suất, như độ trễ cao, có thể phát sinh nếu kết nối mạng giữa hai máy chủ cách xa nhau về mặt địa lý. Cũng có thể có các vấn đề về hiệu suất nếu băng thông quá thấp so với lượng dữ liệu được truyền. Bạn có thể đọc thêm về Cách thiết lập cơ sở dữ liệu từ xa để tối ưu hóa hiệu suất trang web bằng MySQL . Sau đây là hình ảnh minh họa về việc sử dụng máy chủ cơ sở dữ liệu riêng biệt:

Ưu điểm:

  • Tăng hiệu năng: web server không tranh chấp tài nguyên với database.
  • Dễ backup và bảo trì: Có thể thực hiện sao lưu dữ liệu mà không ảnh hưởng đến frontend/backend.
  • Bảo mật tốt hơn: Có thể đặt database trong mạng nội bộ, ẩn hoàn toàn khỏi public.

Nhược điểm:

  • Tăng chi phí: Thêm một máy chủ đồng nghĩa với thêm chi phí vận hành.
  • Cần cấu hình kết nối cẩn thận: Đảm bảo app và DB server có thể giao tiếp an toàn, ổn định.
  • Vẫn chưa tối ưu hoàn toàn cho scale lớn: Vì frontend/backend vẫn đang chia sẻ tài nguyên với nhau.

Vậy mô hình này phù hợp với các trường hợp nào, đầu tiên là các ứng dụng web có bảng dữ liệu lớn, nhiều người dùng, hoặc dùng tính năng tìm kiếm nâng cao, báo cáo, dashboard… tiếp theo là

các hệ thống nội bộ doanh nghiệp cần độ tin cậy cao về dữ liệu nhưng chưa cần hạ tầng phức tạp. Với mô hình này máy chủ cơ sở dữ liệu có vẻ tạm ổn bây giờ chúng ta cần quan tâm đến các thành phần khác cụ thể là web server, chúng ta cùng tìm hiểu mô hình tiếp theo

Thiết lập bộ cân bằng tải (Proxy ngược)

Khi hệ thống đã có một máy chủ riêng cho cơ sở dữ liệu, bạn có thể thấy hiệu suất được cải thiện rõ rệt. Tuy nhiên, sau một thời gian, backend hoặc web server lại bắt đầu… quá tải.

Và thế là bài toán quen thuộc quay lại:

Làm sao để chia tải? Làm sao để hệ thống không sập nếu một node bị lỗi?

Đây chính là lúc mô hình có bộ cân bằng tải phát huy tác dụng.

Load Balancer (bộ cân bằng tải) là thành phần trung gian giúp phân phối khối lượng công việc (traffic) đến nhiều máy chủ backend cùng lúc. Thay vì client truy cập trực tiếp vào một server duy nhất, mọi request sẽ được gửi đến Load Balancer – và từ đó, nó tự động chọn một server khỏe mạnh để xử lý. Nếu một trong các server phía sau bị lỗi, Load Balancer sẽ loại node đó khỏi vòng quay, và chuyển toàn bộ lưu lượng sang các máy chủ còn lại – cho đến khi node bị lỗi được khôi phục.

Không chỉ phân tải – mà còn làm được nhiều hơn

Trong môi trường hiện đại, nhiều hệ thống dùng Load Balancer còn để:

  • Phục vụ nhiều ứng dụng khác nhau trên cùng một tên miền và cổng (ví dụ example.com/api, example.com/admin, example.com/user) bằng cách sử dụng proxy ngược lớp 7 (tầng ứng dụng – HTTP).
  • Xử lý SSL, nén dữ liệu (gzip), cache tĩnh và thậm chí kiểm soát truy cập.

Các phần mềm cân bằng tải phổ biến hiện nay bao gồm: Nginx, HAProxy.

Thiết lập bộ cân bằng tải có thể gây ra tình trạng tắc nghẽn hiệu suất nếu bộ cân bằng tải không có đủ tài nguyên hoặc nếu nó được cấu hình kém.

Sau đây là hình ảnh minh họa về cách thiết lập bộ cân bằng tải:

Ưu điểm:

  • Cải thiện hiệu suất tổng thể: Bằng cách chia đều tải cho nhiều server.
  • Tăng độ tin cậy: Một node hỏng, hệ thống vẫn hoạt động bình thường.
  • Triển khai nhiều app trên cùng một domain: Rất hữu ích khi bạn muốn gom mọi thứ về một địa chỉ duy nhất.
  • Dễ tích hợp các chức năng bảo mật và tối ưu hóa như SSL, gzip, firewall…

Nhược điểm:

  • Phức tạp hơn khi cấu hình và giám sát.
  • Load Balancer có thể trở thành điểm nghẽn nếu không có cơ chế phân tán hoặc dự phòng.

Mô hình này phù hợp khi nào?

  • Khi hệ thống bắt đầu có nhiều server backend, cần chia tải thông minh.
  • Khi bạn muốn đảm bảo tính sẵn sàng cao (High Availability).
  • Khi cần phục vụ nhiều app, microservice hoặc API khác nhau trên cùng một domain.

Vậy còn mô hình nào giúp cải thiện hiệu năng của web tăng trải nghiệm cho người dùng nữa không ? Ta cùng nhau tìm hiểu về mô hình web server có thành phần bộ đệm HTTP.

Thiết lập bộ đệm HTTP (bộ đệm proxy ngược HTTP )

Sau khi đã triển khai bộ cân bằng tải để xử lý nhiều server phía sau, có thể bạn sẽ nhận ra một điều: có những nội dung được truy cập lặp đi lặp lại, nhưng backend vẫn phải xử lý lại từ đầu mỗi lần.

Ví dụ:

  • Trang chủ của bạn được truy cập hàng ngàn lần mỗi giờ.
  • Hình ảnh, JS, CSS – không đổi, nhưng vẫn tiêu tốn tài nguyên.
  • Các API public như /products, /news, /blog thường xuyên được gọi, dù dữ liệu không thay đổi liên tục.

Lúc này, thay vì để backend “vắt kiệt sức” xử lý lại mọi thứ, bạn có thể thêm một lớp thông minh phía trước:

Reverse Proxy Cache hoạt động như một “bức tường lửa hiệu năng” phía trước backend:

  • Khi người dùng truy cập một trang, reverse proxy sẽ gửi request về backend như bình thường.
  • Kết quả phản hồi sẽ được lưu tạm (cache) trong bộ đệm HTTP.
  • Các lần truy cập tiếp theo sẽ được phục vụ ngay từ cache – nhanh hơn, nhẹ hơn, không cần backend xử lý lại.

Một số ví dụ về phần mềm có khả năng tăng tốc HTTP là Varnish, Squid, Nginx. Sau đây là hình ảnh minh họa về cách thiết lập bộ đệm HTTP:

Ưu điểm:

  • Tăng tốc độ phản hồi đáng kể: Các request được trả về gần như ngay lập tức.
  • Giảm tải cho backend: Ít request phải xử lý → tiết kiệm CPU, RAM, database.
  • Cải thiện trải nghiệm người dùng: Đặc biệt khi truy cập từ xa hoặc qua mạng di động.
  • Có thể thiết lập TTL (thời gian sống) linh hoạt: Phù hợp với cả nội dung tĩnh và nội dung thay đổi chậm.

Nhược điểm:

  • Không phù hợp với nội dung cập nhật thường xuyên.
  • Có thể gây lỗi nếu dữ liệu đã cũ nhưng chưa được “xóa khỏi bộ nhớ”.
  • Cần kiểm soát cache key cẩn thận – nếu không, người dùng có thể thấy dữ liệu không đúng.

Dù bạn đã tối ưu tốc độ phản hồi bằng bộ đệm HTTP, thực tế là không phải request nào cũng có thể cache được. Những tác vụ như xác thực người dùng, giao dịch, xử lý đơn hàng… luôn cần truy vấn cơ sở dữ liệu theo thời gian thực.

Và đó là lúc cơ sở dữ liệu bắt đầu trở thành điểm nghẽn tiếp theo.

Đặc biệt khi:

  • Số lượng người dùng tăng lên
  • Có nhiều truy vấn đọc liên tục (SELECT)
  • Bạn muốn giữ database luôn sẵn sàng, kể cả khi có sự cố xảy ra

Vậy chúng ta cùng tìm hiểu tiếp mô hình sẽ giúp quyết vấn đề trên

Thiết lập sao chép cơ sở dữ liệu Primary-replica

Trong các hệ thống web có quy mô vừa và lớn, cơ sở dữ liệu thường là điểm chịu tải nặng nhất – đặc biệt là khi có nhiều truy vấn đọc dữ liệu (SELECT) đến từ các API, dashboard, báo cáo, hay frontend cần hiển thị real-time. Lúc này, chỉ một máy chủ database là không đủ. Bạn cần phân tán tải truy vấn ra nhiều nơi mà không làm mất tính nhất quán của dữ liệu.

Mô hình hoạt động thế nào?

  • Primary (hay Master): Là nơi xử lý tất cả các thao tác ghi dữ liệu (INSERT, UPDATE, DELETE).
  • Replica (hay Slave): Nhận dữ liệu sao chép từ Primary, thường theo thời gian thực hoặc gần như real-time. Replica chỉ thực hiện truy vấn đọc (SELECT).

Các ứng dụng hoặc API có thể được cấu hình để:

  • Gửi truy vấn ghi về Primary
  • Gửi truy vấn đọc về các Replica

Việc phân chia này giúp giảm áp lực cho Primary, đồng thời tăng hiệu năng đọc tổng thể mà không cần nâng cấp một máy duy nhất. Sau đây là hình ảnh minh họa thiết lập sao chép primary-replica, với một nút replica duy nhất:

Ưu điểm:

  • Tăng khả năng đọc (read throughput): Thêm Replica → thêm khả năng phục vụ request đọc.
  • Tăng tính sẵn sàng: Nếu Primary gặp sự cố, có thể nâng một Replica lên làm Primary mới (failover).
  • Hữu ích cho báo cáo, phân tích: Replica có thể dùng cho các truy vấn nặng như dashboard, analytics mà không ảnh hưởng đến dữ liệu vận hành.
  • Có thể đặt Replica gần người dùng hơn (VD: Replica ở US, EU, VN…) để tối ưu tốc độ phản hồi theo vùng địa lý.

Nhược điểm:

  • Dữ liệu không đồng bộ 100% real-time: Có thể có độ trễ nhỏ giữa Primary và Replica (thường chỉ vài giây, nhưng có thể ảnh hưởng đến các giao dịch nhạy cảm).
  • Viết vào Replica sẽ gây lỗi: Hệ thống phải đảm bảo ứng dụng chỉ ghi vào Primary.

Sau khi đi qua 5 mô hình phổ biến ta đã có 1 cái nhìn tổng quan cũng như các cách xử lý để tối ưu tài nguyên cho từng mục đích sử dụng vẫn còn nhiều mô hình khác như Database Sharding, Container hóa (Kubernetes) sẽ được tìm hiểu ở các bài viết sau, bây giờ chúng ta thử gộp cả 5 mô hình trên vào một để xem kết quả sẽ như thế nào

Mô hình kết hợp

Sau đây là sơ đồ ví dụ về kiểu thiết lập môi trường máy chủ này:

Ví dụ, hãy tưởng tượng một tình huống trong đó bộ cân bằng tải được cấu hình để nhận dạng các yêu cầu tĩnh (như hình ảnh, CSS, JavaScript, v.v.) và gửi các yêu cầu đó trực tiếp đến máy chủ lưu trữ đệm, đồng thời gửi các yêu cầu khác đến máy chủ ứng dụng.

Sau đây là phân tích về quy trình khi người dùng gửi yêu cầu về nội dung động:

  1. Người dùng yêu cầu nội dung động từ http://ví dụ.com/(bộ cân bằng tải)
  2. Bộ cân bằng tải gửi yêu cầu đến ứng dụng-backend
  3. Ứng dụng-backend đọc từ cơ sở dữ liệu và trả về nội dung được yêu cầu cho bộ cân bằng tải
  4. Bộ cân bằng tải trả về dữ liệu được yêu cầu cho người dùng

Khi người dùng yêu cầu nội dung tĩnh, quy trình sau sẽ được áp dụng:

  1. Bộ cân bằng tải kiểm tra cache-backend để xác nhận xem nội dung được yêu cầu có được lưu vào bộ nhớ đệm (cache-hit) hay không (cache-miss)
  2. Nếu nội dung là cache-hit thì điều này có nghĩa là nó sẽ trả về nội dung được yêu cầu cho bộ cân bằng tải và nhảy đến bước cuối cùng trong quy trình và trả về dữ liệu cho người dùng. Nếu nội dung là cache-miss, máy chủ bộ nhớ đệm sẽ chuyển tiếp yêu cầu đến app-backend thông qua bộ cân bằng tải
  3. Bộ cân bằng tải chuyển tiếp yêu cầu đến app-backend
  4. Ứng dụng-backend đọc từ cơ sở dữ liệu và trả về nội dung được yêu cầu cho bộ cân bằng tải
  5. Bộ cân bằng tải chuyển tiếp phản hồi đến cache-backend
  6. Bộ đệm lưu trữ nội dung và trả về bộ cân bằng tải
  7. Bộ cân bằng tải trả về dữ liệu được yêu cầu cho người dùng

Phần kết luận

Chúng ta vừa đi qua một hành trình từ những thiết lập đơn giản nhất – như một server duy nhất, đến những mô hình phức tạp hơn như replication. Mỗi mô hình đều có ưu – nhược điểm riêng, và quan trọng nhất là: Không có giải pháp “chuẩn” cho tất cả – chỉ có giải pháp phù hợp với giai đoạn, mục tiêu và nguồn lực của bạn.

Lời khuyên cuối cùng

  • Hãy bắt đầu đơn giản. Đừng quá phức tạp mô hình ngay từ đầu nếu bạn chưa có người dùng thật.
  • Mở rộng khi cần thiết. Khi bạn thấy điểm nghẽn xuất hiện, hãy chọn mô hình phù hợp để giải quyết nó – từng bước một.
  • Tự động hóa và giám sát càng sớm càng tốt. Đừng đợi đến khi hệ thống “cháy” rồi mới tìm cách dập lửa.

0 Bình luận

Đăng nhập để thảo luận

CyStack blog

Mẹo, tin tức, hướng dẫn và các best practice độc quyền của CyStack

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.