0
0
Lập trình
Admin Team
Admin Teamtechmely

Giải Quyết Vấn Đề Cân Bằng Tải với Giao Tiếp gRPC trong Kubernetes - Phần 1

Đăng vào 1 tháng trước

• 4 phút đọc

Giới thiệu

Khi triển khai ứng dụng gRPC trong môi trường Kubernetes, bạn có thể gặp khó khăn khi sử dụng Kubernetes Service để thực hiện cân bằng tải hiệu quả giữa các endpoint gRPC. Vấn đề này xảy ra khi một kết nối lâu dài (long-lived connection) từ client chỉ được định tuyến tới một pod duy nhất, gây giảm khả năng sử dụng tài nguyên của hệ thống, và tạo ra tình trạng một replica bị quá tải trong khi nhiều replicas khác vẫn trong trạng thái nhàn rỗi. Có thể hình dung một cách đơn giản là “thằng nhiều hộp sữa thằng không hộp nào”.

Thí nghiệm Để Làm Rõ Vấn Đề

Mình đã thực hiện một thí nghiệm với hai dịch vụ A và B, trong đó client gửi request tới A qua HTTP, sau đó request được chuyển tiếp tới B qua gRPC thông qua Kubernetes service của B. Đây là quy trình thí nghiệm:

  1. Chạy K6 script để gửi hàng loạt requests đồng thời vào service A.
  2. Trong quá trình này, quan sát logs của các pod service B.

Kết quả khá bất ngờ, khi chỉ một pod duy nhất nhận các requests trong suốt quá trình tải, trong khi các pod còn lại không nhận request nào.

Tại Sao Điều Này Xảy Ra Với gRPC?

Khác Biệt Giữa HTTP/1.1 và HTTP/2

HTTP/1.1

  • Mỗi request sử dụng một kết nối TCP riêng biệt.
  • Nhiều request đồng thời sẽ yêu cầu mở nhiều TCP connection.

HTTP/2

  • Tất cả các request và response truyền qua một kết nối TCP duy nhất.
  • Dữ liệu được gửi qua các stream độc lập với việc sử dụng lớp framing của HTTP/2.
  • Các stream có thể được gửi song song trên cùng một kết nối TCP, giúp loại bỏ tình trạng head-of-line blocking và tối ưu hóa băng thông.
  • Multiplexing cho phép dữ liệu từ nhiều request và response được gửi đồng thời qua một kết nối duy nhất.

Cơ Chế Hoạt Động Của gRPC Trên HTTP/2

Khi gRPC giao tiếp qua một kết nối TCP duy nhất, điều này có nghĩa là khi client gRPC mở kết nối tới Kubernetes Service, kết nối này sẽ được duy trì và không được mở thêm một kết nối mới cho các request tiếp theo. Do đó, tất cả các request được chuyển đến một pod cụ thể mà không có khả năng phân phối lại giữa các pod khác.

Tại Sao Kubernetes không Thực Hiện Cân Bằng Tải Trong Trường Hợp Này?

Kubernetes Service chủ yếu hoạt động thông qua Kube-proxy, và cơ chế cân bằng tải của nó hoạt động ở Layer 4. Khi một client gRPC mở kết nối TCP, Kube-proxy chỉ chuyển tiếp kết nối tới một pod nhất định tại thời điểm thiết lập ban đầu. Sau đó, toàn bộ lưu lượng sẽ tiếp tục được gửi đến cùng một pod mà không gia tăng sự phân phối.

Điều Này Không Xảy Ra Với HTTP/1.1?

Trong trường hợp của HTTP/1.1, mỗi request sẽ tạo một kết nối TCP mới. Điều này cho phép Kube-proxy phân phối các kết nối đến các pod khác nhau dựa trên cơ chế cân bằng tải mặc định, từ đó đạt được hiệu quả cân bằng tải tốt hơn.

Giải Pháp Cân Bằng Tải Cho gRPC

1. Sử Dụng Client-Side Load Balancing

Client-side load balancing là kỹ thuật cho phép client tự phân phối request đến nhiều endpoint khác nhau của backend service. Client cần quản lý danh sách endpoint (pod IP) và tích hợp logic cân bằng tải dựa trên danh sách này.

Service Discovery

Client có khả năng tự động cập nhật danh sách endpoint khi pod được thêm, xóa hoặc thay đổi nhờ vào Kubernetes DNS thông qua các bản ghi SRV hoặc A.

Logic Cân Bằng Tải Tại Client

Client phải tích hợp logic thực hiện cân bằng tải bằng cách sử dụng thư viện gRPC client hỗ trợ load balancing như grpc-go, grpc-java hoặc grpc-python.

2. Sử Dụng Service Mesh

Service Mesh cung cấp khả năng cân bằng tải như một tính năng tích hợp sẵn, với các công cụ phổ biến như Linkerd và Istio hỗ trợ Layer 7 load balancing, rất phù hợp với gRPC vì gRPC dựa trên HTTP/2.

Hoạt Động Của Service Mesh

  • Sidecar Proxy: Các sidecar proxy (như Envoy trong Istio hoặc proxy riêng của Linkerd) được triển khai cùng với mỗi pod, chịu trách nhiệm chuyển tiếp request và thực hiện các yêu cầu khác như mTLS, retry, hoặc circuit breaking.
  • Routing và Load Balancing: Service Mesh sẽ theo dõi toàn bộ các pod trong mesh, từ đó thực hiện cân bằng tải thông minh dựa trên các thuật toán như round-robin, least-request, hoặc random.

Kết Luận

Giao tiếp gRPC trong Kubernetes có thể gặp khó khăn khi cố gắng tích hợp với cơ chế load balancing mặc định. Tuy nhiên, với các giải pháp như Client-Side Load Balancing hoặc Service Mesh (Linkerd, Istio), chúng ta có thể đảm bảo hiệu quả phân tải và tính ổn định cho ứng dụng. Việc lựa chọn giải pháp cân bằng tải phù hợp sẽ phụ thuộc vào yêu cầu cụ thể về hiệu năng và quản lý của hệ thống. Hãy luôn kiểm tra và tối ưu hóa kiến trúc để đảm bảo hệ thống hoạt động hiệu quả và đáng tin cậy. Hy vọng bài viết sẽ giúp bạn có thêm kiến thức về networking trong Kubernetes và các vấn đề liên quan đến cân bằng tải.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào