gRPC og høyytelses-API-er · leksjon

Enkel unær gRPC-tjeneste

Implementer en grunnleggende gRPC-tjeneste og -klient med «forespørsel-svar» fra grunnen av ved hjelp av generert kode.

Leksjon 3 av 411 trinn

Enkel unær gRPC-tjeneste er en gratis leksjon i gRPC og høyytelses-API-er på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i gRPC og høyytelses-API-er, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i gRPC og høyytelses-API-er inneholder totalt 4 leksjoner.

Unary RPC: Enkel kommunikasjon

I gRPC er en Unary RPC det enkleste kommunikasjonsmønsteret. Det ligner på et tradisjonelt funksjonskall, der en klient sender én forespørsel til serveren, og serveren svarer med ett svar.

Tenk på det som en vanlig «forespørsel-svar»-modell. Klienten venter på svaret fra serveren før den fortsetter.

  • Klienten sender én melding.
  • Serveren sender én melding tilbake.
  • Dette er den vanligste typen RPC.

Se på Protobuf-definisjonen vår

Før vi går videre til implementeringen, skal vi kort repetere den enkle Protocol Buffer (Protobuf)-definisjonen vår. Dette skjemaet definerer tjenesten og meldingene vi skal bruke.

Vi skal implementere Greeter-tjenesten med metoden SayHello.

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.example.grpc.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

(Husk at kodegenerering ble gjennomgått i en tidligere leksjon.)

Server: Utvide basisklassen

Etter at vi har generert kode fra .proto-filen vår, oppretter gRPC en abstrakt basisklasse for serveren. For Greeter-tjenesten vår er dette GreeterGrpc.GreeterImplBase.

For å implementere tjenesten oppretter vi en ny klasse som extends denne basisklassen, og overstyrer tjenestemetoden(e).

class GreeterImpl extends GreeterGrpc.GreeterImplBase {
    @Override
    public void sayHello(HelloRequest req,
                         StreamObserver<HelloReply> resObserver) {
        // ... implementation goes here ...
    }
}

StreamObserver er måten vi sender svaret tilbake på.

Serverlogikk: Bygge svaret

Inne i sayHello-metoden mottar vi HelloRequest. Deretter kan vi behandle forespørselen og bygge HelloReply.

Metoden StreamObserver.onNext() sender svaret, mens onCompleted() signaliserer at RPC-kallet er fullført.

class GreeterImpl extends GreeterGrpc.GreeterImplBase {
    @Override
    public void sayHello(HelloRequest req,
                         StreamObserver<HelloReply> resObserver) {
        System.out.println("Received name: " + req.getName());
        HelloReply reply = HelloReply.newBuilder()
                                   .setMessage("Hello " + req.getName())
                                   .build();
        resObserver.onNext(reply);     // Send the response
        resObserver.onCompleted();  // Mark RPC as complete
    }
}

Fullstendig serverimplementasjon

La oss nå sette alt sammen for å opprette og starte en gRPC-server. Denne serveren lytter etter innkommende klientforespørsler på en bestemt port.

Prøv å kjøre denne koden, og fortsett deretter med klientimplementeringen!

package com.example.grpc.helloworld;

import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class HelloWorldServer {
    private Server server;

    private void start() throws IOException {
        int port = 50051;
        server = ServerBuilder.forPort(port)
                .addService(new GreeterImpl())
                .build()
                .start();
        System.out.println("Server started, listening on " + port);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                try {
                    HelloWorldServer.this.stop();
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
                System.err.println("*** server shut down");
            }
        });
    }

    private void stop() throws InterruptedException {
        if (server != null) {
            server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
        }
    }

    private void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        final HelloWorldServer server = new HelloWorldServer();
        server.start();
        server.blockUntilShutdown();
    }

    static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
        @Override
        public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
            System.out.println("Received: " + req.getName());
            HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
            responseObserver.onNext(reply);
            responseObserver.onCompleted();
        }
    }
}

Klientstub: Koble til og foreta kall

På klientsiden genererer gRPC også «stubber». Disse stubbene tilbyr metodene som brukes til å kalle den eksterne tjenesten, slik at det føles som et lokalt metodekall.

For unary RPC bruker vi ofte en blokkerende stub, noe som betyr at klienten venter på svaret fra serveren.

// Blocking stub for our Greeter service
GreeterGrpc.GreeterBlockingStub blockingStub;

Stubben håndterer alle detaljene rundt den underliggende nettverkskommunikasjonen for deg!

Klientkanal: Forbindelsen

