In Entwicklung Letztes Updateated:
Teilen:
Jira-Software ist das Projektmanagement-Tool Nr. 1, das von agilen Teams zum Planen, Verfolgen, Freigeben und Unterstützen großartiger Software verwendet wird.

Sehen wir uns an, wie Sie gRPC in Java implementieren.

gRPC (Google Remote Procedure Call): gRPC ist eine von Google entwickelte Open-Source-RPC-Architektur, um eine Hochgeschwindigkeitskommunikation zwischen Mikrodiensten zu ermöglichen. gRPC ermöglicht Entwicklern die Integrationate Dienstleistungen, die in verschiedenen Sprachen verfasst sind. gRPC verwendet das Protobuf-Nachrichtenformat (Protocol Buffers), ein hocheffizientes, hochgepacktes Nachrichtenformat zur Serialisierung strukturierter Daten.

Für einige Anwendungsfälle kann die gRPC-API effizienter sein als die REST API.

Versuchen wir, einen Server auf gRPC zu schreiben. Zuerst müssen wir mehrere schreiben .proto Dateien, die Dienste und Modelle beschreiben (DTO). Für einen einfachen Server verwenden wir ProfileService und ProfileDescriptoder.

ProfileService sieht so aus:

syntax = "proto3";
package com.deft.grpc;
import "google/protobuf/empty.proto";
import "profile_descriptor.proto";
service ProfileService {
  rpc GetCurrentProfile (google.protobuf.Empty) returns (ProfileDescriptor) {}
  rpc clientStream (stream ProfileDescriptor) returns (google.protobuf.Empty) {}
  rpc serverStream (google.protobuf.Empty) returns (stream ProfileDescriptor) {}
  rpc biDirectionalStream (stream ProfileDescriptor) returns (stream 	ProfileDescriptor) {}
}

gRPC unterstützt eine Vielzahl von Client-Server-Kommunikationsoptionen. Wir werden sie alle aufschlüsseln:

  • Normaler Serveraufruf – Anfrage/Antwort.
  • Streaming vom Client zum Server.
  • Streaming vom Server zum Client.
  • Und natürlich der bidirektionale Stream.

Der ProfiDer Dienst leService verwendet die ProfileDescriptoder, was im Importabschnitt angegeben ist:

syntax = "proto3";
package com.deft.grpc;
message ProfileDescriptor {
  int64 profile_id = 1;
  string name = 2;
}
  • int64 ist Long für Java. Lassen Sie die profiIch gehöre dazu.
  • Schnur – Genau wie in Java ist dies eine String-Variable.

Sie können Gradle oder Maven verwenden, um das Projekt zu erstellen. Es ist bequemer für mich, Maven zu verwenden. Und weiter wird der Code mit Maven sein. Dies ist wichtig genug, um zu sagen, dass die zukünftige Generation der .proto für Gradle etwas anders sein wird und die Build-Datei anders konfiguriert werden muss. Um einen einfachen gRPC-Server zu schreiben, benötigen wir nur eine Abhängigkeit:

<dependency>
    <groupId>io.github.lognet</groupId>
    <artifactId>grpc-spring-boot-starter</artifactId>
    <version>4.5.4</version>
</dependency>

Es ist einfach unglaublich. Dieser Starter macht uns enorm viel Arbeit.

Das Projekt, das wir erstellen werdenate wird etwa so aussehen:

Wir benötigen GrpcServerApplication, um die Spring Boot-Anwendung zu starten. Und GrpcProfileService, der Methoden aus dem implementiert .proto Service. Um protoc und gener zu verwendenate Klassen aus geschriebenen .proto-Dateien, fügen Sie protobuf-maven-plugin zu pom.xml hinzu. Der Build-Abschnitt sieht folgendermaßen aus:

<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>
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                    <outputDirectory>${basedir}/target/generated-sources/grpc-java</outputDirectory>
                    <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.38.0:exe:${os.detected.classifier}</pluginArtifact>
                    <clearOutputDirectory>false</clearOutputDirectory>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  • protoSourceRoot – Angabe des Verzeichnisses, in dem sich die .proto-Dateien befindenated.
  • Ausgabe Verzeichnis – Wählen Sie das Verzeichnis aus, in dem die Dateien gespeichert werden sollenated.
  • clearOutputDirectory – eine Markierung, die angibt, dass das Gener nicht gelöscht werden sollated-Dateien.

In dieser Phase können Sie ein Projekt erstellen. Als nächstes müssen Sie zu dem Ordner gehen, den wir im Ausgabeverzeichnis angegeben haben. Das Genated-Dateien werden dort sein. Jetzt können Sie Ihren Abschluss machenally implementieren GrpcProfileService.

Die Klassendeklaration sieht wie folgt aus:

@GRpcService
public class GrpcProfileService extends ProfileServiceGrpc.ProfileServiceImplBase

GRpcService annotation – Markiert die Klasse als grpc-service-Bean.

