Da ich mich wieder für Java entschieden habe, habe ich beschlossen, einen gRPC-Server zu schreiben, um meine Java-Kenntnisse zu aktualisieren.
Dieser Artikel ist wunderbar, also streame ich ihn nur, aber da es viel Yak-Rasur gibt, würde ich ihn gerne aufnehmen.
Das erste, woran ich festhielt, war die Erstellung einer sehr einfachen Hello World-Konsolenanwendung mit maven
. Verwenden Sie einfach maven-archetype-quickstart
.
mvn archetype:generate
-DgroupId=com.simplearchitect \
-DartifactId=helloGRPC \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
proto file
Genau Hello World Level Protobuf. Syntax
muss auf Proto3
eingestellt sein, sonst wird die alte Version verwendet. java_package
bestimmt das Paket der automatisch generierten Klasse, daher wäre es möglicherweise besser gewesen, ihr einen ernsteren Namen zu geben. Outer_classname
ist der Name der automatisch generierten Klasse, die das Konzept des Protokolls darstellt.
Der folgende Protokollpuffer hat eine Methode namens "SayHello" und definiert einen einfachen Dienst, der "HelloReply" zurückgibt, wenn Sie eine "HelloRequest" senden.
main/proto/helloworld.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
Lesen Sie dies, um die Proto-Datei besser zu verstehen.
Es ist notwendig, automatisch eine Klasse basierend auf der Proto-Datei zu generieren. Dies erfordert, dass "Maven" auf "Abhängigkeit" und "Plugin" gesetzt wird. Schauen Sie sich die obere Seite von gRPC-Java - Eine RPC-Bibliothek und ein Framework an und setzen Sie "maven".
Es ist notwendig, Bibliotheken der "io.grpc" -Familie hinzuzufügen und "protobuf-maven-plugin" und "os-maven-plugin" einzuschließen. Übrigens ist os-maven-plugin
os-maven-plugin is a Maven extension/plugin that generates various useful platform-dependent project properties normalized from ${os.name} and ${os.arch}.
Und das. os-maven-plugin.
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.31.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.31.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.31.1</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
:
<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.12.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.31.1:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Mit dieser Einstellung generiert mvn clean package
automatisch eine Klasse.
Übrigens scheint es beim Erstellen eines Projekts in IntelliJ besser, "Ziel" einmal zu generieren und dann auszuführen. Wenn die Standardeinstellung beibehalten wird, verschwindet das Zielverzeichnis. Laden Sie das Projekt nach dem Erstellen von "Ziel" in IntelliJ und es wird automatisch festgelegt. Wenn nicht, müssen Sie die folgenden Einstellungen vornehmen: Datei> Projektstrukturmodul.
Wenn Sie beim Laden in IntelliJ nicht mit der rechten Maustaste auf das Projekt klicken und ein zusätzliches Maven-Projekt auswählen, kann die Abhängigkeit vom Bildschirm nicht behoben werden, und es tritt ein Fehler auf, auch wenn in maven
kein Fehler vorliegt. Wird enden.
Schreiben Sie einen Server mit Bezug auf die generierte Klasse. Ermöglicht dies über das Hauptprogramm. Sie müssen lediglich den Server starten, konfigurieren und die geerbten Klassen festlegen.
package com.simplearchitect;
import java.io.IOException;
import java.util.logging.Logger;
import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.GreeterGrpc.GreeterImplBase;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.CallStreamObserver;
import static io.grpc.ServerBuilder.*;
public class SimpleServer {
Logger logger = Logger.getLogger(getClass().getName());
Server server;
public void start() throws IOException {
server = ServerBuilder
.forPort(8080)
.addService((BindableService) new SimpleHelloServiceImpl())
.build()
.start();
logger.info("start gRPC server.");
}
public void stop() {
if (server != null) {
server.shutdown();
logger.info("Shutting down gRPC server.");
}
}
public void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
public static class SimpleHelloServiceImpl extends GreeterImplBase {
Logger logger = Logger.getLogger(getClass().getName());
public void sayHello(HelloRequest request, CallStreamObserver<HelloReply> responseObserver) {
logger.info(String.format("request: name = %s", request.getName()));
HelloReply reply = HelloReply.newBuilder().setMessage("Hello, " + request.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
abstract static class Seltsamerweise habe ich eine neue statische Klasse. Was bedeutet das? Die folgende Klasse ist die Vererbungsquellklasse, aber sie ist eine statische abstrakte Klasse. Dies ist eigentlich keine "statische" Klasse, aber diese Klasse ist eine innere Klasse und mit "statisch" gekennzeichnet, um anzuzeigen, dass sie instanziiert werden kann, ohne die übergeordnete Klasse der inneren Klasse zu instanziieren. In Wirklichkeit ist es also eine Klasse, die instanziiert werden kann.
public static abstract class GreeterImplBase implements io.grpc.BindableService {
/**
* <pre>
* Sends a greeting
* </pre>
*/
public void sayHello(io.grpc.examples.helloworld.HelloRequest request,
io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver) {
asyncUnimplementedUnaryCall(getSayHelloMethod(), responseObserver);
}
@java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
.addMethod(
getSayHelloMethod(),
asyncUnaryCall(
new MethodHandlers<
io.grpc.examples.helloworld.HelloRequest,
io.grpc.examples.helloworld.HelloReply>(
this, METHODID_SAY_HELLO)))
.build();
}
}
Das Erstellen und Ausführen einer JAR-Datei mit "mvn clean package" führt zu einem Fehler. Dies liegt daran, dass Jar die Bibliothek nicht enthält. Fügen wir das Maven-Assembly-Plugin hinzu. Jetzt können Sie auch "mainClass" angeben und eine Bibliothek erstellen, die die abhängigen Gläser enthält. `
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.simplearchitect.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>sample</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
The Assembly Plugin for Maven enables developers to combine project output into a single distributable archive that also contains dependencies, modules, site documentation, and other files.
Umm. Genau das, wonach Sie gesucht haben.
PS > > java -jar .\target\helloGRPC-1.0-SNAPSHOT-jar-with-dependencies.jar
Aug 16, 2020 11:17:33 PM com.simplearchitect.SimpleServer start
INFO: start gRPC server.
> Enter stop.
Ich frage mich, ob es funktioniert, aber zuerst wurde es kompiliert, ein Glas mit einer Bibliothek wurde erstellt und es hat funktioniert. Nächstes Mal werde ich versuchen, einen Client zu erstellen und ihn zu verschieben. Ich möchte das Verhalten von "CallStreamObserver" klar verstehen.
Recommended Posts