Introduktion til gRPC

1. Introduktion

gRPC er en open source RPC-ramme med høj ydeevne, der oprindeligt blev udviklet af Google. Det hjælper med at eliminere kedelpladekode og hjælper med at forbinde polyglot-tjenester i og på tværs af datacentre.

2. Oversigt

Rammen er baseret på en klientservermodel af fjernprocedurkald. En klientapplikation kan direkte kalde metoder til en serverapplikation som om det var et lokalt objekt.

Denne artikel bruger følgende trin til at oprette en typisk klientserverapplikation ved hjælp af gRPC:

  1. Definer en tjeneste i en .proto fil
  2. Generer server- og klientkode ved hjælp af protokolbuffer-kompilatoren
  3. Opret serverapplikationen, implementer de genererede servicegrænseflader og gyt gRPC-serveren
  4. Opret klientapplikationen, lav RPC-opkald ved hjælp af genererede stubber

Lad os definere en simpel Hej service som returnerer hilsner til gengæld for for- og efternavnet.

3. Maven-afhængigheder

Lad os tilføje afhængigheder af grpc-netty, grpc-protobuf og grpc-stub:

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

4. Definition af tjenesten

Vi starter med at definere en tjeneste, angive metoder, der kan kaldes eksternt sammen med deres parametre og returtyper.

Dette gøres i .proto fil ved hjælp af protokolbufferne. De bruges også til at beskrive strukturen af ​​nyttelastmeddelelserne.

4.1. Grundlæggende konfigurationer

Lad os oprette en HelloService.proto fil til vores prøve Hej service. Vi starter med at tilføje få grundlæggende konfigurationsoplysninger:

syntaks = "proto3"; mulighed java_multiple_files = true; pakke org.baeldung.grpc;

Den første linje fortæller kompilatoren, hvilken syntaks der bruges i denne fil. Som standard genererer compileren al Java-koden i en enkelt Java-fil. Den anden linje tilsidesætter denne indstilling, og alt genereres i individuelle filer.

Endelig specificerer vi den pakke, vi vil bruge til vores genererede Java-klasser.

4.2. Definition af meddelelsesstruktur

Dernæst definerer vi meddelelsen:

besked HelloRequest {string firstName = 1; streng efternavn = 2; }

Dette definerer anmodningen nyttelast. Her defineres hver attribut, der går ind i meddelelsen sammen med dens type.

Der skal tildeles et unikt nummer til hver attribut, kaldet som tag. Dette tag bruges af protokolbufferen til at repræsentere attributten i stedet for at bruge attributnavnet.

Så i modsætning til JSON, hvor vi ville videregive attributnavn fornavn hver eneste gang ville protokolbuffer bruge tallet 1 til at repræsentere fornavn. Definition af svar på nyttelast svarer til anmodningen.

Bemærk, at vi kan bruge det samme tag på tværs af flere meddelelsestyper:

besked HelloResponse {string greeting = 1; }

4.3. Definition af servicekontrakten

Lad os endelig definere servicekontrakten. For vores Hej service vi definerer en Hej() operation:

tjenesten HelloService {rpc hej (HelloRequest) returnerer (HelloResponse); }

Det Hej() operation accepterer en unary anmodning og returnerer et unary svar. gRPC understøtter også streaming ved at prefixere strøm nøgleord til anmodningen og svaret.

5. Generering af koden

Nu passerer vi HelloService.proto fil til protokolbuffer-kompilatoren protoc for at generere Java-filer. Der er flere måder at udløse dette på.

5.1. Brug af Protocol Buffer Compiler

Først har vi brug for Protocol Buffer Compiler. Vi kan vælge mellem mange prækompilerede binære filer, der er tilgængelige her.

Derudover er vi nødt til at hente gRPC Java Codegen Plugin.

Endelig kan vi bruge følgende kommando til at generere koden:

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. Brug af Maven Plugin

Som udvikler vil du gerne have, at kodegenerering integreres tæt i dit build-system. gRPC giver en protobuf-maven-plugin til Maven build-systemet:

   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} kompiler kompil-brugerdefineret 

Os-maven-plugin-udvidelsen / plugin genererer forskellige nyttige platformafhængige projektegenskaber som $ {os.detected.classifier}

6. Oprettelse af serveren

Uanset hvilken metode du bruger til kodegenerering, genereres følgende nøglefiler:

  • HelloRequest.java - indeholder HelloRequest type definition
  • HelloResponse.javadette indeholder HelleResponse type definition
  • HelloServiceImplBase.javadette indeholder den abstrakte klasse HelloServiceImplBase som giver en implementering af alle de operationer, vi definerede i servicegrænsefladen

6.1. Tilsidesættelse af servicebaseklassen

Det standardimplementering af abstraktklassen HelloServiceImplBase er at kaste undtagelse for runtimeio.grpc.StatusRuntimeException siger, at metoden er uimplementeret.

Vi udvider denne klasse og tilsidesætter Hej() metode nævnt i vores servicedefinition:

offentlig klasse HelloServiceImpl udvider HelloServiceImplBase {@Override offentlig ugyldig hej (HelloRequest anmodning, StreamObserver responsObserver) {String hilsen = ny StringBuilder () .append ("Hello,") .append (request.getFirstName ()) .append (""). tilføj (request.getLastName ()). tilString (); HelloResponse svar = HelloResponse.newBuilder () .setGreeting (hilsen) .build (); responsObserver.onNext (svar); responseObserver.onCompleted (); }}

Hvis vi sammenligner underskriften af Hej() med den, vi skrev i HellService.proto fil, vil vi bemærke, at den ikke vender tilbage Hej Svar. I stedet tager det andet argument som StreamObserver, som er en reaktionsobservator, et opkald tilbage til serveren for at ringe med sit svar.

Denne måde klienten får en mulighed for at foretage et blokerende opkald eller et ikke-blokerende opkald.

gRPC bruger bygherrer til oprettelse af objekter. Vi bruger HelloResponse.newBuilder () og indstil hilsenteksten til at bygge en Hej Svar objekt. Vi indstiller dette objekt til responseObserver's onNext () metode til at sende det til klienten.

Endelig er vi nødt til at ringe onFuldført () for at specificere, at vi er færdige med at håndtere RPC, ellers hænges forbindelsen op, og klienten venter bare på, at der kommer flere oplysninger.

6.2. Kørsel af Grpc-serveren

Dernæst skal vi starte gRPC-serveren for at lytte efter indgående anmodninger:

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

Her bruger vi igen bygherren til at oprette en gRPC-server på port 8080 og tilføje HelloServiceImpl tjeneste, som vi definerede. Start() ville starte serveren. I vores eksempel kalder vi awaitTermination () for at holde serveren kørende i forgrunden og blokere prompten.

7. Oprettelse af klienten

gRPC tilvejebringer en kanalkonstruktion, der abstraherer de underliggende detaljer ligesom forbindelse, forbindelsespooling, belastningsbalancering osv.

Vi opretter en kanal ved hjælp af ManagedChannelBuilder. Her specificerer vi serveradressen og porten.

Vi bruger almindelig tekst uden kryptering:

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

Derefter skal vi oprette en stub, som vi bruger til at foretage det faktiske fjernopkald til Hej(). Stubben er den primære måde for klienter at interagere med serveren på. Når du bruger automatisk genererede stubber, vil stubklassen have konstruktører til indpakning af kanalen.

Her bruger vi en blokerende / synkron stub, så RPC-opkaldet venter på, at serveren skal svare, og vil enten returnere et svar eller rejse en undtagelse. Der er to andre typer stubs leveret af gRPC, som letter ikke-blokerende / asynkrone opkald.

Endelig tid til at lave Hej() RPC-opkald. Her passerer vi HelloRequest. Vi kan bruge de automatisk genererede settere til at indstille fornavn, efternavn egenskaber for HelloRequest objekt.

Vi kommer tilbage Hej Svar objekt returneret fra serveren.

8. Konklusion

I denne vejledning så vi, hvordan vi kunne bruge gRPC til at lette udviklingen af ​​kommunikation mellem to tjenester ved at fokusere på at definere tjenesten og lade gRPC håndtere al kedelpladekoden.

Som sædvanligt finder du kilderne på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found