۱. مرور کلی
gRPC یک چارچوب و مجموعه ابزار فراخوانی رویه از راه دور (RPC) است که در گوگل توسعه داده شده است. این چارچوب به شما امکان میدهد با استفاده از Protocol Buffers، یک مجموعه ابزار و زبان سریالسازی دودویی بسیار قدرتمند، یک سرویس تعریف کنید. سپس به شما امکان میدهد stubهای اصطلاحی کلاینت و سرور را از تعریف سرویس خود به زبانهای مختلف تولید کنید.
در این آزمایشگاه کد، یاد خواهید گرفت که چگونه یک سرویس مبتنی بر جاوا بسازید که با استفاده از چارچوب gRPC یک API را در معرض نمایش قرار میدهد، و سپس یک کلاینت بنویسید که از stub تولید شده سمت کلاینت gRPC استفاده کند.
آنچه یاد خواهید گرفت
- زبان بافر پروتکل
- نحوه پیاده سازی سرویس gRPC با استفاده از جاوا
- نحوه پیادهسازی کلاینت gRPC با استفاده از جاوا
چگونه از این آموزش استفاده خواهید کرد؟
تجربه خود را در ساخت برنامههای Node.js چگونه ارزیابی میکنید؟
تجربه خود را در ساخت برنامههای Go چگونه ارزیابی میکنید؟
۲. تنظیمات و الزامات
تنظیم محیط خودتنظیم
- وارد Cloud Console شوید و یک پروژه جدید ایجاد کنید یا از یک پروژه موجود دوباره استفاده کنید. اگر از قبل حساب Gmail یا Google Workspace ندارید، باید یکی ایجاد کنید .



شناسه پروژه را به خاطر بسپارید، یک نام منحصر به فرد در تمام پروژههای Google Cloud (نام بالا قبلاً گرفته شده و برای شما کار نخواهد کرد، متاسفیم!). بعداً در این آزمایشگاه کد به آن PROJECT_ID گفته خواهد شد.
- در مرحله بعد، برای استفاده از منابع گوگل کلود، باید پرداخت را در Cloud Console فعال کنید .
اجرای این آزمایشگاه کد، اگر اصلاً هزینهای نداشته باشد، نباید هزینه زیادی داشته باشد. حتماً دستورالعملهای بخش «پاکسازی» را که به شما نحوه خاموش کردن منابع را آموزش میدهد، دنبال کنید تا پس از این آموزش، متحمل هزینه نشوید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان ۳۰۰ دلاری هستند.
پوسته ابری گوگل
اگرچه این آزمایشگاه کد میتواند از طریق رایانه شما اجرا شود، اما در این آزمایشگاه کد ما از Google Cloud Shell ، یک محیط خط فرمان که در فضای ابری اجرا میشود، استفاده خواهیم کرد.
این ماشین مجازی مبتنی بر دبیان، تمام ابزارهای توسعه مورد نیاز شما را در خود جای داده است. این ماشین مجازی یک دایرکتوری خانگی ۵ گیگابایتی دائمی ارائه میدهد و در فضای ابری گوگل اجرا میشود که عملکرد شبکه و احراز هویت را تا حد زیادی بهبود میبخشد. این بدان معناست که تنها چیزی که برای این آزمایشگاه کد نیاز دارید یک مرورگر است (بله، روی کرومبوک هم کار میکند).
- برای فعال کردن Cloud Shell از کنسول Cloud، کافیست روی Activate Cloud Shell کلیک کنید.
(فقط چند لحظه طول میکشد تا آماده شود و به محیط متصل شود).


پس از اتصال به Cloud Shell، باید ببینید که از قبل احراز هویت شدهاید و پروژه از قبل روی PROJECT_ID شما تنظیم شده است.
gcloud auth list
خروجی دستور
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
خروجی دستور
[core] project = <PROJECT_ID>
اگر به هر دلیلی پروژه تنظیم نشده باشد، کافیست دستور زیر را اجرا کنید:
gcloud config set project <PROJECT_ID>
به دنبال PROJECT_ID خود هستید؟ بررسی کنید که در مراحل راهاندازی از چه شناسهای استفاده کردهاید یا آن را در داشبورد Cloud Console جستجو کنید:

