Aktualisieren Sie Ihre Java-Kenntnisse, indem Sie einen gRPC-Server in Java schreiben (1)

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.

Vorlagen zum Schreiben von Konsolenanwendungen in Maven

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.

Automatische Klassengenerierung

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

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

image.png

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 gRPC-Server

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

Hinzufügen einer Abhängigkeit zu Java

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.

Lauf

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

Aktualisieren Sie Ihre Java-Kenntnisse, indem Sie einen gRPC-Server in Java schreiben (2).
Aktualisieren Sie Ihre Java-Kenntnisse, indem Sie einen gRPC-Server in Java schreiben (1)
Was ich beim Erstellen eines Servers in Java gelernt habe
Suchen Sie eine Teilmenge in Java
Erstellen Sie mit Java Ihren eigenen einfachen Server und verstehen Sie HTTP
3 Implementieren Sie einen einfachen Interpreter in Java
Ich habe ein PDF mit Java erstellt.
Eine Person, die C ++ schreibt, hat versucht, Java zu schreiben
Behandeln Sie Ihre eigenen Anmerkungen in Java
Implementieren Sie den gRPC-Client in Ruby
Ein einfaches Beispiel für Rückrufe in Java
Bleiben Sie in einem Java Primer stecken
[Java] Teilen Sie eine Zeichenfolge durch ein angegebenes Zeichen
Bei der Suche nach mehreren in einem Java-Array
Doppelte Karte sortiert nach Schlüssel in Java
Schriftliche Unterschiede in Ruby, PHP, Java, JS
Wichtige Punkte für die Einführung von gRPC in Java
Verstehen Sie die Java-Oberfläche auf Ihre eigene Weise
[Erstellen] Ein Memorandum über das Codieren in Java
Java erstellt eine Tabelle in einem Word-Dokument
Java erstellt ein Kreisdiagramm in Excel
Was ist eine Klasse in der Java-Sprache (1 /?)
Was ist eine Klasse in der Java-Sprache (2 /?)
Grundkenntnisse in der Java-Entwicklung Schreiben von Notizen
Erstellen Sie eine TODO-App in Java 7 Create Header
Lassen Sie uns eine Taschenrechner-App mit Java erstellen
Fortsetzung Sprechen Sie über das Schreiben von Java mit Emacs @ 2018
Abrufen des Verlaufs vom Zabbix-Server in Java
Implementieren Sie so etwas wie einen Stack in Java
Teilen Sie eine Zeichenfolge in Java mit ". (Dot)"
Erstellen einer Matrixklasse in Java Teil 1
Die Geschichte des Schreibens von Java in Emacs
Lesen und Schreiben von GZIP-Dateien in Java
Erstellen wir eine vielseitige Dateispeicher (?) - Operationsbibliothek, indem wir die Dateispeicherung / -erfassung mit Java abstrahieren
Organisieren Sie den Unterschied im Schreibkomfort zwischen dem Java-Lambda-Ausdruck und dem Kotlin-Lambda-Ausdruck.