首页 >后端开发 >Golang >Web 和服务器之间的 gRPC。

Web 和服务器之间的 gRPC。

WBOY
WBOY原创
2024-08-31 06:35:36666浏览

该项目演示了如何使用 Envoy 代理在 Web 客户端和服务器之间建立简单的 gRPC 通信。

我正在使用 gRPC-Web 库来实现此目的。 gRPC-Web 是一个 JavaScript 客户端库,允许 Web 应用程序与 gRPC 服务交互。由于浏览器不支持 HTTP/2 或标准 gRPC 使用的二进制协议,因此 gRPC-Web 提供了一种弥合差距的方法,即使用 HTTP/1.1 或 HTTP/2 并以浏览器可以处理的方式对 gRPC 消息进行编码。 gRPC-Web 的工作原理如下:

  1. 客户端使用 gRPC-Web 向服务器发送请求,通常通过 HTTP/1.1 或 HTTP/2 进行通信。元数据(如标头)可以附加到请求中,例如用于身份验证(例如 JWT 令牌)。

请求以 gRPC-Web 格式编码,通常对二进制 gRPC 负载使用 base64 编码。客户端通过 HTTP/1.1 或 HTTP/2 发送此请求。

  1. Envoy(或其他反向代理,如 Nginx)充当 gRPC-Web 客户端和 gRPC 服务器之间的中介。 Envoy 接收 gRPC-Web 请求,解码 gRPC-Web 负载,并使用 HTTP/2 将其作为标准 gRPC 请求转发到 gRPC 服务器。

gRPC 服务器处理请求,就好像它是本机 gRPC 请求一样,使用 HTTP/2 进行通信。

  1. gRPC 服务器处理传入的 gRPC 请求,执行必要的业务逻辑,并生成响应(在本示例中是 Go 编写的应用程序)。响应以标准 gRPC 格式编码并发回 Envoy。

  2. Envoy 接收 gRPC 响应,将其编码为 gRPC-Web 格式(通常使用 base64),然后通过 HTTP/1.1 或 HTTP/2 将其发送回 gRPC-Web 客户端。 gRPC 响应中包含的任何元数据(例如状态代码)都会被适当翻译。

  3. gRPC-Web 客户端对响应进行解码并将其转换为 Web 应用程序中可用的格式。 Web 应用程序处理响应,根据需要更新 UI 或处理错误。

gRPC between Web and Server.

注意:当前不支持客户端和双向流式传输(请参阅流式传输路线图)

gRPC-Web 的优点

  • 浏览器兼容性:允许现代 Web 应用程序与 gRPC 服务交互,而不需要对 HTTP/2 和二进制协议的本机支持。
  • 效率:利用 gRPC 的性能和效率,同时适应网络。

这里有一个 GitHub 项目:

https://github.com/ehsaniara/gRPC-web-example

原始文件

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

服务器端(去)

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

特使配置

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

JS Web 客户端(webpack)

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

这是与此项目相关的 GitHub 项目

https://github.com/ehsaniara/gRPC-web-example

以上是Web 和服务器之间的 gRPC。的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn