1. Tổng quan
gRPC là một khung và bộ công cụ lệnh gọi quy trình từ xa (RPC) không phân biệt ngôn ngữ và nền tảng do Google phát triển. Nó cho phép bạn xác định một dịch vụ bằng cách sử dụng vùng đệm giao thức, một bộ công cụ và ngôn ngữ chuyển đổi tuần tự nhị phân đặc biệt mạnh mẽ. Sau đó, bạn có thể tạo các phần giữ chỗ máy chủ và ứng dụng theo thành ngữ từ định nghĩa dịch vụ của mình bằng nhiều ngôn ngữ.
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách tạo một dịch vụ dựa trên Java để hiển thị một API bằng khung gRPC, sau đó viết một ứng dụng để sử dụng mã giả lập phía máy khách gRPC đã tạo.
Kiến thức bạn sẽ học được
- Ngôn ngữ vùng đệm giao thức
- Cách triển khai dịch vụ gRPC bằng Java
- Cách triển khai ứng dụng gRPC bằng Java
Bạn sẽ sử dụng hướng dẫn này như thế nào?
Bạn đánh giá thế nào về trải nghiệm của mình khi tạo ứng dụng Node.js?
Bạn đánh giá thế nào về trải nghiệm của mình khi tạo ứng dụng Go?
2. Thiết lập và yêu cầu
Thiết lập môi trường theo tốc độ của riêng bạn
- Đăng nhập vào Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.



Hãy nhớ mã dự án, một tên duy nhất trên tất cả các dự án trên Google Cloud (tên ở trên đã được sử dụng và sẽ không hoạt động đối với bạn, xin lỗi!). Sau này trong lớp học lập trình này, chúng ta sẽ gọi nó là PROJECT_ID.
- Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên của Google Cloud.
Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Hãy nhớ làm theo mọi hướng dẫn trong phần "Dọn dẹp" để biết cách tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.
Google Cloud Shell
Mặc dù có thể chạy lớp học lập trình này trên máy tính, nhưng trong lớp học lập trình này, chúng ta sẽ sử dụng Google Cloud Shell, một môi trường dòng lệnh chạy trên đám mây.
Máy ảo dựa trên Debian này được trang bị tất cả các công cụ phát triển mà bạn cần. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Điều này có nghĩa là bạn chỉ cần một trình duyệt (có, trình duyệt này hoạt động trên Chromebook) cho lớp học lập trình này.
- Để kích hoạt Cloud Shell từ Bảng điều khiển Cloud, bạn chỉ cần nhấp vào Kích hoạt Cloud Shell
(mất vài phút để cung cấp và kết nối với môi trường).


Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án đã được đặt thành PROJECT_ID.
gcloud auth list
Đầu ra của lệnh
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Đầu ra của lệnh
[core] project = <PROJECT_ID>
Nếu vì lý do nào đó mà dự án chưa được thiết lập, bạn chỉ cần đưa ra lệnh sau:
gcloud config set project <PROJECT_ID>
Bạn đang tìm PROJECT_ID? Kiểm tra mã nhận dạng bạn đã dùng trong các bước thiết lập hoặc tìm mã nhận dạng đó trong trang tổng quan của Cloud Console:

Cloud Shell cũng đặt một số biến môi trường theo mặc định, có thể hữu ích khi bạn chạy các lệnh trong tương lai.
echo $GOOGLE_CLOUD_PROJECT
Đầu ra của lệnh
<PROJECT_ID>
- Cuối cùng, hãy đặt cấu hình dự án và vùng mặc định.
gcloud config set compute/zone us-central1-f
Bạn có thể chọn nhiều múi giờ khác nhau. Để biết thêm thông tin, hãy xem phần Khu vực và vùng.
3. Tạo một dịch vụ gRPC
Tạo một dự án Java mới bằng Maven:
$ mvn archetype:generate -DgroupId=com.example.grpc \ -DartifactId=grpc-hello-server \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false $ cd grpc-hello-server
Thêm tệp định nghĩa gRPC
Trong gRPC, tải trọng dịch vụ (yêu cầu và phản hồi) và các hoạt động của dịch vụ cần được ghi lại trong IDL (Ngôn ngữ định nghĩa giao diện). gRPC sử dụng cú pháp Protobuffer 3 để xác định tải trọng và các thao tác của thông báo. Hãy tạo một tệp proto cho Dịch vụ lời chào đơn giản với Yêu cầu lời chào và Phản hồi lời chào.
Trước tiên, hãy tạo một thư mục proto mới để lưu trữ tệp proto mới:
$ mkdir -p src/main/proto
Sau đó, hãy tạo một tệp proto mới src/main/proto/GreetingService.proto.
Bạn có thể dùng vim,nano, hoặc emacs để chỉnh sửa tệp:
src/main/proto/GreetingService.proto
syntax = "proto3";
package com.example.grpc;
// Request payload
message HelloRequest {
// Each message attribute is strongly typed.
// You also must assign a "tag" number.
// Each tag number is unique within the message.
string name = 1;
// This defines a strongly typed list of String
repeated string hobbies = 2;
// There are many more basics types, like Enum, Map
// See https://developers.google.com/protocol-buffers/docs/proto3
// for more information.
}
message HelloResponse {
string greeting = 1;
}
// Defining a Service, a Service can have multiple RPC operations
service GreetingService {
// Define a RPC operation
rpc greeting(HelloRequest) returns (HelloResponse);
}
Thêm phần phụ thuộc và trình bổ trợ gRPC
Sau khi có định nghĩa, chúng ta có thể tạo cả mã giả lập phía máy chủ và mã giả lập phía máy khách từ tệp này. Bạn cần thêm các phần phụ thuộc và trình bổ trợ gRPC.
Trước tiên, hãy thêm các phần phụ thuộc gRPC vào pom.xml:
pom.xml
<project>
...
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
...
</dependencies>
...
</project>
Sau đó, hãy thêm trình bổ trợ:
pom.xml
<project>
...
<dependencies>
...
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.9.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.24.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Tạo các đoạn mã
Khi bạn tạo ứng dụng, trình bổ trợ sẽ chuyển đổi các định nghĩa proto thành mã Java.
$ mvn -DskipTests package
Cách xem các tệp được tạo:
$ find target/generated-sources
Triển khai Dịch vụ
Trước tiên, hãy tạo một lớp GreetingServiceImpl mới sẽ triển khai thao tác greeting:
src/main/java/com/example/grpc/GreetingServiceImpl.java
package com.example.grpc;
import io.grpc.stub.StreamObserver;
public class GreetingServiceImpl extends GreetingServiceGrpc.GreetingServiceImplBase {
@Override
public void greeting(GreetingServiceOuterClass.HelloRequest request,
StreamObserver<GreetingServiceOuterClass.HelloResponse> responseObserver) {
// HelloRequest has toString auto-generated.
System.out.println(request);
// You must use a builder to construct a new Protobuffer object
GreetingServiceOuterClass.HelloResponse response = GreetingServiceOuterClass.HelloResponse.newBuilder()
.setGreeting("Hello there, " + request.getName())
.build();
// Use responseObserver to send a single response back
responseObserver.onNext(response);
// When you are done, you must call onCompleted.
responseObserver.onCompleted();
}
}
Triển khai Máy chủ
Cuối cùng, bạn sẽ cần khởi động một máy chủ để theo dõi một cổng và đăng ký việc triển khai dịch vụ này. Chỉnh sửa lớp App và phương thức chính của lớp đó:
src/main/java/com/example/grpc/App.java
package com.example.grpc;
import io.grpc.*;
public class App
{
public static void main( String[] args ) throws Exception
{
// Create a new server to listen on port 8080
Server server = ServerBuilder.forPort(8080)
.addService(new GreetingServiceImpl())
.build();
// Start the server
server.start();
// Server threads are running in the background.
System.out.println("Server started");
// Don't exit the main thread. Wait until server is terminated.
server.awaitTermination();
}
}
Cuối cùng, hãy chạy máy chủ:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
4. Sử dụng Dịch vụ
Trình tạo đã tạo tất cả các phần giữ chỗ phía máy khách. Để đơn giản hoá phòng thí nghiệm, chúng ta sẽ sử dụng cùng một dự án Maven, nhưng chỉ cần thêm một lớp Client mới có phương thức chính mới.
Trước tiên, hãy nhấp vào + để mở một phiên Cloud Shell mới để bạn không cần phải chấm dứt máy chủ:

Trong phiên mới, hãy chuyển sang thư mục grpc-hello-server:
$ cd grpc-hello-server
Sau đó, hãy thêm lớp Client mới:
src/main/java/com/example/grpc/Client.java
package com.example.grpc;
import io.grpc.*;
public class Client
{
public static void main( String[] args ) throws Exception
{
// Channel is the abstraction to connect to a service endpoint
// Let's use plaintext communication because we don't have certs
final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:8080")
.usePlaintext(true)
.build();
// It is up to the client to determine whether to block the call
// Here we create a blocking stub, but an async stub,
// or an async stub with Future are always possible.
GreetingServiceGrpc.GreetingServiceBlockingStub stub = GreetingServiceGrpc.newBlockingStub(channel);
GreetingServiceOuterClass.HelloRequest request =
GreetingServiceOuterClass.HelloRequest.newBuilder()
.setName("Ray")
.build();
// Finally, make the call using the stub
GreetingServiceOuterClass.HelloResponse response =
stub.greeting(request);
System.out.println(response);
// A Channel should be shutdown before stopping the process.
channel.shutdownNow();
}
}
Cuối cùng, hãy chạy ứng dụng:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray"
Vậy là xong! Khá đơn giản phải không?
5. Dịch vụ phát trực tuyến
Bạn có thể thử nhiều cách khác. Ví dụ: bạn có thể dễ dàng tạo một dịch vụ phát trực tuyến chỉ bằng cách thêm từ khoá stream vào tệp proto cho tham số yêu cầu hoặc tham số phản hồi, ví dụ:
src/main/proto/GreetingService.proto
syntax = "proto3";
package com.example.grpc;
...
// Defining a Service, a Service can have multiple RPC operations
service GreetingService {
// MODIFY HERE: Update the return to streaming return.
rpc greeting(HelloRequest) returns (stream HelloResponse);
}
Cập nhật máy chủ để gửi nhiều phản hồi thay vì chỉ một. Bạn có thể thực hiện việc này bằng cách thực hiện nhiều lệnh gọi responseObserver.onNext(...):
src/main/java/com/example/grpc/GreetingServiceImpl.java
package com.example.grpc;
import io.grpc.stub.StreamObserver;
public class GreetingServiceImpl extends GreetingServiceGrpc.GreetingServiceImplBase {
@Override
public void greeting(GreetingServiceOuterClass.HelloRequest request,
StreamObserver<GreetingServiceOuterClass.HelloResponse> responseObserver) {
...
// Feel free to construct different responses if you'd like.
responseObserver.onNext(response);
responseObserver.onNext(response);
responseObserver.onNext(response);
// When you are done, you must call onCompleted.
responseObserver.onCompleted();
}
}
Ứng dụng phải sử dụng mã giả lập không đồng bộ thay vì mã giả lập chặn. Cập nhật mã ứng dụng, nhớ cập nhật loại stub thành GreetingServiceStub:
src/main/java/com/example/grpc/Client.java
package com.example.grpc;
import io.grpc.*;
// New import
import io.grpc.stub.*;
public class Client
{
public static void main( String[] args ) throws Exception
{
final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:8080")
.usePlaintext(true)
.build();
// Replace the previous synchronous code with asynchronous code.
// This time use an async stub:
GreetingServiceGrpc.GreetingServiceStub stub = GreetingServiceGrpc.newStub(channel);
// Construct a request
GreetingServiceOuterClass.HelloRequest request =
GreetingServiceOuterClass.HelloRequest.newBuilder()
.setName("Ray")
.build();
// Make an Asynchronous call. Listen to responses w/ StreamObserver
stub.greeting(request, new StreamObserver<GreetingServiceOuterClass.HelloResponse>() {
public void onNext(GreetingServiceOuterClass.HelloResponse response) {
System.out.println(response);
}
public void onError(Throwable t) {
}
public void onCompleted() {
// Typically you'll shutdown the channel somewhere else.
// But for the purpose of the lab, we are only making a single
// request. We'll shutdown as soon as this request is done.
channel.shutdownNow();
}
});
}
}
Tạo lại ứng dụng:
$ mvn -DskipTests package
Khởi động lại cả máy chủ và máy khách trong phiên Cloud Shell riêng.
Cách khởi động máy chủ:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
Cách khởi động ứng dụng:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray" greeting: "Hello there, Ray" greeting: "Hello there, Ray"
6. Xin chúc mừng!
Nội dung đã đề cập:
- Ngôn ngữ vùng đệm giao thức
- Cách triển khai máy chủ gRPC bằng Java
- Cách triển khai ứng dụng gRPC bằng Java
Các bước tiếp theo:
- Tìm hiểu thêm về gRPC Java
- Xem thêm các ví dụ về gRPC Java trên GitHub
- Tìm hiểu về Truyền trực tuyến trong gRPC
- Tìm hiểu thêm về gRPC sang REST Transcoding
Gửi ý kiến phản hồi cho chúng tôi
- Vui lòng dành chút thời gian để hoàn thành bản khảo sát rất ngắn của chúng tôi