1. Panoramica
gRPC è un framework e un insieme di strumenti per chiamate di procedura remota (RPC) indipendenti dal linguaggio e dalla piattaforma, sviluppati da Google. Consente di definire un servizio utilizzando Protocol Buffers, un linguaggio e un insieme di strumenti di serializzazione binaria particolarmente potenti. Ti consente poi di generare stub client e server idiomatici dalla definizione del servizio in una serie di lingue.
In questo codelab imparerai a creare un servizio basato su Java che espone un'API utilizzando il framework gRPC e poi a scrivere un client per utilizzare lo stub lato client gRPC generato.
Cosa imparerai a fare
- Il linguaggio di definizione dei protocolli
- Come implementare un servizio gRPC utilizzando Java
- Come implementare un client gRPC utilizzando Java
Come utilizzerai questo tutorial?
Come valuti la tua esperienza di creazione di app Node.js?
Come valuti la tua esperienza di creazione di app Go?
2. Configurazione e requisiti
Configurazione dell'ambiente autonomo
- Accedi alla console Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.



Ricorda l'ID progetto, un nome univoco tra tutti i progetti Google Cloud (il nome sopra è già stato utilizzato e non funzionerà per te, mi dispiace). In questo codelab verrà chiamato PROJECT_ID.
- Successivamente, dovrai abilitare la fatturazione in Cloud Console per utilizzare le risorse Google Cloud.
L'esecuzione di questo codelab non dovrebbe costare molto, se non nulla. Assicurati di seguire le istruzioni riportate nella sezione "Pulizia", che ti consiglia come arrestare le risorse in modo da non incorrere in addebiti oltre questo tutorial. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.
Google Cloud Shell
Sebbene questo codelab possa essere utilizzato dal tuo computer, in questo codelab utilizzeremo Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.
Questa macchina virtuale basata su Debian viene caricata con tutti gli strumenti di sviluppo di cui avrai bisogno. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Ciò significa che per questo codelab ti servirà solo un browser (sì, funziona su Chromebook).
- Per attivare Cloud Shell dalla console Cloud, fai clic su Attiva Cloud Shell
(bastano pochi istanti per eseguire il provisioning e connettersi all'ambiente).


Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è già impostato sul tuo PROJECT_ID.
gcloud auth list
Output comando
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Output comando
[core] project = <PROJECT_ID>
Se per qualche motivo il progetto non è impostato, esegui questo comando:
gcloud config set project <PROJECT_ID>
Stai cercando PROJECT_ID? Controlla l'ID che hai utilizzato nei passaggi di configurazione o cercalo nella dashboard della console Cloud:

Cloud Shell imposta anche alcune variabili di ambiente per impostazione predefinita, che potrebbero essere utili quando esegui i comandi futuri.
echo $GOOGLE_CLOUD_PROJECT
Output comando
<PROJECT_ID>
- Infine, imposta la zona e la configurazione del progetto predefinite.
gcloud config set compute/zone us-central1-f
Puoi scegliere una serie di zone diverse. Per saperne di più, consulta Regioni e zone.
3. Crea un servizio gRPC
Crea un nuovo progetto Java con Maven:
$ mvn archetype:generate -DgroupId=com.example.grpc \ -DartifactId=grpc-hello-server \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false $ cd grpc-hello-server
Aggiungere un file di definizione gRPC
In gRPC, i payload del servizio (richiesta e risposta) e le operazioni del servizio devono essere acquisiti in un IDL (Interface Definition Language). gRPC utilizza la sintassi di Protobuffer 3 per definire i payload e le operazioni dei messaggi. Creiamo un file proto per un semplice servizio di saluto con una richiesta di saluto e una risposta di saluto.
Innanzitutto, crea una nuova directory proto per contenere il nuovo file proto:
$ mkdir -p src/main/proto
Poi, crea un nuovo file proto src/main/proto/GreetingService.proto.
Puoi utilizzare vim,nano, o emacs per modificare il file:
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);
}
Aggiungere dipendenze e plug-in gRPC
Una volta ottenuta la definizione, possiamo generare sia lo stub lato server sia quello lato client da questo file. Dovrai aggiungere i plug-in e le dipendenze gRPC.
Innanzitutto, aggiungi le dipendenze gRPC a 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>
Quindi, aggiungi il plug-in:
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>
Generare gli stub
Quando crei l'applicazione, il plug-in converte le definizioni proto in codice Java.
$ mvn -DskipTests package
Per visualizzare i file generati:
$ find target/generated-sources
Implementare il Servizio
Innanzitutto, crea una nuova classe GreetingServiceImpl che implementerà l'operazione 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();
}
}
Implementare il server
Infine, dovrai avviare un server per ascoltare una porta e registrare questa implementazione del servizio. Modifica la classe App e il relativo metodo principale:
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();
}
}
Infine, esegui il server:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
4. Utilizzo del servizio
Il generatore ha già generato tutti gli stub lato client. Per semplificare il lab, utilizzeremo lo stesso progetto Maven, ma aggiungeremo semplicemente una nuova classe Client con un nuovo metodo principale.
Innanzitutto, fai clic su + per aprire una nuova sessione di Cloud Shell in modo da non dover terminare il server:

Nella nuova sessione, passa alla directory grpc-hello-server:
$ cd grpc-hello-server
Quindi, aggiungi la nuova classe 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();
}
}
Infine, esegui il client:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray"
È tutto. È un gioco da ragazzi, no?
5. Servizio di streaming
Puoi provare molte altre cose. Ad esempio, puoi creare facilmente un servizio di streaming semplicemente aggiungendo la parola chiave stream al parametro di richiesta o risposta nel file proto, ad esempio
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);
}
Aggiorna il server in modo che invii più risposte anziché una sola. Puoi farlo effettuando più chiamate 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();
}
}
Il client deve utilizzare uno stub asincrono anziché uno stub di blocco. Aggiorna il codice client assicurandoti di aggiornare il tipo stub a 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();
}
});
}
}
Ricrea l'applicazione:
$ mvn -DskipTests package
Riavvia sia il server che il client in una sessione Cloud Shell separata.
Per avviare il server:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
Per avviare il client:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray" greeting: "Hello there, Ray" greeting: "Hello there, Ray"
6. Complimenti!
Argomenti trattati:
- Il linguaggio di definizione dei protocolli
- Come implementare un server gRPC utilizzando Java
- Come implementare un client gRPC utilizzando Java
Passaggi successivi:
- Scopri di più su gRPC Java
- Visualizza altri esempi di gRPC Java su GitHub.
- Scopri di più sullo streaming in gRPC
- Scopri di più sulla transcodifica da gRPC a REST
Inviaci il tuo feedback
- Ti invitiamo a dedicare qualche istante per completare il nostro brevissimo sondaggio.