Java ile gRPC hizmeti oluşturma

1. Genel Bakış

gRPC Google'da geliştirilen, dilden bağımsız, platform açısından bağımsız bir uzak prosedür çağrısı (RPC) çerçevesi ve araç setidir. Özellikle güçlü bir ikili program serileştirme araç seti ve dili olan Protokol Arabelleklerini kullanarak hizmet tanımlamanızı sağlar. Daha sonra çeşitli dillerde hizmet tanımınızdan deyimsel istemci ve sunucu kökleri oluşturmanıza olanak tanır.

Bu codelab'de, gRPC çerçevesini kullanarak API ortaya çıkaran Java tabanlı bir hizmet derlemeyi ve oluşturulan gRPC istemci taraflı saplama kısmını kullanmak için bir istemci yazmayı öğreneceksiniz.

Neler öğreneceksiniz?

  • Protokol Arabellek Dili
  • Java kullanarak gRPC hizmeti uygulama
  • Java kullanarak gRPC istemcisini uygulama

Bu eğiticiden nasıl yararlanacaksınız?

Yalnızca okuma Okuyun ve alıştırmaları tamamlayın

Node.js uygulamaları oluşturma deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Yeterli

Go uygulamaları oluşturma deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Yeterli

2. Kurulum ve Gereksinimler

Kendi hızınızda ortam kurulumu

  1. Cloud Console'da oturum açıp yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap oluşturmanız gerekir.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Tüm Google Cloud projelerinde benzersiz bir ad olan proje kimliğini unutmayın (yukarıdaki ad zaten alınmış ve size uygun olmayacaktır!). Bu kod laboratuvarın ilerleyen bölümlerinde PROJECT_ID olarak adlandırılacaktır.

  1. Sonraki adımda, Google Cloud kaynaklarını kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir.

Bu codelab'i çalıştırmanın maliyeti, yüksek değildir. "Temizleme" bölümündeki talimatları izlediğinizden emin olun. bölümünde, bu eğiticinin dışında faturalandırmayla karşılaşmamanız için kaynakları nasıl kapatacağınız konusunda tavsiyelerde bulunuyoruz. Yeni Google Cloud kullanıcıları, 300 ABD doları değerindeki ücretsiz denemeden yararlanabilir.

Google Cloud Shell

Bu codelab, bilgisayarınızdan çalıştırılabilse de bu codelab'de, Cloud'da çalışan bir komut satırı ortamı olan Google Cloud Shell'i kullanacağız.

Bu Debian tabanlı sanal makine, ihtiyacınız olan tüm geliştirme araçlarıyla yüklüdür. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud'da çalışarak ağ performansını ve kimlik doğrulamasını büyük ölçüde iyileştirir. Yani bu codelab'de ihtiyacınız olan tek şey bir tarayıcıdır (Evet, Chromebook'ta çalışır).

  1. Cloud Shell'i Cloud Console'dan etkinleştirmek için Cloud Shell'i etkinleştir a8460e837e9f5fda.png simgesini tıklamanız yeterlidir (sağlanması ve ortama bağlanması yalnızca birkaç dakika sürer).

b532b2f19ab85dda.png

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

Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin PROJECT_ID olarak ayarlanmış olduğunu göreceksiniz.

gcloud auth list

Komut çıkışı

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

Komut çıkışı

[core]
project = <PROJECT_ID>

Herhangi bir nedenle proje ayarlanmamışsa şu komutu vermeniz yeterlidir:

gcloud config set project <PROJECT_ID>

PROJECT_ID cihazınızı mı arıyorsunuz? Kurulum adımlarında kullandığınız kimliği kontrol edin veya Cloud Console kontrol panelinden arayın:

2485e00c1223af09.png

Cloud Shell bazı ortam değişkenlerini de varsayılan olarak ayarlar. Bu değişkenler, gelecekte komut çalıştırdığınızda işinize yarayabilir.

echo $GOOGLE_CLOUD_PROJECT

Komut çıkışı

<PROJECT_ID>
  1. Son olarak, varsayılan alt bölgeyi ve proje yapılandırmasını ayarlayın.
gcloud config set compute/zone us-central1-f

Çeşitli farklı alt bölgeler seçebilirsiniz. Daha fazla bilgi için Bölgeler ve Bölgeler.

3. gRPC Hizmeti Oluşturma

Maven ile yeni bir Java projesi oluşturun:

$ mvn archetype:generate -DgroupId=com.example.grpc \
 -DartifactId=grpc-hello-server \
 -DarchetypeArtifactId=maven-archetype-quickstart \
 -DinteractiveMode=false
$ cd grpc-hello-server

gRPC Tanım Dosyası Ekleme

gRPC'de hizmet yüklerinin (istek ve yanıt) ve hizmet işlemlerinin IDL (Arayüz Tanımlama Dili) olarak yakalanması gerekir. gRPC, mesaj yüklerini ve işlemlerini tanımlamak için Protobuffer 3 söz dizimini kullanır. Basit bir Karşılama Hizmeti için Hello İsteği ve Hello yanıtı ile birlikte bir proto dosyası oluşturalım.

İlk olarak, yeni proto dosyasını içerecek yeni bir proto dizini oluşturun:

$ mkdir -p src/main/proto

Sonra src/main/proto/GreetingService.proto adlı yeni bir proto dosyası oluşturun.

Dosyayı düzenlemek için vim,nano, veya emacs aracını kullanabilirsiniz:

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 Bağımlılıkları ve Eklentisi Ekleme

Tanımı belirledikten sonra, bu dosyadan hem sunucu tarafı saplama hem de istemci tarafı saplamayı oluşturabiliriz. gRPC bağımlılarını ve eklentilerini eklemeniz gerekir.

İlk olarak gRPC bağımlılıklarını pom.xml öğesine ekleyin:

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>

Ardından eklentiyi ekleyin:

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>

Saplamaları Oluştur

Uygulamayı derlediğinizde, eklenti proto tanımlarını Java koduna dönüştürür.

$ mvn -DskipTests package

Oluşturulan dosyaları görmek için:

$ find target/generated-sources

Hizmeti Uygulama

Öncelikle, greeting işlemini uygulayacak yeni bir GreetingServiceImpl sınıfı oluşturun:

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();
  }
}

Sunucuyu uygulama

Son olarak, bağlantı noktasını dinlemek ve bu hizmet uygulamasını kaydetmek için bir sunucu başlatmanız gerekir. App sınıfını ve ana yöntemini düzenleyin:

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();
    }
}

Son olarak, sunucuyu çalıştırın:

$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.App
...
Server Started

4. Hizmeti Kullanma

Oluşturma aracı, istemci taraflı saplamaların tümünü zaten oluşturdu. Laboratuvarda kolaylık sağlamak için aynı Maven projesini kullanacağız ancak yeni bir ana yöntemle yeni bir Client sınıfı ekleyeceğiz.

Öncelikle + simgesini tıklayarak yeni bir Cloud Shell oturumu açın. Böylece sunucuyu sonlandırmanıza gerek kalmaz:

1ff0fda960b9adfc.png

Yeni oturumda grpc-hello-server dizinine geçin:

$ cd grpc-hello-server

Ardından, yeni Client sınıfını ekleyin:

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();
    }
}

Son olarak, istemciyi çalıştırın:

$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.Client
...
greeting: "Hello there, Ray"

İşte bu kadar. Çok basit, değil mi?

5. Akış Hizmeti

Deneyebileceğiniz çok daha fazla şey var. Örneğin, proto dosyasındaki stream anahtar kelimesini isteğe veya yanıt parametresine (ör.

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);
}

Sunucunuzu tek bir yanıt yerine birden çok yanıt gönderecek şekilde güncelleyin. Bunu, birden fazla responseObserver.onNext(...) çağrısı yaparak yapabilirsiniz:

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();
  }
}

İstemci, engelleme koçanı yerine eşzamansız bir saplama kullanmalıdır. stub türünü GreetingServiceStub olarak güncellediğinizden emin olarak istemci kodunu güncelleyin:

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();
        }
      });
    }
}

Uygulamayı yeniden derleyin:

$ mvn -DskipTests package

Hem sunucuyu hem de istemciyi kendi Cloud Shell oturumunda yeniden başlatın.

Sunucuyu başlatmak için:

$ mvn exec:java -Dexec.mainClass=com.example.grpc.App
...
Server Started

Müşteriyi başlatmak için:

$ mvn exec:java -Dexec.mainClass=com.example.grpc.Client
...
greeting: "Hello there, Ray"
greeting: "Hello there, Ray"
greeting: "Hello there, Ray"

6. Tebrikler!

İşlediğimiz konular:

  • Protokol Arabellek Dili
  • Java kullanarak gRPC sunucusu uygulama
  • Java kullanarak gRPC istemcisini uygulama

Sonraki Adımlar:

Geri bildiriminizi paylaşın

  • Lütfen çok kısa bir süre ayırarak anketimizi doldurun.