阅读 417

grpc(node server) + grpc-web + vue3 + envoy代理 使用总结

概念解析

grpc

gRPC是一个现代的开源高性能远程过程调用(Remote Procedure Call, RPC)框架,可以在任何环境中运行。通过对负载平衡、跟踪、运行状况检查和身份验证的可插拔支持

image.png

更多介绍:www.grpc.io/

grpc-web

gRPC-Web 提供了一个 Javascript 库,允许浏览器客户端访问 gRPC 服务

protobuf

protobuf 是 Google 的语言中立、平台中立、可扩展的结构化数据序列化机制——想想 XML,但更小、更快、更简单。您可以定义一次数据的结构化方式,然后您可以使用特殊生成的源代码轻松地使用各种语言在各种数据流中写入和读取结构化数据。

envoy

Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线 这里我们主要使用http2.0代理

grpc(node server)

  1. 新建 helloworld.proto
syntax = "proto3";

package helloworld;

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

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
复制代码
  1. node.js 写一个grpc server

var PROTO_PATH = __dirname + "/helloworld.proto";

var assert = require("assert");
var grpc = require("@grpc/grpc-js");
var protoLoader = require("@grpc/proto-loader");
var packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});
var protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
var helloworld = protoDescriptor.helloworld;

function doSayHello(call, callback) {
  callback(null, {
    message: "Hello! " + call.request.name,
  });
}

function getServer() {
  var server = new grpc.Server();
  server.addService(helloworld.Greeter.service, {
    //对应protobuf service 方法
    sayHello: doSayHello,
  });
  return server;
}

if (require.main === module) {
  var server = getServer();
  server.bindAsync(
    "0.0.0.0:9090",
    grpc.ServerCredentials.createInsecure(),
    (err, port) => {
      assert.ifError(err);
      server.start();
    }
  );
}

exports.getServer = getServer;

复制代码
  1. package.json
{
  "dependencies": {
    "@grpc/grpc-js": "^1.3.7",
    "@grpc/proto-loader": "^0.6.4",
    "grpc": "^1.24.11",
    "lodash": "^4.17.21"
  }
}

复制代码

4.运行调试 为了调试方便 可以安装一个nodemon 热加载

npm install -g nodemon 

node server.js
or
nodemon server.js

复制代码

envoy 代理

很多教程没有详细说明http2.0 代理,如果没有进行代理浏览器无法访问到接口

  1. 安装envoy (mac安装,其他系统自行百度)
brew install envoy
复制代码
  1. 新建 envoy.yarml

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address: { address: 0.0.0.0, port_value: 8181 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                codec_type: auto
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route:
                            cluster: greeter_service
                            max_stream_duration:
                              grpc_timeout_header_max: 0s
                      cors:
                        allow_origin_string_match:
                          - prefix: "*"
                        allow_methods: GET, PUT, DELETE, POST, OPTIONS
                        allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                        max_age: "1728000"
                        expose_headers: custom-header-1,grpc-status,grpc-message
                http_filters:
                  - name: envoy.filters.http.grpc_web
                  - name: envoy.filters.http.cors
                  - name: envoy.filters.http.router
  clusters:
    - name: greeter_service
      connect_timeout: 0.25s
      type: logical_dns
      http2_protocol_options: {}
      lb_policy: round_robin
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 0.0.0.0
                      port_value: 9090

复制代码

使用端口:

image.png

代理端口:

image.png

  1. 启动代理
envoy -c envoy.yaml
复制代码

vue3 grpc-web 数据接入

1.protobuf protoc-gen-grpc-web 安装(mac,其他系统自行百度)

brew install protobuf
brew install protoc-gen-grpc-web
复制代码

2.protobuf js 转换

protoc helloworld.proto \
    --js_out=import_style=commonjs:./ \
    --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./
复制代码

执行后会得到两个js文件

image.png

  1. 走到这里基本完事,随便一个项目vue,react都可以,我这里使用的是vue3。
<template>
  <div>
    <h1>grpc-web</h1>
    data :{{ state.data }}
  </div>
</template>

<script setup>
import { reactive } from "vue";
const state = reactive({
  data: "",
});
const { HelloRequest } = require("./helloworld_pb.js");
const { GreeterClient } = require("./helloworld_grpc_web_pb.js");

//切记 调用接口 不是server的接口
var client = new GreeterClient("http://localhost:8181");
var request = new HelloRequest();
request.setName("Jack");

// 接口调用
client.sayHello(request, {}, (err, response) => {
  console.log(response.getMessage());
  state.data = response.getMessage();
});

// 流式调用 服务端未实现
// client.sayHello(request, {}, (err, response) => {
//   response.on("data", (data) => {
//     console.log(data.getMessage());
//     state.data = data.getMessage();
//   });
//   response.on("end", () => {
//     console.log("end");
//   });
// });
</script>
复制代码

效果展示

image.png

如图所示 使用grpc protobuf 相比传统http json的数据通信方式使得数据更小,节省带宽,数据传输快。在数据量大,数据交互频繁的项目中是必不可少的,年纪大了记录一下,方便以后使用😄。

文章分类
前端
文章标签