Mettez à jour vos connaissances Java en écrivant un serveur gRPC en Java (1)

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.

Modèles pour l'écriture d'applications console dans maven

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.

Génération automatique de classes

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'inclureprotobuf-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. image.png

À 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.

image.png

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.

Ecrire un serveur gRPC

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();
    }
  }

Ajouter une dépendance à Java

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.

Courir

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

Mettez à jour vos connaissances Java en écrivant un serveur gRPC en Java (2)
Mettez à jour vos connaissances Java en écrivant un serveur gRPC en Java (1)
Ce que j'ai appris lors de la création d'un serveur en Java
Rechercher un sous-ensemble en Java
Créez votre propre serveur simple avec Java et comprenez HTTP
3 Implémentez un interpréteur simple en Java
J'ai créé un PDF avec Java.
Une personne écrivant C ++ a essayé d'écrire Java
Gérez vos propres annotations en Java
Implémenter le client gRPC dans Ruby
Un exemple simple de rappels en Java
Restez coincé dans un Java Primer
[Java] Divise une chaîne de caractères par un caractère spécifié
Lors de la recherche de plusieurs dans un tableau Java
Carte en double triée par clé en Java
Différences d'écriture en Ruby, PHP, Java, JS
Points clés pour l'introduction de gRPC en Java
Comprenez l'interface java à votre manière
[Création] Un mémorandum sur le codage en Java
Java crée un tableau dans un document Word
Java crée un graphique circulaire dans Excel
Qu'est-ce qu'une classe en langage Java (1 /?)
Qu'est-ce qu'une classe en langage Java (2 /?)
Connaissance de base de la rédaction de notes de développement Java
Créer une application TODO dans Java 7 Créer un en-tête
Créons une application de calcul avec Java
Discussion continue sur l'écriture de Java avec Emacs @ 2018
Obtenir l'historique du serveur Zabbix en Java
Implémenter quelque chose comme une pile en Java
Diviser une chaîne avec ". (Dot)" en Java
Création d'une classe de matrice dans Java Partie 1
L'histoire de l'écriture de Java dans Emacs
Lire et écrire des fichiers gzip en Java
Créons une bibliothèque d'opérations de stockage de fichiers polyvalente (?) En faisant abstraction du stockage / acquisition de fichiers avec Java
Organisez la différence de confort d'écriture entre l'expression lambda Java et l'expression lambda Kotlin.