API Gateway căn bản

advance Mar 31, 2021

Microservice

Để nói về API Gateway thì trước tiên có lẽ sẽ cần giới thiệu một chút về Microservice. Vậy Microservice là gì ?

Nói một cách đơn giản thì Microservice là một mẫu kiến trúc trong đó một ứng dụng sẽ được cấu thành bởi một tập hợp các service (components) có những đặc tính sau :  
- Được quy định rõ ràng về scope và được tổ chức xung quanh business capabilities
- Được tổ chức đóng gói một cách chạt chẽ 
- Có khả năng maintaince cao và có khả năng test được 
- Ràng buộc lỏng lẻo ( loosely coupled )
- Có khả năng deploy một cách độc lập 

Các services sẽ hoạt động cùng nhau để đáp ứng business requests một cách linh động  đối nghịch với mô hình nguyên khối nơi mọi thứ được gắn chặt chẽ với nhau. Hơn nữa bằng cách chia nhỏ ứng dụng thành các services làm tăng khả năng triển khai, mở rộng, khả năng chịu lỗi và dễ dàng lựa chọn công nghệ thích hợp cho phát triển từng phần của ứng dụng.

Tuy nhiên theo chân lý "không có bữa ăn nào là miễn phí", ứng dụng xây dựng trên kiến trúc microservices có những vấn đề của riêng nó cần được giải quyết. Một vấn đề dễ thấy đó là làm thế nào để có thể gọi các service để thực hiện business request khi mà một ứng dụng hiện giờ đã đang chia thành hàng trăm components nhỏ?

Fig: What is the communication methods

Communication Method

Direct communication

Cách tiếp cận đầu tiên và cũng là cách tiếp cận dễ nhất đó chính là "Direct Communication"- hay giao tiếp trực tiếp trong đó :

  • Mỗi microservice sẽ public 1 endpoint
  • Mỗi endpoint sẽ được gắn với 1 load balancer nhằm mục đích phân phối request tới các instances bên dưới hosting microservice đó. Điều này đảm bảo khả năng availability của service cao hơn, tránh trường hợp khi chỉ có một instance của service sẽ vô tình hình thành một bottle neck.
  • Client sẽ gọi trực tiếp service thông qua public endpoint
Fig 2 : Direct communication

Giao tiếp trực tiếp tuy đơn giản nhưng rõ ràng cũng thể hiện những điểm khó khăn trong việc thực thi:

  • Client sẽ phải ghi nhớ và lưu trữ toàn bộ các endpoint của các services.
  • Client sẽ phải đủ thông minh để thực hiện phối hợp các request đến các service khi một business request liên quan đến thực thi của nhiều hơn 1 service
  • Việc gọi nhiều service thông qua môi trường network là không hề ổn với các thiết bị mobile và hệ thống mạng không ổn định ( vốn là tiền đề cần được xem xét khi nói về giao tiếp qua mạng )
  • Do quan hệ giữa client và service ràng buộc chặt chẽ nên nếu refactoring service client sẽ bị ảnh hưởng trực tiếp
  • Như đã nói ở đặc điểm của microservice đó là mỗi service có sự độc lập trong việc implementation nên hoàn toàn có thể có giao thức trao đổi khác nhau; trong trường hợp đó client sẽ phải ghi nhớ giao thức của từng loại service cũng như cần khả năng thực hiện toàn bộ các loại giao thức mà ứng dụng yêu cầu.
  • Do trong microservice các service tuân thủ "share as little as possible" nên các tính năng chung như : authentication, authorization, log, cache ... sẽ cần được implement bởi toàn bộ các service.

Với các lí do kể trên, thật sự khó có thể tiến hành cách tiếp cận này trong điều kiện thực tế.

API Gateway

Như vậy có thể thấy bản chất việc chia ứng dụng thành nhiều service con có nhiều ưu điểm nhưng làm xuất hiện đòi hỏi về việc xử lý loại bỏ side-effect của việc tăng lượng communication một cách phân tán từ phía client. API Gateway được giới thiệu như là một giải pháp cho vấn đề này.

