Pengenalan kepada gRPC

1. Pengenalan

gRPC adalah rangka kerja RPC sumber terbuka berprestasi tinggi yang pada mulanya dikembangkan oleh Google. Ia membantu menghilangkan kod plat boiler dan membantu menghubungkan perkhidmatan polyglot di dan di seluruh pusat data.

2. Gambaran keseluruhan

Kerangka ini didasarkan pada model pelanggan-pelayan panggilan prosedur jarak jauh. Aplikasi klien boleh memanggil kaedah secara langsung pada aplikasi pelayan seolah-olah itu adalah objek tempatan.

Artikel ini akan menggunakan langkah-langkah berikut untuk membuat aplikasi pelayan klien khas menggunakan gRPC:

  1. Tentukan perkhidmatan dalam fail .proto
  2. Hasilkan kod pelayan dan klien menggunakan penyusun penyangga protokol
  3. Buat aplikasi pelayan, melaksanakan antara muka perkhidmatan yang dihasilkan dan melahirkan pelayan gRPC
  4. Buat aplikasi klien, buat panggilan RPC menggunakan rintisan yang dihasilkan

Mari tentukan HelloService ringkas yang mengembalikan ucapan sebagai ganti nama depan dan nama belakang.

3. Pergantungan Maven

Mari tambahkan pergantungan grpc-netty, grpc-protobuf dan grpc-stub:

 io.grpc grpc-netty 1.16.1   io.grpc grpc-protobuf 1.16.1   io.grpc grpc-stub 1.16.1  

4. Mendefinisikan Perkhidmatan

Kami mulakan dengan menentukan perkhidmatan, menentukan kaedah yang dapat dipanggil dari jarak jauh bersama dengan parameter dan jenis pengembaliannya .

Ini dilakukan dalam fail .proto menggunakan buffer protokol. Mereka juga digunakan untuk menjelaskan struktur pesan muatan.

4.1. Konfigurasi Asas

Mari kita buat fail HelloService.proto untuk sampel HelloService kami . Kami mulakan dengan menambahkan beberapa butiran konfigurasi asas:

syntax = "proto3"; option java_multiple_files = true; package org.baeldung.grpc;

Baris pertama memberitahu penyusun sintaks apa yang digunakan dalam fail ini. Secara lalai, penyusun menghasilkan semua kod Java dalam satu fail Java. Baris kedua mengatasi tetapan ini, dan semuanya akan dihasilkan dalam fail individu.

Akhirnya, kami menentukan pakej yang ingin kami gunakan untuk kelas Java yang dihasilkan.

4.2. Mendefinisikan Struktur Mesej

Seterusnya, kami menentukan mesej:

message HelloRequest { string firstName = 1; string lastName = 2; }

Ini menentukan muatan permintaan. Di sini setiap atribut yang masuk ke dalam mesej ditentukan bersama dengan jenisnya.

Nombor unik perlu diberikan untuk setiap atribut, disebut sebagai tag. Tag ini digunakan oleh buffer protokol untuk mewakili atribut dan bukan menggunakan nama atribut.

Jadi, tidak seperti JSON di mana kita akan memberikan nama atribut nama pertama setiap kali, penyangga protokol akan menggunakan nombor 1 untuk mewakili nama pertama . Definisi muatan respons serupa dengan permintaan.

Perhatikan bahawa kami dapat menggunakan tag yang sama di beberapa jenis mesej:

message HelloResponse { string greeting = 1; }

4.3. Menentukan Kontrak Perkhidmatan

Akhirnya, mari kita tentukan kontrak perkhidmatan. Untuk HelloService kami menentukan operasi hello () :

service HelloService { rpc hello(HelloRequest) returns (HelloResponse); }

Operasi hello () menerima permintaan yang tidak henti-henti dan mengembalikan respons yang tidak wajar. gRPC juga menyokong penstriman dengan awalan kata kunci aliran kepada permintaan dan respons.

5. Menjana Kod

Sekarang kita lulus HelloService.proto fail ke protokol penampan pengkompil protoc untuk menjana fail Java. Terdapat pelbagai cara untuk mencetuskan ini.

5.1. Menggunakan Penyusun Penyangga Protokol

Pertama, kita memerlukan Protocol Buffer Compiler. Kita boleh memilih dari banyak binari yang dikompilasi yang terdapat di sini.

Selain itu, kita perlu mendapatkan Java Codegen Plugin gRPC.

Akhirnya, kita boleh menggunakan arahan berikut untuk menghasilkan kod:

protoc --plugin=protoc-gen-grpc-java=$PATH_TO_PLUGIN -I=$SRC_DIR --java_out=$DST_DIR --grpc-java_out=$DST_DIR $SRC_DIR/HelloService.proto

