1. Übersicht
gRPC ist ein sprach- und plattformneutrales Framework und Toolset für Remoteprozeduraufrufe (Remote Procedure Call, RPC), das bei Google entwickelt wurde. Damit können Sie einen Dienst mit Protocol Buffers definieren, einem besonders leistungsstarken binären Serialisierungstoolset und einer besonders leistungsstarken Sprache. Anschließend können Sie aus Ihrer Dienstdefinition idiomatische Client- und Server-Stubs in verschiedenen Sprachen generieren.
In diesem Codelab erfahren Sie, wie Sie einen Java-basierten Dienst erstellen, der eine API über das gRPC-Framework bereitstellt, und wie Sie einen Client schreiben, der den generierten gRPC-Client-Stub verwendet.
Lerninhalte
- Die Protocol Buffer-Sprache
- So implementieren Sie einen gRPC-Dienst mit Java
- gRPC-Client mit Java implementieren
Wie werden Sie diese Anleitung verwenden?
Wie würden Sie Ihre Erfahrung beim Erstellen von Node.js-Apps bewerten?
Wie würden Sie Ihre Erfahrungen mit der Entwicklung von Go-Apps bewerten?
2. Einrichtung und Anforderungen
Umgebung zum selbstbestimmten Lernen einrichten
- Melden Sie sich in der Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.



Notieren Sie sich die Projekt-ID, also den projektübergreifend nur einmal vorkommenden Namen eines Google Cloud-Projekts. Der oben angegebene Name ist bereits vergeben und kann leider nicht mehr verwendet werden. Sie wird später in diesem Codelab als PROJECT_ID bezeichnet.
- Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Google Cloud-Ressourcen verwenden zu können.
Die Durchführung dieses Codelabs sollte keine oder nur geringe Kosten verursachen. Folgen Sie bitte der Anleitung im Abschnitt „Bereinigen“, in der Sie erfahren, wie Sie Ressourcen herunterfahren können, damit nach Abschluss dieser Anleitung keine Gebühren anfallen. Neue Nutzer von Google Cloud kommen für das Programm für kostenlose Testversionen mit einem Guthaben von 300$ infrage.
Google Cloud Shell
Dieses Codelab kann zwar von Ihrem Computer aus ausgeführt werden, aber in diesem Codelab verwenden wir Google Cloud Shell, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.
Diese Debian-basierte virtuelle Maschine verfügt über alle Entwicklungstools, die Sie benötigen. Sie bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und läuft in Google Cloud, was die Netzwerkleistung und Authentifizierung erheblich verbessert. Für dieses Codelab benötigen Sie also nur einen Browser (es funktioniert auch auf einem Chromebook).
- Klicken Sie zum Aktivieren von Cloud Shell in der Cloud Console einfach auf Cloud Shell aktivieren
. Die Bereitstellung und Verbindung mit der Umgebung sollte nur wenige Augenblicke dauern.


Sobald die Verbindung mit der Cloud Shell hergestellt ist, sehen Sie, dass Sie bereits authentifiziert sind und für das Projekt schon Ihre PROJECT_ID eingestellt ist.
gcloud auth list
Befehlsausgabe
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Befehlsausgabe
[core] project = <PROJECT_ID>
Wenn das Projekt aus irgendeinem Grund nicht festgelegt ist, führen Sie einfach den folgenden Befehl aus:
gcloud config set project <PROJECT_ID>
Suchst du nach deinem PROJECT_ID? Sehen Sie nach, welche ID Sie in den Einrichtungsschritten verwendet haben, oder suchen Sie sie im Cloud Console-Dashboard:

In Cloud Shell werden auch einige Umgebungsvariablen standardmäßig festgelegt, die für zukünftige Befehle nützlich sein können.
echo $GOOGLE_CLOUD_PROJECT
Befehlsausgabe
<PROJECT_ID>
- Legen Sie zum Schluss die Standardzone und die Projektkonfiguration fest.
gcloud config set compute/zone us-central1-f
Sie können verschiedene Zonen auswählen. Weitere Informationen finden Sie unter Regionen und Zonen.
3. gRPC-Dienst erstellen
Erstellen Sie ein neues Java-Projekt mit Maven:
$ mvn archetype:generate -DgroupId=com.example.grpc \ -DartifactId=grpc-hello-server \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false $ cd grpc-hello-server
gRPC-Definitionsdatei hinzufügen
In gRPC müssen Dienstnutzlasten (Anfrage und Antwort) und die Dienstvorgänge in einer IDL (Interface Definition Language) erfasst werden. gRPC verwendet die Protobuffer 3-Syntax, um Nachrichtennutzlasten und ‑vorgänge zu definieren. Erstellen wir eine Proto-Datei für einen einfachen Greeting Service mit einem Hello-Request und einer Hello-Response.
Erstellen Sie zuerst ein neues Proto-Verzeichnis für die neue Proto-Datei:
$ mkdir -p src/main/proto
Erstellen Sie dann eine neue Protobuf-Datei src/main/proto/GreetingService.proto.
Sie können die Datei mit vim,nano, oder emacs bearbeiten:
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-Abhängigkeiten und ‑Plug-in hinzufügen
Sobald Sie die Definition haben, können wir sowohl den serverseitigen als auch den clientseitigen Stub aus dieser Datei generieren. Sie müssen die gRPC-Abhängigkeiten und ‑Plug-ins hinzufügen.
Fügen Sie zuerst die gRPC-Abhängigkeiten zum pom.xml hinzu:
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>
Fügen Sie dann das Plug-in hinzu:
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>
Stubs generieren
Wenn Sie die Anwendung erstellen, konvertiert das Plug-in die Proto-Definitionen in Java-Code.
$ mvn -DskipTests package
So rufen Sie die generierten Dateien auf:
$ find target/generated-sources
Dienst implementieren
Erstellen Sie zuerst eine neue GreetingServiceImpl-Klasse, die den greeting-Vorgang implementiert:
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();
}
}
Server implementieren
Schließlich müssen Sie einen Server starten, der auf einem Port wartet, und diese Dienstimplementierung registrieren. Bearbeiten Sie die Klasse App und ihre Hauptmethode:
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();
}
}
Führen Sie zum Schluss den Server aus:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
4. Dienst nutzen
Der Generator hat bereits alle clientseitigen Stubs generiert. Der Einfachheit halber verwenden wir für das Lab dasselbe Maven-Projekt, fügen aber einfach eine neue Client-Klasse mit einer neuen Hauptmethode hinzu.
Klicken Sie zuerst auf +, um eine neue Cloud Shell-Sitzung zu öffnen, damit Sie den Server nicht beenden müssen:

Wechseln Sie in der neuen Sitzung in das Verzeichnis grpc-hello-server:
$ cd grpc-hello-server
Fügen Sie dann die neue Client-Klasse hinzu:
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();
}
}
Führen Sie schließlich den Client aus:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray"
Geschafft! Ganz einfach, oder?
5. Streamingdienst
Es gibt noch viel mehr, was Sie ausprobieren können. Sie können beispielsweise ganz einfach einen Streamingdienst erstellen, indem Sie das Keyword stream in der Protobuf-Datei entweder dem Anfrage- oder dem Antwortparameter hinzufügen, z.B.
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);
}
Aktualisieren Sie Ihren Server so, dass er mehrere Antworten statt nur einer sendet. Dazu können Sie mehrere responseObserver.onNext(...)-Aufrufe ausführen:
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();
}
}
Der Client muss einen asynchronen Stub anstelle des blockierenden Stubs verwenden. Aktualisieren Sie den Clientcode und achten Sie darauf, dass der Typ stub auf GreetingServiceStub aktualisiert wird:
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();
}
});
}
}
Erstellen Sie die Anwendung neu:
$ mvn -DskipTests package
Starten Sie sowohl den Server als auch den Client in einer eigenen Cloud Shell-Sitzung neu.
So starten Sie den Server:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
So starten Sie den Client:
$ mvn exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray" greeting: "Hello there, Ray" greeting: "Hello there, Ray"
6. Glückwunsch!
Behandelte Themen:
- Die Protocol Buffer-Sprache
- gRPC-Server mit Java implementieren
- gRPC-Client mit Java implementieren
Vorgehensweise:
- Weitere Informationen zu gRPC Java
- Weitere gRPC Java-Beispiele auf GitHub
- Informationen zum Streaming in gRPC
- Weitere Informationen zur gRPC-zu-REST-Transcodierung
Feedback geben
- Bitte nehmen Sie sich einen Moment Zeit, um an unserer kurzen Umfrage teilzunehmen.