Da wir unseren Service erben von ProfileServiceGrpc, ProfileServiceImplBase, können wir die Methoden der Elternklasse überschreiben. Die erste Methode, die wir überschreiben werden, ist getCurrentProfile:

    @Override
    public void getCurrentProfile(Empty request, StreamObserver<ProfileDescriptorOuterClass.ProfileDescriptor> responseObserver) {
        System.out.println("getCurrentProfile");
        responseObserver.onNext(ProfileDescriptorOuterClass.ProfileDescriptor
                .newBuilder()
                .setProfileId(1)
                .setName("test")
                .build());
        responseObserver.onCompleted();
    }

Um dem Kunden zu antworten, müssen Sie den aufWeiter -Methode auf dem übergebenen StreamObserver. Senden Sie nach dem Senden der Antwort ein Signal an den Client, dass der Server seine Arbeit beendet hat onAbgeschlossen. Beim Senden einer Anfrage an getCurrentProfile Server, die Antwort wird sein:

{
  "profile_id": "1",
  "name": "test"
}

Als nächstes werfen wir einen Blick auf den Server-Stream. Bei diesem Messaging-Ansatz sendet der Client eine Anfrage an den Server, der Server antwortet dem Client mit einem Nachrichtenstrom. Es sendet beispielsweise fünf Anfragen in einer Schleife. Wenn das Senden abgeschlossen ist, sendet der Server eine Nachricht an den Client über den erfolgreichen Abschluss des Streams.

Die überschriebene Server-Stream-Methode sieht wie folgt aus:

@Override
    public void serverStream(Empty request, StreamObserver<ProfileDescriptorOuterClass.ProfileDescriptor> responseObserver) {
        for (int i = 0; i < 5; i++) {
            responseObserver.onNext(ProfileDescriptorOuterClass.ProfileDescriptor
                    .newBuilder()
                    .setProfileId(i)
                    .build());
        }
        responseObserver.onCompleted();
    }

Somit erhält der Client fünf Nachrichten mit a ProfileId, gleich der Antwortnummer.

{
  "profile_id": "0",
  "name": ""
}
{
  "profile_id": "1",
  "name": ""
}
…
{
  "profile_id": "4",
  "name": ""
}

Der Client-Stream ist dem Server-Stream sehr ähnlich. Erst jetzt überträgt der Client einen Nachrichtenstrom an den Server processEs sind sie. Der Server kann process Nachrichten sofortately oder warten Sie auf alle Anfragen des Clients und dann process Them.

    @Override
    public StreamObserver<ProfileDescriptorOuterClass.ProfileDescriptor> clientStream(StreamObserver<Empty> responseObserver) {
        return new StreamObserver<>() {

            @Override
            public void onNext(ProfileDescriptorOuterClass.ProfileDescriptor profileDescriptor) {
                log.info("ProfileDescriptor from client. Profile id: {}", profileDescriptor.getProfileId());
            }

            @Override
            public void onError(Throwable throwable) {

            }

            @Override
            public void onCompleted() {
                responseObserver.onCompleted();
            }
        };
    }

Im Client-Stream müssen Sie die StreamObserver an den Client, an den der Server Nachrichten empfängt. Die Methode onError wird aufgerufen, wenn im Stream ein Fehler aufgetreten ist. Zum Beispiel ist es terminated falsch.

Um einen bidirektionalen Stream zu implementieren, ist es notwendig, die Erstellung eines Streams vom Server und dem Client zu kombinieren.

@Override
    public StreamObserver<ProfileDescriptorOuterClass.ProfileDescriptor> biDirectionalStream(
            StreamObserver<ProfileDescriptorOuterClass.ProfileDescriptor> responseObserver) {

        return new StreamObserver<>() {
            int pointCount = 0;
            @Override
            public void onNext(ProfileDescriptorOuterClass.ProfileDescriptor profileDescriptor) {
                log.info("biDirectionalStream, pointCount {}", pointCount);
                responseObserver.onNext(ProfileDescriptorOuterClass.ProfileDescriptor
                        .newBuilder()
                        .setProfileId(pointCount++)
                        .build());
            }

            @Override
            public void onError(Throwable throwable) {

            }

            @Override
            public void onCompleted() {
                responseObserver.onCompleted();
            }
        };
    } 

In diesem Beispiel gibt der Server als Antwort auf die Nachricht des Clients eine zurück profile mit einer erhöhten Punktzahl.

Schlussfolgerung

Wir haben die grundlegenden Optionen für die Nachrichtenübermittlung zwischen einem Client und einem Server unter Verwendung von . behandelt gRPC: implementierter Server-Stream, Client-Stream, bidirektionaler Stream.

Der Artikel wurde von Sergey Golitsyn . geschrieben

Teilen:
  • Redaktion
    Autor
    Ein Expertenteam von Geekflare ist Leidenschaftatesehr engagiertated zum Teilen umsetzbarer Inhalte, zur Bereitstellung von Erkenntnissen und zur Bereitstellung maßgeschneiderter Ratschläge, um Einzelpersonen und Unternehmen dabei zu helfen, in einer digitalen Welt erfolgreich zu sein.

Danke an unsere Sponsoren

Weitere großartige Lektüre zum Thema Entwicklung

Treiben Sie Ihr Geschäft an

Einige der Tools und Services, die Ihrem Unternehmen helfen grow.