Uvod u gRPC

1. Uvod

gRPC je RPC okvir visokih performansi, open source okvir koji je u početku razvio Google. Pomaže u uklanjanju šifre uzorka i pomaže u povezivanju poliglotskih usluga u i između podatkovnih centara.

2. Pregled

Okvir se temelji na modelu klijent-poslužitelja poziva udaljenih procedura. Klijentska aplikacija može izravno pozivati ​​metode na poslužiteljskoj aplikaciji kao da je lokalni objekt.

Ovaj će se članak koristiti slijedećim koracima za stvaranje tipične aplikacije klijent-poslužitelj pomoću gRPC-a:

  1. Definirajte uslugu u a .proto datoteka
  2. Generirajte poslužiteljski i klijentski kôd pomoću prevoditelja međuspremnika protokola
  3. Stvorite poslužiteljsku aplikaciju, implementirajući generirana sučelja usluge i mrijesteći gRPC poslužitelj
  4. Stvorite klijentsku aplikaciju, upućujući RPC pozive koristeći generirane kvarove

Definirajmo jednostavan HelloService koja vraća pozdrave u zamjenu za ime i prezime.

3. Ovisnosti Mavena

Dodajmo ovisnosti grpc-netty, grpc-protobuf i grpc-stub:

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

4. Utvrđivanje usluge

Počinjemo s definiranjem usluge, specificiranje metoda koje se mogu pozvati na daljinu, zajedno s njihovim parametrima i vrstama povratka.

To je učinjeno u .proto datoteku pomoću međuspremnika protokola. Također se koriste za opisivanje strukture poruka korisnog tereta.

4.1. Osnovne konfiguracije

Stvorimo a HelloService.proto datoteka za naš uzorak HelloService. Za početak dodajemo nekoliko osnovnih detalja o konfiguraciji:

sintaksa = "proto3"; opcija java_multiple_files = true; paket org.baeldung.grpc;

Prvi redak govori prevoditelju koja se sintaksa koristi u ovoj datoteci. Prema zadanim postavkama, kompajler generira sav Java kôd u jednoj Java datoteci. Drugi redak poništava ovu postavku i sve će se generirati u pojedinačnim datotekama.

Na kraju, specificiramo paket koji želimo koristiti za generirane Java klase.

4.2. Definiranje strukture poruka

Zatim definiramo poruku:

poruka HelloRequest {string firstName = 1; niz lastName = 2; }

Ovo definira korisni teret zahtjeva. Ovdje je definiran svaki atribut koji ulazi u poruku zajedno sa svojim tipom.

Svakom atributu, koji se naziva oznaka, treba dodijeliti jedinstveni broj. Ovu oznaku koristi međuspremnik protokola za predstavljanje atributa umjesto da koristi ime atributa.

Dakle, za razliku od JSON-a gdje bismo dodali ime atributa ime svaki bi put međuspremnik protokola koristio broj 1 za predstavljanje ime. Definicija korisnog tereta odgovora slična je zahtjevu.

Imajte na umu da istu oznaku možemo koristiti u više vrsta poruka:

poruka HelloResponse {string pozdrav = 1; }

4.3. Utvrđivanje ugovora o usluzi

Na kraju, definirajmo ugovor o usluzi. Za naše HelloService definiramo a zdravo() operacija:

usluga HelloService {rpc hello (HelloRequest) vraća (HelloResponse); }

The zdravo() operacija prihvaća unaarni zahtjev i vraća unarni odgovor. gRPC također podržava streaming prefiksom potok ključna riječ na zahtjev i odgovor.

5. Generiranje koda

Sada prolazimo HelloService.proto datoteku u kompajler protokola međuspremnika protoc za generiranje Java datoteka. Postoji više načina da se to pokrene.

5.1. Korištenje kompajlera protokola međuspremnika

Prvo, trebamo kompajler protokola međuspremnika. Možemo birati između mnogih prekompajliranih binarnih datoteka koje su ovdje dostupne.

Uz to, moramo nabaviti gRPC Java Codegen dodatak.

Napokon, za generiranje koda možemo koristiti sljedeću naredbu:

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. Korištenje dodatka Maven

Kao programer, željeli biste da generiranje koda bude čvrsto integrirano s vašim sustavom gradnje. gRPC pruža a protobuf-maven-plugin za sustav gradnje 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} kompajliranje compile-custom 

Proširenje / dodatak os-maven-plugin generira različita korisna svojstva projekta ovisno o platformi, poput $ {os.detected.classifier}

6. Izrada poslužitelja

Neovisno o tome koju metodu koristite za generiranje koda, generirat će se sljedeće ključne datoteke:

  • HelloRequest.java - sadrži HelloRequest definicija tipa
  • HelloResponse.javaovo sadrži HelleResponse definicija tipa
  • HelloServiceImplBase.javaovo sadrži apstraktnu klasu HelloServiceImplBase koja osigurava implementaciju svih operacija koje smo definirali u sučelju usluge

6.1. Nadjačavanje osnovne klase usluge

The zadana implementacija apstraktne klase HelloServiceImplBase je baciti runtime iznimkuio.grpc.StatusRuntimeException rekavši da se metoda ne provodi.

Proširit ćemo ovu klasu i poništiti zdravo() metoda spomenuta u našoj definiciji usluge:

javna klasa HelloServiceImpl proširuje HelloServiceImplBase {@Override javna void hello (HelloRequest zahtjev, StreamObserver responseObserver) {String pozdrav = novi StringBuilder () .append ("Hello,") .append (request.getFirstName ()) .append (""). append (request.getLastName ()) .toString (); HelloResponse odgovor = HelloResponse.newBuilder () .setGreeting (pozdrav) .build (); responseObserver.onNext (odgovor); responseObserver.onCompleted (); }}

Usporedimo li potpis od zdravo() s onim koji smo napisali u HellService.proto datoteku, primijetit ćemo da se ne vraća HelloResponse. Umjesto toga, drugi argument uzima kao StreamObserver, koji je promatrač odgovora, uzvratni poziv koji će poslužitelj nazvati svojim odgovorom.

Ovuda klijent dobiva mogućnost upućivanja blokirnog ili neblokirajućeg poziva.

gRPC koristi graditelje za stvaranje objekata. Koristimo HelloResponse.newBuilder () i postavite tekst pozdrava za izgradnju a HelloResponse objekt. Ovaj smo objekt postavili na responseObserver onNext () način slanja klijentu.

Napokon, trebamo nazvati onCompleted () kako bismo precizirali da smo završili s RPC-om, inače će veza biti prekinuta, a klijent će samo pričekati da stignu dodatne informacije.

6.2. Pokretanje Grpc poslužitelja

Dalje, moramo pokrenuti gRPC poslužitelj kako bi slušao dolazne zahtjeve:

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

Ovdje opet koristimo graditelj za stvaranje gRPC poslužitelja na portu 8080 i dodavanje HelloServiceImpl usluga koju smo definirali. početak() pokrenuo bi poslužitelj. U našem ćemo primjeru nazvati awaitTermination () kako bi poslužitelj i dalje radio u prvom planu i blokirao upit.

7. Stvaranje klijenta

gRPC pruža konstrukciju kanala koja apstrahira temeljne detalje poput veze, udruživanja veza, uravnoteženja opterećenja itd.

Stvorit ćemo kanal pomoću ManagedChannelBuilder. Ovdje navodimo adresu i port poslužitelja.

Koristit ćemo običan tekst bez ikakve enkripcije:

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

Dalje, moramo stvoriti krov koji ćemo koristiti za upućivanje stvarnog daljinskog poziva zdravo(). Stub je primarni način da klijenti komuniciraju s poslužiteljem. Kada se koriste automatski generirani stubovi, klasa stub će imati konstruktore za omatanje kanala.

Ovdje koristimo blokadu / sinkronu kalupu tako da RPC poziv čeka da poslužitelj odgovori i vratit će odgovor ili pokrenuti iznimku. Postoje dvije druge vrste kvara koje pruža gRPC, a koje olakšavaju neblokirajuće / asinkrone pozive.

Napokon, vrijeme je da napravimo zdravo() RPC poziv. Ovdje prolazimo HelloRequest. Možemo koristiti automatski generirane postavljače za postavljanje ime, prezime atributi HelloRequest objekt.

Vraćamo HelloResponse objekt vraćen sa poslužitelja.

8. Zaključak

U ovom uputstvu vidjeli smo kako možemo koristiti gRPC kako bismo olakšali razvoj komunikacije između dviju usluga usredotočujući se na definiranje usluge i dopuštajući gRPC-u da obrađuje sav kôd uzorka.

Kao i obično, izvore ćete pronaći na GitHubu.