Cloud Shell همچنین برخی از متغیرهای محیطی را به طور پیشفرض تنظیم میکند که ممکن است هنگام اجرای دستورات بعدی مفید باشند.
echo $GOOGLE_CLOUD_PROJECT
خروجی دستور
<PROJECT_ID>
- در نهایت، منطقه پیشفرض و پیکربندی پروژه را تنظیم کنید.
gcloud config set compute/zone us-central1-f
شما میتوانید مناطق مختلفی را انتخاب کنید. برای اطلاعات بیشتر، به بخش مناطق و نواحی مراجعه کنید.
۳. ایجاد یک سرویس gRPC
یک پروژه جاوا جدید با Maven ایجاد کنید:
$ mvn archetype:generate -DgroupId=com.example.grpc \ -DartifactId=grpc-hello-server \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false $ cd grpc-hello-server
اضافه کردن فایل تعریف gRPC
در gRPC، بارهای سرویس (درخواست و پاسخ) و عملیات سرویس باید در یک IDL (زبان تعریف رابط) ثبت شوند. gRPC از سینتکس Protobuffer 3 برای تعریف بارهای پیام و عملیات استفاده میکند. بیایید یک فایل proto برای یک سرویس خوشامدگویی ساده با یک درخواست سلام و پاسخ سلام ایجاد کنیم.
ابتدا، یک دایرکتوری جدید proto برای نگهداری فایل جدید proto ایجاد کنید:
$ mkdir -p src/main/proto
سپس، یک فایل پروتو جدید src/main/proto/GreetingService.proto ایجاد کنید.
برای ویرایش فایل میتوانید vim,nano, یا emacs استفاده کنید:
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);
}
افزودن وابستگیها و افزونههای gRPC
وقتی تعریف را انجام دادید، میتوانیم هم stub سمت سرور و هم stub سمت کلاینت را از این فایل تولید کنیم. باید وابستگیها و افزونههای gRPC را اضافه کنید.
ابتدا، وابستگیهای gRPC را به 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>
سپس افزونه را اضافه کنید:
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>
تولید Stubها
وقتی برنامه را میسازید، افزونه تعاریف proto را به کد جاوا تبدیل میکند.
$ mvn -DskipTests package
برای مشاهده فایلهای تولید شده:
$ find target/generated-sources
پیادهسازی سرویس
ابتدا، یک کلاس GreetingServiceImpl جدید ایجاد کنید که عملیات 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();
}
}
پیادهسازی سرور
در نهایت، باید یک سرور راهاندازی کنید تا به یک پورت گوش دهد و این پیادهسازی سرویس را ثبت کند. کلاس App و متد main آن را ویرایش کنید:
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();
}
}
در نهایت، سرور را اجرا کنید:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
۴. استفاده از سرویس
مولد از قبل تمام stub های سمت کلاینت را تولید کرده است. برای سادگی کار، ما از همان پروژه Maven استفاده خواهیم کرد، اما به سادگی یک کلاس Client جدید با یک متد main جدید اضافه خواهیم کرد.
ابتدا، روی + کلیک کنید تا یک جلسه جدید Cloud Shell باز شود تا نیازی به خاتمه دادن به سرور نباشد:

در جلسه جدید، به دایرکتوری grpc-hello-server بروید:
$ cd grpc-hello-server
سپس، کلاس Client جدید را اضافه کنید:
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();
}
}
در نهایت، کلاینت را اجرا کنید:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray"
همین! خیلی سادهست، نه؟
۵. سرویس استریم
چیزهای خیلی بیشتری هست که میتوانید امتحان کنید. برای مثال، میتوانید به راحتی و با اضافه کردن کلمه کلیدی stream در فایل proto به پارامتر درخواست یا پاسخ، یک سرویس استریمینگ بسازید، مثلاً
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);
}
سرور خود را طوری بهروزرسانی کنید که به جای فقط یک پاسخ، چندین پاسخ ارسال کند. میتوانید این کار را با فراخوانیهای متعدد 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();
}
}
کلاینت باید به جای stub مسدودکننده از stub ناهمزمان استفاده کند. کد کلاینت را بهروزرسانی کنید و مطمئن شوید که نوع stub را به 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();
}
});
}
}
بازسازی برنامه:
$ mvn -DskipTests package
هر دو سرور و کلاینت را در جلسه Cloud Shell خود مجدداً راهاندازی کنید.
برای شروع سرور:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
برای شروع کلاینت:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray" greeting: "Hello there, Ray" greeting: "Hello there, Ray"
۶. تبریک میگویم!
آنچه ما پوشش دادهایم:
- زبان بافر پروتکل
- نحوه پیاده سازی سرور gRPC با استفاده از جاوا
- نحوه پیادهسازی کلاینت gRPC با استفاده از جاوا
مراحل بعدی:
- درباره gRPC جاوا بیشتر بدانید
- نمونههای بیشتر gRPC جاوا را در GitHub ببینید
- آشنایی با استریمینگ در gRPC
- درباره تبدیل کد gRPC به REST بیشتر بدانید
نظرات خود را با ما در میان بگذارید
- لطفا کمی وقت بگذارید و نظرسنجی بسیار کوتاه ما را تکمیل کنید.