ساخت سرویس gRPC با جاوا

1. بررسی اجمالی

gRPC یک چارچوب و مجموعه ابزار فراخوانی روش از راه دور از راه دور (RPC) بی طرف از نظر زبان و پلتفرم خنثی است که در گوگل توسعه یافته است. این به شما امکان می دهد یک سرویس را با استفاده از Protocol Buffers، یک مجموعه ابزار و زبان سریال سازی باینری قدرتمند تعریف کنید. سپس به شما این امکان را می‌دهد که از تعریف سرویس خود به زبان‌های مختلف، کلاینت و سرور اصطلاحی ایجاد کنید.

در این کد لبه، شما یاد خواهید گرفت که چگونه یک سرویس مبتنی بر جاوا بسازید که یک API را با استفاده از چارچوب gRPC در معرض نمایش قرار دهد، و سپس یک کلاینت بنویسید تا از خرد سمت مشتری gRPC تولید شده استفاده کند.

چیزی که یاد خواهید گرفت

  • زبان بافر پروتکل
  • نحوه پیاده سازی سرویس gRPC با استفاده از جاوا
  • نحوه پیاده سازی کلاینت gRPC با استفاده از جاوا

چگونه از این آموزش استفاده خواهید کرد؟

فقط از طریق آن را بخوانید آن را بخوانید و تمرینات را کامل کنید

به تجربه خود از ساخت اپلیکیشن های Node.js چه امتیازی می دهید؟

تازه کار متوسط مسلط

به تجربه خود از ساخت اپلیکیشن های Go چگونه امتیاز می دهید؟

تازه کار متوسط مسلط

2. راه اندازی و الزامات

تنظیم محیط خود به خود

  1. به کنسول Cloud وارد شوید و یک پروژه جدید ایجاد کنید یا از یک موجود استفاده مجدد کنید. اگر قبلاً یک حساب Gmail یا Google Workspace ندارید، باید یک حساب ایجاد کنید .

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

شناسه پروژه را به خاطر بسپارید، یک نام منحصر به فرد در تمام پروژه های Google Cloud (نام بالا قبلاً گرفته شده است و برای شما کار نخواهد کرد، متأسفیم!). بعداً در این آزمایشگاه کد به عنوان PROJECT_ID نامیده خواهد شد.

  1. در مرحله بعد، برای استفاده از منابع Google Cloud، باید صورت‌حساب را در Cloud Console فعال کنید .

اجرا کردن از طریق این کد لبه نباید هزینه زیادی داشته باشد، اگر اصلاً باشد. حتماً دستورالعمل‌های موجود در بخش «تمیز کردن» را دنبال کنید که به شما توصیه می‌کند چگونه منابع را خاموش کنید تا بیش از این آموزش متحمل صورت‌حساب نشوید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان 300 دلاری هستند.

Google Cloud Shell

در حالی که این کد لبه را می توان از رایانه شما کار کرد، در این کد لبه از Google Cloud Shell استفاده خواهیم کرد، یک محیط خط فرمان که در Cloud اجرا می شود.

این ماشین مجازی مبتنی بر دبیان با تمام ابزارهای توسعه که شما نیاز دارید بارگذاری شده است. این دایرکتوری اصلی 5 گیگابایتی دائمی را ارائه می دهد و در Google Cloud اجرا می شود و عملکرد شبکه و احراز هویت را بسیار افزایش می دهد. این بدان معنی است که تمام چیزی که برای این کد لبه نیاز دارید یک مرورگر است (بله، روی کروم بوک کار می کند).

  1. برای فعال کردن Cloud Shell از Cloud Console، کافی است روی Activate Cloud Shell کلیک کنید. a8460e837e9f5fda.png (تهیه و اتصال به محیط فقط چند لحظه طول می کشد).

b532b2f19ab85dda.png

Screen Shot 2017-06-14 at 10.13.43 PM.png

پس از اتصال به 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 جستجو کنید:

2485e00c1223af09.png

Cloud Shell همچنین برخی از متغیرهای محیطی را به صورت پیش‌فرض تنظیم می‌کند که ممکن است هنگام اجرای دستورات آینده مفید باشند.

echo $GOOGLE_CLOUD_PROJECT

خروجی فرمان

<PROJECT_ID>
  1. در نهایت، منطقه پیش فرض و پیکربندی پروژه را تنظیم کنید.
gcloud config set compute/zone us-central1-f

شما می توانید مناطق مختلفی را انتخاب کنید. برای اطلاعات بیشتر، به مناطق و مناطق مراجعه کنید.

3. یک سرویس 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 برای تعریف بارهای پیام و عملیات استفاده می کند. بیایید یک فایل پروتو برای یک سرویس خوش آمدگویی ساده با درخواست سلام و پاسخ سلام ایجاد کنیم.

ابتدا یک دایرکتوری پروتو جدید برای نگهداری فایل پروتوی جدید ایجاد کنید:

$ 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 را اضافه کنید

وقتی تعریف را داشتید، می‌توانیم هم خرد سمت سرور و هم خرد سمت کلاینت را از این فایل تولید کنیم. شما باید وابستگی ها و افزونه های 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>

Stubs را تولید کنید

هنگامی که برنامه را می سازید، افزونه تعاریف اولیه را به کد جاوا تبدیل می کند.

$ 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 جدید باز شود تا نیازی به پایان دادن به سرور نباشد:

1ff0fda960b9adfc.png

در جلسه جدید، به دایرکتوری 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 در فایل پروتو به پارامتر درخواست یا پاسخ، به راحتی یک سرویس استریم بسازید.

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. تبریک می گویم!

آنچه ما پوشش داده ایم:

  • زبان بافر پروتکل
  • نحوه پیاده سازی سرور gRPC با استفاده از جاوا
  • نحوه پیاده سازی کلاینت gRPC با استفاده از جاوا

مراحل بعدی:

نظرات خود را با ما در میان بگذارید

  • لطفا یک لحظه برای تکمیل نظرسنجی بسیار کوتاه ما وقت بگذارید