1. Übersicht
gRPC ist ein sprach- und plattformneutrales RPC-Framework und -Toolset, das bei Google entwickelt wurde. Sie können damit einen Dienst mithilfe von Protocol Buffers definieren, einem besonders leistungsstarken Toolset und einer Sprache für die binäre Serialisierung. Anschließend können Sie idiomatische Client- und Server-Stubs aus Ihrer Dienstdefinition in verschiedenen Sprachen generieren.
In diesem Codelab erfahren Sie, wie Sie einen Java-basierten Dienst erstellen, der eine API mithilfe des gRPC-Frameworks freigibt, und dann einen Client schreiben, der den generierten clientseitigen gRPC-Stub verwendet.
Aufgaben in diesem Lab
- Die Protokollzwischenspeichersprache
- gRPC-Dienst mit Java implementieren
- gRPC-Client mit Java implementieren
Wie möchten Sie diese Anleitung nutzen?
<ph type="x-smartling-placeholder">Wie würden Sie Ihre Erfahrung mit der Erstellung von Node.js-Anwendungen bewerten?
<ph type="x-smartling-placeholder">Wie würden Sie Ihre Erfahrung mit der Erstellung von Go-Apps bewerten?
<ph type="x-smartling-placeholder">2. Einrichtung und Anforderungen
Umgebung für das selbstbestimmte 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 in diesem Codelab später als PROJECT_ID
bezeichnet.
- Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Google Cloud-Ressourcen nutzen zu können.
Dieses Codelab sollte möglichst wenig kosten. Folgen Sie der Anleitung im Abschnitt „Bereinigen“, . Hier erfahren Sie, wie Sie Ressourcen herunterfahren, damit Ihnen über dieses Tutorial hinaus keine Kosten entstehen. Neue Google Cloud-Nutzer haben Anspruch auf eine kostenlose Testversion mit 300$Guthaben.
Google Cloud Shell
Sie können dieses Codelab zwar auf Ihrem Computer ausführen, im Codelab verwenden wir jedoch Google Cloud Shell, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.
Diese Debian-basierte virtuelle Maschine verfügt über alle erforderlichen Entwicklungstools. Es bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und wird in Google Cloud ausgeführt. Dadurch werden die Netzwerkleistung und die Authentifizierung erheblich verbessert. Für dieses Codelab benötigen Sie also nur einen Browser – ja, er funktioniert auf Chromebooks.
- Klicken Sie einfach auf Cloud Shell aktivieren , um Cloud Shell über die Cloud Console zu aktivieren. Die Bereitstellung und Verbindung mit der Umgebung dauert einen Moment.
Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie bereits authentifiziert sind und dass das Projekt bereits auf Ihre PROJECT_ID
eingestellt ist.
gcloud auth list
Befehlsausgabe
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Befehlsausgabe
[core] project = <PROJECT_ID>
Sollte das Projekt aus irgendeinem Grund nicht eingerichtet sein, geben Sie einfach den folgenden Befehl ein:
gcloud config set project <PROJECT_ID>
Du suchst dein Gerät (PROJECT_ID
)? Sehen Sie nach, welche ID Sie bei den Einrichtungsschritten verwendet haben, oder rufen Sie sie im Dashboard der Cloud Console auf:
Cloud Shell legt außerdem standardmäßig einige Umgebungsvariablen fest, die bei der Ausführung zukünftiger Befehle nützlich sein können.
echo $GOOGLE_CLOUD_PROJECT
Befehlsausgabe
<PROJECT_ID>
- Legen Sie schließlich 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. Lassen Sie uns eine Proto-Datei für einen einfachen Begrüßungsdienst mit einer Hello-Anfrage und einer Hello-Antwort erstellen.
Erstellen Sie zunächst ein neues Proto-Verzeichnis für die neue Proto-Datei:
$ mkdir -p src/main/proto
Erstellen Sie dann eine neue Proto-Datei src/main/proto/GreetingService.proto
.
Sie können vim,nano,
oder emacs
verwenden, um die Datei zu 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 über die Definition verfügen, können wir sowohl den serverseitigen Stub 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 zu 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
Abschließend müssen Sie einen Server starten, der einen Port überwacht und diese Dienstimplementierung registriert. Bearbeiten Sie die App
-Klasse 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(); } }
Abschließend führen Sie den Server aus:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.App ... Server Started
4. Nutzung des Dienstes
Der Generator hat bereits alle clientseitigen Stubs generiert. Der Einfachheit halber verwenden wir dasselbe Maven-Projekt, fügen aber einfach eine neue Client
-Klasse mit einer neuen Main-Methode 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 zum Verzeichnis grpc-hello-server
:
$ cd grpc-hello-server
Fügen Sie dann die neue Klasse Client
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 zum Schluss den Client aus:
$ mvn -DskipTests package exec:java -Dexec.mainClass=com.example.grpc.Client ... greeting: "Hello there, Ray"
Fertig! Ganz einfach, oder?
5. Streamingdienst
Es gibt noch viel mehr, das Sie ausprobieren können. Sie können beispielsweise ganz einfach einen Streamingdienst erstellen, indem Sie einfach das Schlüsselwort stream
in der .proto-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 nicht nur eine, sondern mehrere Antworten gesendet werden. Führen Sie dazu mehrere responseObserver.onNext(...)
-Aufrufe durch:
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 ändern Sie den Typ stub
in 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(); } }); } }
Erstellen Sie die Anwendung neu:
$ mvn -DskipTests package
Starten Sie den Server und den Client jeweils 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 Protokollzwischenspeichersprache
- gRPC-Server mit Java implementieren
- gRPC-Client mit Java implementieren
Vorgehensweise:
- Weitere Informationen zu gRPC-Java
- Weitere gRPC-Java-Beispiele auf GitHub ansehen
- Informationen zu Streaming in gRPC
- Weitere Informationen zu gRPC-REST-Transcodierung
Feedback geben
- Bitte nehmen Sie sich einen Moment Zeit, um an unserer kurzen Umfrage teilzunehmen.