Før klienten kan bruke en stub, trenger den en kanal. En kanal representerer en forbindelse til en gRPC-server på en bestemt vert og port.

Kanaler har vanligvis lang levetid og kan gjenbrukes for flere RPC-kall.

ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
                                            .usePlaintext() // No TLS for simplicity
                                            .build();
blockingStub = GreeterGrpc.newBlockingStub(channel);

usePlaintext() er greit i lokal utvikling, men bør unngås i produksjon!

Fullstendig klientimplementasjon

Nå som kanalen og stubben er klare, kan vi foreta unary RPC-kallet. Vi bygger en HelloRequest og sender den via stubben.

Kjør serveren fra forrige trinn, og kjør deretter denne klienten for å se den i praksis!

package com.example.grpc.helloworld;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

import java.util.concurrent.TimeUnit;

public class HelloWorldClient {
    private final ManagedChannel channel;
    private final GreeterGrpc.GreeterBlockingStub blockingStub;

    public HelloWorldClient(String host, int port) {
        channel = ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext() // For simplicity, no TLS
                .build();
        blockingStub = GreeterGrpc.newBlockingStub(channel);
    }

    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    public void greet(String name) {
        System.out.println("Will try to greet " + name + "...");
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloReply response;
        try {
            response = blockingStub.sayHello(request);
        } catch (StatusRuntimeException e) {
            System.err.println("RPC failed: " + e.getStatus());
            return;
        }
        System.out.println("Greeting: " + response.getMessage());
    }

    public static void main(String[] args) throws Exception {
        HelloWorldClient client = new HelloWorldClient("localhost", 50051);
        try {
            String user = "CoddyKit User";
            if (args.length > 0) {
                user = args[0];
            }
            client.greet(user);
        } finally {
            client.shutdown();
        }
    }
}

Unary-flyt: Forespørsel og svar

Når du kjører klienten, sender den HelloRequest til serveren. Serveren mottar den, behandler den ved hjelp av GreeterImpl og sender tilbake en HelloReply.

  • Klient: Oppretter kanal og stub, og bygger HelloRequest.
  • Klient: Kaller blockingStub.sayHello(request).
  • Server: Mottar HelloRequest i sayHello-metoden.
  • Server: Behandler forespørselen, bygger HelloReply og kaller onNext() og onCompleted().
  • Klient: Mottar HelloReply og fortsetter kjøringen.

Dette fullfører én hel unary RPC-syklus!

Sjekk av unary-tjenesten

Tenk på en gRPC-unary-tjeneste. Hvilken komponent er ansvarlig for å motta en forespørsel, behandle den og sende tilbake ett enkelt svar?

Oppsummering: Enkel unary RPC

Godt jobbet! Du har lært hvordan du implementerer en grunnleggende unary gRPC-tjeneste og klient:

  • Vi gjennomgikk Protobuf-skjemaet for tjenesten vår.
  • Vi implementerte serverlogikken ved å utvide den genererte basisklassen og håndtere forespørsler.
  • Vi bygde en gRPC-server og startet den.
  • På klientsiden brukte vi en kanal for å koble til og en blokkerende stub for å foreta RPC-kallet.

Unary RPC-er er grunnleggende i gRPC og gir en robust måte å håndtere enkel forespørsel-svar-kommunikasjon på. Deretter skal vi utforske mer avanserte strømmingsmønstre!

Gratis å komme i gang

Lær deg gRPC og høyytelses-API-er med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
12
Leksjoner
48

Ofte stilte spørsmål

Er leksjonen «Enkel unær gRPC-tjeneste» gratis?

Ja – hele teksten i «Enkel unær gRPC-tjeneste» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av gRPC og høyytelses-API-er-kurset, kan du oppgradere til CoddyKit PRO. Kurset i gRPC og høyytelses-API-er inneholder totalt 4 leksjoner.

Hva lærer jeg i «Enkel unær gRPC-tjeneste»?

Implementer en grunnleggende gRPC-tjeneste og -klient med «forespørsel-svar» fra grunnen av ved hjelp av generert kode. Du øver på gRPC og høyytelses-API-er med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med gRPC og høyytelses-API-er?

Ingen tidligere erfaring er nødvendig. gRPC og høyytelses-API-er på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Enkel unær gRPC-tjeneste»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne gRPC og høyytelses-API-er-leksjonen?

Ja. Alle gRPC og høyytelses-API-er-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Definere Protobuf-skjemaer
  2. Generere gRPC-kode
  3. Enkel unær gRPC-tjeneste
  4. Strømmende RPC-er: server, klient og toveis
← Tilbake til gRPC og høyytelses-API-er