gRPC tarp žiniatinklio ir serverio: paprastas gRPC ryšys

Tai paprastas gRPC ryšys tarp žiniatinklio kliento ir serverio naudojant įgaliotąjį įgaliotinį.
Tam naudoju gRPC-Web biblioteką. „gRPC-Web“ yra „JavaScript“ kliento biblioteka, leidžianti žiniatinklio programoms susisiekti su gRPC paslaugomis. Kadangi naršyklės nepalaiko HTTP/2 arba dvejetainio protokolo, naudojamo standartinio gRPC, „gRPC-Web“ suteikia galimybę užpildyti spragą naudojant HTTP/1.1 arba HTTP/2 ir užkoduojant gRPC pranešimus taip, kad juos galėtų apdoroti naršyklės. Štai kaip veikia gRPC-Web:
1- Klientas siunčia užklausas serveriui naudodamas gRPC-Web, kuris paprastai naudoja HTTP/1.1 arba HTTP/2. Prie užklausos gali būti pridėti metaduomenys (pvz., antraštės), pvz., autentifikavimui (pvz., JWT prieigos raktai).
Užklausa užkoduota gRPC-Web formatu, paprastai dvejetainei gRPC naudingajai apkrovai naudojant base64 kodavimą. Klientas siunčia šią užklausą per HTTP/1.1 arba HTTP/2.
2. „Envoy“ (arba kitas atvirkštinis tarpinis serveris, pvz., „Nginx“) yra tarp gRPC-Web kliento ir gRPC serverio. Pasiuntinys gauna gRPC-Web užklausą, dekoduoja gRPC-Web naudingąją apkrovą ir persiunčia ją kaip standartinę gRPC užklausą gRPC serveriui naudodamas HTTP/2.
GRPC serveris apdoroja užklausą taip, lyg tai būtų savoji gRPC užklausa, naudodamas HTTP/2.
3 – gRPC serveris apdoroja gaunamą gRPC užklausą, atlieka verslo logiką ir sugeneruoja atsakymą (šiuo atveju rašytinę programą Go). Atsakymas užkoduojamas standartiniu gRPC formatu ir siunčiamas atgal pasiuntiniui.
4- Pasiuntinys gauna gRPC atsakymą, užkoduoja jį gRPC-Web formatu (paprastai base64) ir siunčia atgal gRPC-Web klientui per HTTP/1.1 arba HTTP/2. Visi metaduomenys gRPC atsakyme, pvz., būsenos kodai, yra išverčiami.
5- gRPC-Web klientas iššifruoja atsakymą ir naudoja žiniatinklio programą.
PASTABA: Kliento pusės ir dvikryptis srautinis perdavimas šiuo metu nepalaikomas (žr srautinio perdavimo planas)
gRPC-Web privalumai
- Naršyklės suderinamumas: leidžia šiuolaikinėms žiniatinklio programoms sąveikauti su gRPC paslaugomis, nereikalaujant vietinio HTTP/2 ir dvejetainių protokolų palaikymo.
- Efektyvumas: išnaudoja gRPC našumą ir efektyvumą pritaikant jį žiniatinkliui.
Čia yra veikianti demonstracija
https://github.com/ehsaniara/gRPC-web-example
Demonstracinis greitas paleidimas
docker compose up -d
Tada atidarykite naršyklę adresu__http://localhost:8081__ (pastaba: šioje demonstracijoje naudojami 8081 ir 8080 prievadai)
Projekto struktūra
- client/: yra gRPC-Web kliento kodas
- serveris/: yra gRPC serverio kodas, parašytas Go
- envoy/: pasiuntinio konfigūracijos failas
Būtinos sąlygos
Proto failas
syntax = "proto3";
package helloworld;
option go_package = "./proto"; // Add this line
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
Serveris
Pagrindinis serverio failas (server/main.go
):
package main
import (
"context"
"google.golang.org/grpc/reflection"
"log"
"net"
pb "github.com/ehsaniara/gRPC-web-example/proto"
"google.golang.org/grpc"
)
type server struct {
pb.UnimplementedGreeterServer
}
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
// Register reflection service on gRPC server.
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
log.Println("Server is running on port 50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
Pasiuntinio konfig
...
http_filters:
- name: envoy.filters.http.grpc_web
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
- name: envoy.filters.http.cors
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
...
Interneto klientas
Kliento failas (client/src/index.js
)
// Import the generated gRPC-Web client stubs and message classes
import {GreeterClient} from './generated/helloworld_grpc_web_pb';
import {HelloRequest} from './generated/helloworld_pb';
// Create an instance of the Greeter client
const client = new GreeterClient('http://localhost:8080');
// Function to send a greeting request
function sayHello(name) {
// Create a new request
const request = new HelloRequest();
request.setName(name);
// Call the sayHello method on the Greeter client
client.sayHello(request, {}, (err, response) => {
if (err) {
console.error('Error:', err.message);
document.getElementById('output').textContent = 'Error: ' + err.message;
} else {
console.log('Greeting:', response.getMessage());
document.getElementById('output').textContent = 'Greeting: ' + response.getMessage();
}
});
}
// Example usage: sending a request when the page loads
document.addEventListener('DOMContentLoaded', () => {
const name = 'World';
sayHello(name);
});
Bėk generuoti.sh generuoti *_pb.js
failus, kuriuos reikia turėti grpc-web
ir protoc-gen-js
jau įdiegta jūsų kompiuteryje.
$ npm i grpc-web
$ npm install -g protoc-gen-js
Tai sugeneruos helloworld_grpc_web_pb.js
ir helloworld_pb.js
failus, kurie jau yra šioje demonstracijoje.
Čia yra susijęs „GitHub“ projektas: