Nhân một người bạn hỏi về vấn đề này, mình take note lại vì đã được hỏi 2 lần :sosad:

ALB: là dịch vụ Application Load Balancer của AWS, một dịch vụ về cân bằng tải của AWS hoạt động ở layer 7 support giao thức HTTP/HTTPs, Websocket, HTTP2.

nginx: là một webserver opensource, support cả chức năng cân bằng tải ở layer 7 (có support ở layer 4 nhưng khá cơ bản).

Ngoài ALB và nginx thì còn có HAproxy cũng là một service cung cấp chức năng cân bằng tải ở layer 4 và layer 7 khá phổ biến.

Load balancer là dịch vụ sẽ phục vụ như một single point giao tiếp với user. Load balancer sẽ phân tán các incomming request từ user tới nhiều server phía sau LB nhằm mục đích scale hệ thống.

Câu hỏi đặt ra là khi xây dựng một hệ thống trên AWS, ta sẽ chọn cái gì để thực hiện chức năng cân bằng tải? ALB hay nginx? ưu nhược điểm của từng dịch vụ là gì?

Về bản chất, ALB và nginx hoạt động cùng chức năng cân bằng tải, một trong các rule khi thiết kế hệ thống đó là KISS, giữ cho hệ thống đơn giản nhất có thể, tránh gây confuse. Điều đó có nghĩa là về lý thuyết ta chỉ nên sử dụng một dịch vụ cho một chức năng cụ thể nào đó.

1. Chỉ xài ALB

Ưu điểm:

  • Chi phí rẻ, $20.
  • Support tính năng host-based và path-based giúp routing request tới các cụm host có chức năng khác nhau.
  • Tận dụng infra của AWS để hỗ trợ multi-zone, high availability dễ dàng.

Nhược điểm:

  • ALB chỉ hỗ trợ round robin algorithm.
  • Log của ALB không nhiều thông tin hữu ích cho việc build 1 in-house metric system như nginx.

Lưu ý thêm là round-robin là một thuật toán cân bằng tải rất không fair, LB sẽ tuần tự pass đều số lượng request incoming tới các instance phía sau mà không quan tâm trạng thái hay khả năng phục vụ của instance phía sau như thế náo. Sẽ dẫn tới trường hợp là:

  • Có instance xui xẻo sẽ chỉ nhận các heavy request, nhưng nó chưa kịp xử lý xong đã bị pass tiếp nhiều heavy request khác vào.
  • Có instance thì lại chỉ phải phục vụ các request rất nhanh, nhưng vì round-robin chia đều nên ở request tiếp theo nó vẫn có thể nhận được các request nhẹ nhàng đó tiếp.

Tính năng multi-zone là một tính năng khá khó xây dựng trên một hệ thống on-premise, hiểu đơn giản thì nếu bạn có một LB đặt ở DC Viettel thì bạn sẽ phải có 1 LB khác cùng chức năng, sync với nhau và heartbeat với nhau ở DC của FPT.

2. Nếu chỉ xài nginx

Một lựa chọn khác đó là thay vì sử dụng dịch vụ của AWS, ta có thể tự build LB và tự vận hành như các hệ thống on-premise. Đây là bài toán cũ mà bất cứ ai xây dựng hệ thống on-premise cũng đã từng gặp qua.

Ưu điểm:

  • Hỗ trợ nhiều thuật toán load balancer như round-robin, round-robin weight, ip_hash (session persistence), least-connected.
  • Log có nhiều thông tin hỗ trợ debug và metric.
  • Hỗ trợ nhiều module giúp thực hiện nhiều chức năng nâng cao:
    • lua modules.
    • headers-more-nginx-module -> giúp ẩn token hoặc làm sai lệch token từ server -> hữu ích khi cần che giấu công nghệ ở server-side.
    • Các module giao tiếp trực tiếp tới các service như redis, memcached, mysql …
  • Hỗ trợ các tính năng cản lọc cơ bản và lightweight ở tầng load balancer như block by ip, geoip, user-agent.
  • Hỗ trợ routing từ một dải IP vào một cụm server nào đó trong backend -> sẽ rất hữu ích khi muốn debug/test trên production mà không ảnh hưởng tới user.

Nhược điểm:

LB sẽ là single point of fail giữa user và server, sử dụng nginx làm LB ta phải đảm bảo được là dịch vụ LB sẽ luôn có khả năng dự phòng. Dự phòng ở đây cần đạt được ở 3 yêu cầu:

  • Dự phòng ở mức service, dịch vụ nginx phải luôn luôn được phục vụ hoặc ít nhất có khả năng tự restart để giảm thiểu thời gian downtime (nhưng restart sẽ force close current connection).
  • Dự phòng ở mức server, sẽ phải luôn có một server nginx tương tự để thay thế khi server chính bị hư hỏng phần cứng hoặc sập điện … Yêu cầu này có thể thực hiện ở khi sử dụng nginx + keepalived + floating IP.
  • Ở mức dự phòng server, ta cần phải đặt LB ở một khu vực khác ví dụ như ở 2 DC khác nhau, đây là vấn đề không dễ và so với chi phí $20 của AWS thì đây là một mức giá quá hời cho tính năng này.

Nói thêm về tính năng routing dựa trên client IP của nginx là nó vô cùng hữu ích khi ta cần test sản phẩm trên môi trường production, nhưng chỉ effect tới 1 lượng nhỏ user (ví dụ user là QC trong cty, routing dựa trên static ip của cty), ngoài ra cũng có thể routing tới 1 server mới với code mới nhưng database và các phần khác vẫn như cũ.

Về metric, ta có thể có metric dạng như vầy giúp đánh giá hệ thống.

nginx-metric-log

3. Tóm lại

Để tận dụng lợi thế của cả 2 dịch vụ, cuối cùng ta có diagram như sau:

alb_nginx_backend

Ngoài lý do ở đầu bài (do một người bạn hỏi) thì bài này nhằm thỏa mãn cho câu hỏi tại sao lại có 2 service cùng chức năng trong hệ thống. Thắc mắc, tự đặt câu hỏi, tự tìm câu trả lời luôn đem lại một cảm hứng giúp thúc đẩy đam mê trong công việc và thúc đẩy bản thân tự phát triển.