Giao tiếp hiệu quả giữa các Microservice

Lựa Chọn Giữa http/1.1 Và gRPC. TL; DR: Use gRPC

Làm thế nào mà việc giao tiếp giữa các microservice lại gây ảnh hưởng đến hiệu suất và khả năng mở rộng của ứng dụng. Giao tiếp giữa các dịch vụ có thể đồng bộ hoặc không. Đối với bài viết này, chúng tôi sẽ tập trung vào sự đồng bộ. Theo ý kiến cá nhân của chúng tôi thì có 2 giao thức phổ biến:

  • HTTP/1.1: giao thức http mặc định
  • gRPC: cuộc gọi thủ tục từ xa với hiệu suất cao (RPC framework). gRPC.io hoạt động dựa vào tài liệu toàn diện của mình.

Hãy thử xem một số code mẫu và chạy thử một số thử nghiệm hiệu suất để xem thử các lựa của chúng tôi

Có thể bạn quan tâm:

  Giải đáp những thắc mắc kĩ thuật quan trọng về Microservices
  Hướng dẫn vượt khó Microservices vô cùng giá trị dành cho bạn!
  gRPC và ứng dụng nó trong Microservices

 

Chế Độ Non-cluster

Cùng bắt đầu với một mô hình nhỏ và cố gắng nhận một cuộc trò chuyện microservice với một bên khác.

Sơ đồ cấu trúc ứng dụng đơn giản

Ứng dụng của chúng tôi bao gồm các thành phần:

  • Load Testing tool: jMeter
  • Service A: Đưa ra yêu cầu cho service B và trả về phản hồi đó.
  • Service B: Trả lời bằng static JSON sau 10ms cho tất cả các API
  • VMs: Cả hai VM đều là máy Amazon EC2 t2.xlarge

HTTP / 1.1

Đây là yêu cầu mặc định mà chúng tôi thực hiện khi sử dụng bất kỳ thư viện HTTP client nào như axios, superagent.

Hãy tạo ServiceB để triển khai API của chúng tôi.

server.route({
  method: 'GET',
  path: '/',
  handler: async (request, h) => {
    const response = await new Promise((resolve) => {
      setTimeout(() => {
        resolve({
          id: 1,
          name: 'Abhinav Dhasmana',
          enjoys_coding: true,

        });
      }, 10);
    });
    return h.response(response);
  },
});

Service B triển khai HTTP / 1.1

Tiếp theo, chúng tôi tạo serviceA gọi serviceB bằng HTTP / 1.1

server.route({
  method: 'GET',
  path: '/',
  handler: async (request, h) => {
    try {
      const response = await Axios({
        url: 'http://localhost:8001/',
        method: 'GET',
      });
      return h.response(response.data);
    } catch (err) {
      throw Boom.clientTimeout(err);
    }
  },
});

Service A triển khai HTTP/1.1

Với hai service đang chạy này chúng tôi có thể kích hoạt jMeter để thử nghiệm hiệu năng. Chúng tôi sẽ sử dụng 50 người dùng với 2000 yêu cầu mỗi người. Chúng ta có thể thấy trong ảnh chụp màn hình bên dưới trung bình của chúng là 37ms.

Kết quả hoạt động của HTTP / 1.1 ở chế độ Non-cluster

gRPC

gRPC sử dụng protocol buffers theo mặc định. Ngoài serviceAserviceB, chúng tôi còn cần thêm một file proto sẽ xác định cuộc gọi từ xa của chúng tôi.

syntax = "proto3";

service SampleDataService {
  rpc GetSampleData (Empty) returns (SampleData) {}
}

message SampleData {
  int32 id = 1;
  string name = 2;
  bool enjoys_coding = 3;
}

message Empty {}

File proto cho tiếp xúc với RPC

Hãy triển khai lại serviceB, lần này hãy sử dụng gRPC

const grpc = require('grpc');

const proto = grpc.load('serviceB.proto');
const server = new grpc.Server();

const GetSampleData = (call, callback) => {
  setTimeout(() => {
    callback(null, {
      id: 1,
      name: 'Abhinav Dhasmana',
      enjoys_coding: true,
    });
  }, 10);
};

server.addService(proto.SampleDataService.service, {
  GetSampleData,
});

const port = process.env.PORT;
console.log('port', port);

server.bind(`0.0.0.0:${port}`, grpc.ServerCredentials.createInsecure());

server.start();
console.log('grpc server is running');

Service B khi triển khai gRPC

Vài điều cần lưu ý:

  • Chúng tôi tạo máy chủ grpcline 4
  • Chúng tôi thêm một service vào máy chủ của mình ở line 16
  • Chúng tôi liên kết portcedentials ở line 23

serviceA được triển khai bằng cách sử dụng gRPC bên dưới

onst protoPath = `${__dirname}/../serviceB/serviceB.proto`;
const proto = grpc.load(protoPath);

const client = new proto.SampleDataService('localhost:8001', grpc.credentials.createInsecure());
const getDataViagRPC = () => new Promise((resolve, reject) => {
  client.GetSampleData({}, (err, response) => {
    if (!response.err) {
      resolve(response);
    } else {
      reject(err);
    }
  });
});

server.route({
  method: 'GET',
  path: '/',
  handler: async (request, h) => {
    const allResults = await getDataViagRPC();
    return h.response(allResults);
  },
});

Service A khi triển khai gRPC

