Depuis que j'ai décidé de refaire Java, j'ai décidé d'écrire un serveur gRPC pour mettre à jour mes connaissances en Java.
Cet article est merveilleux, donc je ne fais que le diffuser, mais comme il y a beaucoup de rasage de yak, j'aimerais l'inclure.
La première chose dans laquelle je suis resté coincé a été de créer une application console de niveau Hello World très simple avec maven
. Utilisez simplement maven-archetype-quickstart
.
mvn archetype:generate
-DgroupId=com.simplearchitect \
-DartifactId=helloGRPC \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
proto file
Protobuf de niveau Exactement Hello World. La syntaxe
doit être définie sur proto3
ou l'ancienne version sera utilisée. java_package
détermine le package de la classe générée automatiquement, il aurait donc été préférable de lui donner un nom plus sérieux. ʻOuter_classname` est le nom de la classe auto-générée qui représente le concept du protocole.
Le tampon de protocole ci-dessous a une méthode appelée SayHello
et définit un service simple qui renvoie HelloReply
lorsque vous envoyez une HelloRequest
.
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;
}
Lisez ceci pour mieux comprendre le fichier proto
.
Il est nécessaire de générer automatiquement une classe basée sur le fichier proto
. Cela nécessite que maven
soit défini sur dependency
et plugin
.
Regardez la page supérieure de gRPC-Java --An RPC library and framework et définissez maven
.
Il est nécessaire d'ajouter les bibliothèques de la famille ʻio.grpcet d'inclure
protobuf-maven-plugin et ʻos-maven-plugin
. Au fait, ʻos-maven-plugin` est
os-maven-plugin is a Maven extension/plugin that generates various useful platform-dependent project properties normalized from ${os.name} and ${os.arch}.
Et cela. 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>
Avec ce paramètre, mvn clean package
générera automatiquement une classe.
À propos, lors de la création d'un projet dans IntelliJ, il semble préférable de générer une fois target
, puis de l'exécuter. S'il est laissé à la valeur par défaut, le répertoire cible
disparaîtra. Après avoir créé target
, chargez le projet dans intelliJ et il sera défini automatiquement. Sinon, vous devez définir les paramètres suivants Fichier> Module de structure de projet.
Lors du chargement dans IntelliJ, si vous ne cliquez pas avec le bouton droit sur le projet et sélectionnez un projet Maven supplémentaire, même s'il n'y a pas d'erreur dans maven
, la dépendance à l'écran ne peut pas être résolue et une erreur se produira. Va finir.
Ecrivez un serveur en référence à la classe générée. Permet de faire cela à partir du programme principal. Tout ce que vous avez à faire est de démarrer le serveur, de le configurer et de définir les classes héritées.
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
Curieusement, j'ai une nouvelle classe statique. Qu'est-ce que ça veut dire? La classe suivante est la classe source de l'héritage, mais c'est une classe abstraite statique
. Ce n'est en fait pas une classe static
, mais cette classe est une classe interne et est marquée avec static
pour indiquer qu'elle peut être instanciée sans instancier la classe parente de la classe interne. Donc, en réalité, c'est une classe qui peut être instanciée.
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();
}
}
Créer un fichier jar avec mvn clean package
et l'exécuter entraînera une erreur. C'est parce que Jar n'inclut pas la bibliothèque. Ajoutons maven-assembly-plugin
. Maintenant, vous pouvez également spécifier mainClass
et cela créera une bibliothèque contenant les fichiers JAR dépendants.
`
<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. Exactement ce que vous cherchiez.
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.
Je me demande si cela fonctionne, mais tout d'abord, il a été compilé, un pot avec une bibliothèque a été créé et cela a fonctionné. La prochaine fois, j'essaierai de créer un client et de le déplacer. Je veux comprendre clairement le comportement de CallStreamObserver
.
Recommended Posts