🌐Khái niệm về gRPC:
gRPC là viết tắt của “Google Remote Procedure Call” (gọi tắt “gRPC”). Đây là một công nghệ cho phép các ứng dụng chạy trên các máy tính khác nhau truyền thông qua mạng internet để giao tiếp với nhau.

🌍 Cơ chế hoạt động của gRPC:
gRPC dựa trên cơ chế gọi thủ tục từ xa (Remote Procedure Call - RPC). Điều này có nghĩa là, một ứng dụng có thể gọi một hàm hoặc phương thức trên một ứng dụng khác. Điều này giống như việc bạn gọi điện để yêu cầu một dịch vụ từ một nhà hàng.

📞 Để thực hiện gọi RPC, gRPC sử dụng một ngôn ngữ chỉ định gọi là Protocol Buffers, hay viết tắt là “protobuf”. Protocol Buffers giúp định nghĩa dữ liệu và các thông điệp mà ứng dụng gửi nhận khi gọi RPC. Hình ảnh dưới đây mô tả quá trình này:

📷 [Hình ảnh mô tả quá trình gRPC với Protocol Buffers]

🔥 Ưu điểm của gRPC:
gRPC mang lại nhiều lợi ích cho việc phát triển phần mềm và tạo ra các ứng dụng hiệu quả. Dưới đây là một số ưu điểm chính của gRPC:

1️⃣ Hiệu suất cao: gRPC sử dụng mô hình không đồng bộ (asynchronous), cho phép gọi nhiều hàm cùng một lúc và xử lý nhiều gọi dịch vụ đồng thời. Điều này giúp tăng tốc độ và hiệu suất của ứng dụng.

2️⃣ Đa ngôn ngữ: gRPC hỗ trợ nhiều ngôn ngữ lập trình, bao gồm C++, Java, Python, Go và nhiều ngôn ngữ khác. Điều này cho phép lập trình viên lựa chọn ngôn ngữ mà họ đã quen thuộc và sử dụng linh hoạt.

3️⃣ Tích hợp dễ dàng: gRPC tích hợp tốt với các công nghệ khác như HTTP/2 - một phiên bản cải tiến của giao thức HTTP. Điều này giúp tăng tốc độ truyền tải và bảo mật dữ liệu.

👎 Nhược điểm của gRPC:
Mặc dù gRPC mang lại nhiều lợi ích, nhưng cũng có một số hạn chế:

1️⃣ Phức tạp hơn: So với các phương pháp giao tiếp truyền thống như RESTful API, gRPC yêu cầu kiến thức và hiểu biết sâu hơn về RPC và Protocol Buffers. Điều này có thể khiến việc học và triển khai gRPC tốn nhiều thời gian và công sức hơn.

2️⃣ Hạn chế hỗ trợ trên một số nền tảng: Hiện tại, gRPC không hoàn toàn hỗ trợ tất cả các nền tảng, vì vậy bạn cần đảm bảo rằng nền tảng mà bạn sử dụng có sẵn hỗ trợ cho gRPC.

Ví dụ demo

1. Tạo 1 file (.proto)

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.j4u.proto";
option java_outer_classname = "UsersProto";

service UserService {
    rpc createUser(CreateUserRequestMessage) returns (CreateUserResponseMessage);
}

message CreateUserRequestMessage {
    string name = 1;
}

message CreateUserResponseMessage {
    int32 id = 1;
    string name = 2;
}

2. Chạy lệnh mvn clean package để nó gen ra các file .java

3. Thêm thư viện trong pom.xml

io.grpc grpc-stub ${grpc.version} io.grpc grpc-protobuf ${grpc.version} jakarta.annotation jakarta.annotation-api 1.3.5 true

Service 1: Mình tạo 1 service rest api để client gọi đến

@RestController
public class TestController {
    @Autowired
    private UserServiceImpl userService;

    @GetMapping("/test")
    public ResponseEntity<?> testGrpc(){
        userService.testGrpc();
        return null;
    }
}
@Service
public class UserServiceImpl {
    public void testGrpc(){
        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9090).usePlaintext().build();
        UserServiceGrpc.UserServiceBlockingStub  blockingStub = UserServiceGrpc.newBlockingStub(channel);

        CreateUserRequestMessage request = CreateUserRequestMessage.newBuilder().setName("World").build();
        CreateUserResponseMessage response = blockingStub.createUser(request);

        System.out.println("Response from server: " + response.getName());

        channel.shutdown();
    }
}

Service 2: Mình tạo 1 service khác để cho chúng giao tiếp với nhau

@GrpcService
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
    @Override
    public void createUser(CreateUserRequestMessage request, StreamObserver<CreateUserResponseMessage> responseObserver) {

        String requestFromService1 = request.getName();
        System.out.println("requestFromService1: "+requestFromService1);
        CreateUserResponseMessage response = CreateUserResponseMessage.newBuilder().setName("ĐẠT").build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}