API Gateway: là một servers ( nhóm server ) đóng vai trò như là một lối vào duy nhất để truy cập các dịch vụ ( tương tự khái niệm facade trong object oriented design pattern). API gateway sẽ thực hiện 2 loại công việc chính 
- Điều hướng các request từ client đến service tương ứng 
- Thực hiện điều hướng request đến một tập các service ( fan-out ) 
Fig 3 : API Gateway pattern

Như có thể thấy ở hình trên, API Gateway sẽ quản lý endpoint của toàn bộ các service, protocol để nói chuyện với chúng và thay thế client nói chuyện với các service. Bởi vì API Gateway thực hiện việc đóng gói toàn bộ ứng dụng ( câu thành bởi các services ) nên client lúc này sẽ chỉ cần quan tâm đến communicate với endpoint của API Gateway duy nhất thay vì bản thân các services ( Đối với client API Gateway và toàn bộ microservices phía sau trở thành 1 khối ).

Các tính năng cơ bản cần có của API Gateway:

  • Routing : Quản lý các dịch vụ và phân phối request từ client đến dịch vụ tương ứng.
  • Offloading : Cung cấp khả năng giảmtải thôngqua cung cấp các cross-cutting function sử dung chung bởi các microservices.

— Authentication and authorization

— Service discovery integration

— Response caching

— Retry policies, circuit breaker, and QoS

— Rate limiting and throttling

— Load balancing

— Logging, tracing, correlation

— Headers, query strings, and claims transformation

— IP whitelisting

— Centralized Logging (transaction ID across the servers, error logging)

  • API Composition / Aggregration
Fig 5: API Composition 
  • Protocol translation : giải quyết bài toán về sự đa dạng của communication protocol
Fig 6: Protocol Translation
  • Service Mesh : Service Mesh trong microservice là một network infrastructure layer có thể cấu hình được nhằm cung cấp giải pháp cho phép thực hiện các liên lạc nội bộ giữa các services. Nó cung cấp các tính năng như :

— Load Balancing

— Service Discovery

— Health Checks

— Security

Fig 7 : Service Mesh Architecture

Note : Có thể nhận thấy API gateway là một traffic bottle neck và single point of failure nên nếu API gateway bị quá tải hoặc không khả dụng thì sẽ là một thảm hoạ. Chính vì vậy trong thiết kế thực tế, API Gateway thường hiếm khi được host bởi 1 instance mà thường là được host bởi nhiều instance với endpoint được attach vào load balancer của chính API Gateway từ đó cũng cấp khả năng high-availabilty cho API gateway.

Đánh giá

Lợi ích

  • Đóng gói cấu trúc bên trong của ứng dụng, giảm sự phụ thuộc giữa client và ứng dụng
  • Client chỉ cần nói chuyện với gateway thay vì các services
  • Giảm thiểu trao đổi qua lại giữa client và ứng dụng từ đó đơn giản hoá client code
  • Các cross-cutting function được cung cấp để giảm tải cho services.
  • Security : nếu không có API Gateway thì toàn bộ services sẽ cần được exposed ra thế giới bên ngoài và tạo ra nguy cơ về an ninh

Điểm hạn chế

  • Khi xây dung API Gateway vô tình chúng ta đã gắn chặt nó với internal microservices.
  • API Gateway là single point of failure
  • API Gateway có thể làm tăng response time thông qua việc tiến hành thêm các cuộc gọi network tuy ảnh hưởng đó không thực sự lớn so với roud trip của việc không thực hiện sử dung API Gateway
  • Nếu không scale tốt thì API Gateway sẽ là một bottleneck
  • API Gateway sẽ yêu cầu cần thêm chi phí phát triển và bảo trì trong tương lai khi mà nó chứa cả các custom logic và data aggregation.
  • Developer sẽ cần update API Gateway để expose từng microservice’s endpoints.
  • Thêm vào đó việc thay đổi internal microservice có thể dẫn đến sự thay đổi ở tầng API Gateway.

Mở rộng