5.2. Menggunakan Maven Plugin

Sebagai pembangun, anda ingin penjanaan kod disatukan dengan sistem binaan anda. gRPC menyediakan plugin protobuf-maven untuk sistem build Maven:

   kr.motd.maven os-maven-plugin 1.6.1     org.xolstice.maven.plugins protobuf-maven-plugin 0.6.1   com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}  grpc-java  io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}      compile compile-custom      

Sambungan / plugin os-maven-plugin menghasilkan pelbagai sifat projek yang bergantung kepada platform seperti $ {os.detected.classifier}

6. Membuat Pelayan

Tidak kira kaedah mana yang anda gunakan untuk penjanaan kod, fail utama berikut akan dihasilkan:

  • HelloRequest.java - mengandungi definisi jenis HelloRequest
  • HelloResponse.java - ini mengandungi definisi jenis HelleResponse
  • HelloServiceImplBase.java - ini mengandungi kelas abstrak HelloServiceImplBase yang menyediakan pelaksanaan semua operasi yang kami tetapkan dalam antara muka perkhidmatan

6.1. Mengatasi Kelas Pangkalan Perkhidmatan

The pelaksanaan lalai kelas abstrak HelloServiceImplBase adalah untuk membuang runtime pengecualian io.grpc.StatusRuntimeException mengatakan bahawa kaedah ini tidak dilaksanakan.

We shall extend this class and override the hello() method mentioned in our service definition:

public class HelloServiceImpl extends HelloServiceImplBase { @Override public void hello( HelloRequest request, StreamObserver responseObserver) { String greeting = new StringBuilder() .append("Hello, ") .append(request.getFirstName()) .append(" ") .append(request.getLastName()) .toString(); HelloResponse response = HelloResponse.newBuilder() .setGreeting(greeting) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } }

If we compare the signature of hello() with the one we wrote in the HellService.proto file, we'll notice that it does not return HelloResponse. Instead, it takes the second argument as StreamObserver, which is a response observer, a call back for the server to call with its response.

This way the client gets an option to make a blocking call or a non-blocking call.

gRPC uses builders for creating objects. We use HelloResponse.newBuilder() and set the greeting text to build a HelloResponse object. We set this object to the responseObserver's onNext() method to send it to the client.

Finally, we need to call onCompleted() to specify that we’ve finished dealing with the RPC, else the connection will be hung, and the client will just wait for more information to come in.

6.2. Running the Grpc Server

Next, we need to start the gRPC server to listen for incoming requests:

public class GrpcServer { public static void main(String[] args) { Server server = ServerBuilder .forPort(8080) .addService(new HelloServiceImpl()).build(); server.start(); server.awaitTermination(); } }

Here, again we use the builder to create a gRPC server on port 8080 and add the HelloServiceImpl service that we defined. start() would start the server. In our example, we will call awaitTermination() to keep the server running in the foreground blocking the prompt.

7. Creating the Client

gRPC provides a channel construct that abstracts out the underlying details like connection, connection pooling, load balancing, etc.

We'll create a channel using ManagedChannelBuilder. Here, we specify the server address and port.

We'll be using plain text without any encryption:

public class GrpcClient { public static void main(String[] args) { ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080) .usePlaintext() .build(); HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel); HelloResponse helloResponse = stub.hello(HelloRequest.newBuilder() .setFirstName("Baeldung") .setLastName("gRPC") .build()); channel.shutdown(); } }

Next, we need to create a stub which we'll use to make the actual remote call to hello(). The stub is the primary way for clients to interacts with the server. When using auto-generated stubs, the stub class will have constructors for wrapping the channel.

Here we're using a blocking/synchronous stub so that the RPC call waits for the server to respond, and will either return a response or raise an exception. There are two other types of stubs provided by gRPC, which facilitate non-blocking/asynchronous calls.

Akhirnya, masa untuk membuat panggilan RPC halo () . Di sini kita lulus HelloRequest . Kita boleh menggunakan penetap yang dijana secara automatik untuk menetapkan firstName , LASTNAME sifat-sifat daripada HelloRequest objek.

Kami mendapat kembali objek HelloResponse yang dikembalikan dari pelayan.

8. Kesimpulannya

Dalam tutorial ini, kami melihat bagaimana kami dapat menggunakan gRPC untuk mempermudah pengembangan komunikasi antara dua perkhidmatan dengan memfokuskan pada menentukan layanan dan membiarkan gRPC menangani semua kode boilerplate.

Seperti biasa, anda akan menemui sumbernya di GitHub.