1. نظرة عامة
gRPC هي مجموعة أدوات وإطار عمل لاستدعاء الإجراء عن بُعد (RPC) لا يعتمد على لغة أو نظام أساسي، وقد تم تطويرها في Google. تتيح لك تحديد خدمة باستخدام "مخازن البروتوكولات المؤقتة"، وهي مجموعة أدوات ولغة تسلسل ثنائي فعّالة بشكل خاص. بعد ذلك، تتيح لك إنشاء نماذج أولية للعملاء والخوادم بلغات مختلفة من تعريف الخدمة.
في هذا الدرس التطبيقي حول الترميز، ستتعلّم كيفية إنشاء خدمة مستندة إلى Java تعرض واجهة برمجة تطبيقات باستخدام إطار عمل gRPC، ثم كتابة برنامج عميل لاستخدام رمز gRPC النموذجي الذي تم إنشاؤه من جهة العميل.
ما ستتعلمه
- لغة Protocol Buffer
- كيفية تنفيذ خدمة gRPC باستخدام Java
- كيفية تنفيذ برنامج gRPC باستخدام Java
كيف ستستخدم هذا البرنامج التعليمي؟
كيف تقيّم تجربتك في إنشاء تطبيقات Node.js؟
كيف تقيّم تجربتك في إنشاء تطبيقات Go؟
2. الإعداد والمتطلبات
إعداد البيئة بالسرعة التي تناسبك
- سجِّل الدخول إلى Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.



تذكَّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس العملي باسم PROJECT_ID.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.
لن تكلفك تجربة هذا الدرس التطبيقي حول الترميز الكثير من المال، إن لم تكلفك شيئًا على الإطلاق. احرص على اتّباع أي تعليمات في قسم "التنظيف" الذي ينصحك بكيفية إيقاف الموارد حتى لا تتحمّل رسومًا تتجاوز هذا البرنامج التعليمي. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.
Google Cloud Shell
على الرغم من إمكانية تشغيل هذا الدرس العملي من جهاز الكمبيوتر، سنستخدم في هذا الدرس Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية.
يتم تحميل هذا الجهاز الافتراضي المستند إلى Debian بجميع أدوات التطوير التي تحتاج إليها. توفّر هذه الخدمة دليلًا رئيسيًا دائمًا بسعة 5 غيغابايت وتعمل في Google Cloud، ما يؤدي إلى تحسين أداء الشبكة والمصادقة بشكل كبير. وهذا يعني أنّ كل ما تحتاجه لهذا الدرس التطبيقي حول الترميز هو متصفّح (نعم، يمكن استخدامه على جهاز Chromebook).
- لتفعيل Cloud Shell من Cloud Console، ما عليك سوى النقر على تفعيل 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
يمكنك اختيار مجموعة متنوعة من المناطق المختلفة. لمزيد من المعلومات، يُرجى الاطّلاع على الأقاليم والمناطق.
3- إنشاء خدمة gRPC
أنشئ مشروع Java جديدًا باستخدام 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 لخدمة Greeting بسيطة تتضمّن طلب Hello ورد Hello.
أولاً، أنشئ دليل proto جديدًا للاحتفاظ بملف proto الجديد:
$ mkdir -p src/main/proto
بعد ذلك، أنشئ ملف 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
بعد الحصول على التعريف، يمكننا إنشاء كل من الرمز البديل من جهة الخادم والرمز البديل من جهة العميل من هذا الملف. عليك إضافة التبعيات والمكوّنات الإضافية لـ 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>
إنشاء رموز التخزين
عند إنشاء التطبيق، سيحوّل المكوّن الإضافي تعريفات proto إلى رمز Java.
$ 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 وطريقتها الرئيسية:
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
4. استخدام الخدمة
أنشأ المولد جميع رموز التخزين المؤقت من جهة العميل. لتسهيل عملية التدريب العملي، سنستخدم مشروع Maven نفسه، ولكن سنضيف ببساطة فئة Client جديدة مع طريقة رئيسية جديدة.
أولاً، انقر على + لفتح جلسة 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"
هذا كل شيء! الأمر بسيط، أليس كذلك؟
5- خدمة البث
يمكنك تجربة الكثير من الأنشطة الأخرى. على سبيل المثال، يمكنك إنشاء خدمة بث بسهولة من خلال إضافة الكلمة الرئيسية 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 إلى 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"
6. تهانينا!
المواضيع التي تناولناها:
- لغة Protocol Buffer
- كيفية تنفيذ خادم gRPC باستخدام Java
- كيفية تنفيذ برنامج gRPC باستخدام Java
الخطوات التالية:
- مزيد من المعلومات حول gRPC Java
- المزيد من أمثلة gRPC Java على GitHub
- مزيد من المعلومات حول البث في gRPC
- مزيد من المعلومات حول تحويل الترميز من gRPC إلى REST
تقديم ملاحظاتك
- يُرجى تخصيص بعض الوقت لإكمال الاستطلاع القصير جدًا.