Như đã trình bày ở trên, việc chia ứng dụng thành các service cho phép mỗi service được phát triển bởi một đội và không gây ra việc bottle neck về development. Tuy nhiên đối với API Gateway do là đơn thể nên sẽ thường được phát triển và bảo trì bởi một đội phát triển, điều này sẽ tạo ra một development bottle-neck. Thêm vào đó, xuất phát từ yêu cầu thực tế, có nhiều loại client khác nhau phục vụ các yêu cầu business và trải nhiệm của các end-user khác nhau như mobile end-user, web end-user.

Từ 2 phân tích này thấy rằng sẽ rất phù hợp nếu API Gateway thay vì là một hệ thống đơn thể thì sẽ được chia ra thành nhiều thành phần, mỗi thành phần được phát triển/ bảo trì bởi một đội riêng và phục vụ một nhu cầu trải nghiệm riêng của mỗi loại end-user. API Gateway pattern đã có một biến thể phục vụ việc đó và được gọi là Backend for Fronend hay viết tắt là BFF.

Như vậy API Gateway sẽ có nhiều hơn 1 endpoint tuy nhiên số lượng endpoint BFF sẽ không quá nhiều do trên thực tế loại yêu cầu trải nghiệm của end-user không quá đa dạng như số lượng service.

Hands-on part

Một số loại API Gateway khá nổi tiếng

Trong các loại trên thì Kong Api khá dễ cài đặt và sử dụng cho mục đích trải nghiệm nên xin phép đươc giơi thiệu đến các bạn.

Prerequisite: Cài docker lên máy https://docs.docker.com/get-docker/

Step 1:  Tạo DB cho Kong ( option Postgres ), KONG hỗ trợ cả Cassandra nhưng không nên dùng nếu chỉ định thử nghiệm local. 

docker run -d --name kong-database \
               --network=kong-network \
               -p 5432:5432 \
               -e "POSTGRES_USER=your_user_name" \
               -e "POSTGRES_DB=kong" \
               -e "POSTGRES_PASSWORD=your_password" \
               postgres:9.6
Step 2: Chạy migrate để tạo db cho Kong 

docker run --rm \
     --network=kong-network \
     -e "KONG_DATABASE=postgres" \
     -e "KONG_PG_HOST=kong-database" \
     -e "KONG_PG_USER=your_user_name" \
     -e "KONG_PG_PASSWORD=your_password" \
     kong:latest kong migrations bootstrap
     
Step 3: Chạy instance Kong API Gateway ( Các bạn tuỳ chỉnh cổng map với host theo ý mình )

docker run -d --name kong \
     --network=kong-network \
     -e "KONG_DATABASE=postgres" \
     -e "KONG_PG_HOST=kong-database" \
     -e "KONG_PG_USER=your_user_name" \
     -e "KONG_PG_PASSWORD=your_password" \
     -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
     -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
     -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
     -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
     -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
     -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
     -p 8880:8000 \
     -p 8443:8443 \
     -p 0.0.0.0:8881:8001 \
     -p 0.0.0.0:8444:8444 \
     kong:latest
 
Step 4: Để thao tác với Kong API Gateway ta cần dùng API và khá là bất tiện cho người không chuyên nên ta cũng tiến hành cài luôn GUI Admin cho dễ. Mình giới thiệu các bạn dùng Konga : https://github.com/pantsel/konga

Step 4.1: Dựng DB cho Konga và khởi tạo  
docker run --rm --network=kong-network pantsel/konga -c prepare -a postgres -u postgresql://your_user_name:your_password@kong-database:5432/konga_db

Step 4.2: Chạy docker konga và enjoy 

docker run -p 1337:1337 \
     --network=kong-network \ 
     -e "DB_ADAPTER=postgres" \
     -e "DB_HOST=kong-database" \
     -e "DB_PASSWORD=your_password" \
     -e "DB_USER=your_user_name" \
     -e "DB_DATABASE=konga_db" \  
     -e "KONGA_HOOK_TIMEOUT=120000" \
     -e "NODE_ENV=production" \
     --name konga pantsel/konga \

Nếu cài đặt thành công thì konga có thể truy cập từ host của bạn thông qua cổng 1337 ( Ví dụ http://localhost: 1337). Sau khi login vào bạn cần khai báo kong instance với konga như sau :

Tab connection sẽ chứa duy nhất 1 connection kong instance và bạn cần activate nó lên sau để sử dụng.

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.