Một số ghi chú:

  • Chúng tôi tạo client grpc tại line 4
  • Chúng tôi tựực hiện một cuộc gọi từ xa tại line 6

Hãy chạy thử nghiệm công cụ jMeter một lần nữa.

Kết quả hoạt động của gRPC ở chế độ Non-cluster

Như chúng ta có thể thấy từ dữ liệu này, gRPC nhanh hơn 27% so với yêu cầu HTTP / 1.1 thông thường.

Cấu Trúc Ứng Dụng Trong Chế Độ Cluster

Cấu trúc ứng dụng

Nếu bạn đang chạy bất cứ thứ gì trong quá trình sản xuất, rất có thể bạn đang chạy nhiều phiên bản của bất kỳ dịch vụ cụ thể nào. Trong trường hợp này, chúng ta đang thực hiện các thay đổi sau:

  • Chạy ba phiên bản dịch vụ của chúng tôi trên các cổng khác nhau
  • Chúng tôi đang sử dụng NGINX tạo sự cân bằng tải.

HTTP/1.1

Không có thay đổi được yêu cầu từ phía dịch vụ. Tất cả chúng ta cần làm đó là cấu hình nginx để cân bằng lưu lượng tải với serviceB. Chúng tôi có thể sửa đổi /etc/nginx/sites-available/default giống như bên dưới

upstream httpservers {
   server ip_address:8001; 
   server ip_address:8002; 
   server ip_address:8003; 
}
server {
   listen 80; 

   location / {
      proxy_pass http://httpservers;
   }
}

nginx với HTTP/1.1

Bây giờ chúng ta có thể bắt đầu với 3 phiên bản dịch vụ của chúng tôi và chạy thử nghiệm hiệu suất của chúng.

Kết quả hoạt động của HTTP / 1.1 ở chế độ Cluster

gRPC

Hỗ trợ cho gRPC gần đây đã được thêm vào  nginx phiên bản 1..13.10. Vì thế chúng ta cần sử dụng bản mới nhất vì sudo apt-get install nginx mặc định sẽ không thể hoạt động.

Chúng tôi không sử dụng node trong chế độ cluster vì gRPC không được hỗ trợ.

Thực hiện các bước dưới đây để có được nginx mới nhất.

sudo apt-get install -y software-properties-common
sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install nginx

Nhận ngay phiên bản nginx mới nhất

Chúng tôi cũng sẽ cần các chứng chỉ ssl. Chúng tôi có thể tạo các chứng chỉ tự ký bằng openSSL

openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
  -keyout localhost-privatekey.pem -out localhost-certificate.pem

Lệnh tạo chứng chỉ tự ký

Tiếp theo, chúng ta cần thay đổi tệp /etc/nginx/sites-available/default  để bắt đầu sử dụng gRPC.

upstream grpcnodes {
    server ip_address:8001;
    server ip_address:8002;
    server ip_address:8003;
}
server {

    listen 1443 http2;
	  ssl_certificate /home/ubuntu/interserviceCommunication/http2/certificates/localhost-certificate.pem;
          ssl_certificate_key /home/ubuntu/interserviceCommunication/http2/certificates/localhost-privatekey.pem;

	  location / {
                grpc_pass grpcnodes;
##		try_files $uri $uri/ =404; // Don't forget to comment this else you will get 404 as a response
	}

Chính là nó. Hãy chạy thử nghiệm hiệu suất một lần nữa

Kết quả hoạt động của gRPC ở chế độ non cluster

Như chúng ta có thể thấy gRPC nhanh hơn 31% so với HTTP / 1.1

Kết Luận

gRPC thì nhanh. Trong các bản thử nghiệm ở trên, chúng ta có thể thấy nó nhanh hơn 31% so với HTTP / 1.1 chỉ bằng cách thay đổi cách mà chúng tôi trao đổi.

Những mã nguồn này có thể tìm thấy trên GitHub

Topdev via ITNEXT

====

Tuy nhiên, đối với những dự án cần một số yếu tố như tốc độ truyền thông cao và độ trễ thấp, truyền dữ liệu kiểm stream, các hãng công nghệ lớn thường có xu hướng chuyển đổi sang một framework RPC mới dựa trên protobufs và HTTP/2 của Google là gRPC API. 

Tại buổi meetup ngày 14/01/2020 với chủ đề “Migrating APIs from REST to gRPC and LOOP Case study” do anh Việt Nguyễn – CTO | LOOP trình bày, hứa hẹn sẽ mang đến những giải pháp cho vấn đề giao tiếp giữa các services từ chính trường hợp của LOOP.

Tham gia ngay buổi meetup để trao đổi chi tiết hơn cùng cộng đồng IT và chuyên gia đến từ LOOP ngay nhé! 

 = = =
**Nhập ngay code EARLYBIRD@1401 để giảm 100.000đ cho các vé đầu tiên
⏰ Thời gian: 18:30 – 21:00 ngày 14/01/2020
📌 Địa điểm: UP Bách Khoa Hà Nội, tầng 3 toà nhà A1-7, 17 Tạ Quang Bửu, HBT.
🎟 Đăng ký ngay tại: https://meetup.vn/e/F3S

===

LIÊN HỆ

Event team: [email protected] | 028 6681 3236
Ms. Thoa | [email protected] | 038 5098 969
=== Sự kiện thuộc chuỗi PRODUCT IN REAL LIFE hằng tuần được tổ chức bởi TopDev – Giải pháp tuyển dụng ngành IT ===

Service B triển khai HTTP / 1.1