当前位置: 首页 > 工具软件 > gRPC-Web > 使用案例 >

GRPC-WEB 学习

糜淇
2023-12-01

一、介绍

GRPC-Web 是谷歌的一个web 端产品,正式发布在2018-11-28,git官网

现阶段js 前端支持还比较少不支持http2的协议(git解答),所以必须使用Envoy或 gowebproxy代理访问grpc 的服务(c++/java/nodejs/go)

二、 生成文件

  1. proto 文件的定义如下
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

  1. pb 文件的生成,因为grpc传输是protobuf格式

proto.exe 下载

JavaScript 生成命令

protoc.exe -I=. helloworld.proto --js_out=import_style=commonjs:..\pb_gen

c++ 生成命令

protoc.exe -I=. --cpp_out=..\pb_gen helloworld.proto
  1. grpc 服务或客户端生成

Javascript 需要生成的exe的插件git 下载

protoc.exe -I=.\ Situat.proto --js_out=import_style=commonjs:. --plugin=protoc-gen-grpc=protoc-gen-grpc-web.exe  --grpc-web_out=import_style=commonjs,mode=grpcwebtext:.

c++ 生成命令

protoc.exe -I=. --grpc_out=..\pb_gen --plugin=protoc-gen-grpc=grpc_cpp_plugin.exe helloworld.proto

三、 web客户端

需要nmp 生成编译,package.json

主要的依赖库protobuf和grpc的版本与服务端一定要保持一致

{
  "name": "grpc-web-simple-example",
  "version": "0.1.0",
  "description": "gRPC-Web simple example",
  "devDependencies": {
    "@grpc/proto-loader": "^0.3.0",
    "async": "^1.5.2",
    "google-protobuf": "^3.6.1",
    "grpc": "^1.17.0",
    "grpc-web": "^1.0.3",
    "lodash": "^4.6.1",
    "webpack": "^4.16.5",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.14"
  }
}

执行命令

npm install

webpack 打包配置

module.exports = {
    entry:
        "./client.js",
        output:{filename:"./main.js"},
    devtool:'source-map'
}

webpack 打包编译

npx webpack

webpack-dev-server 可以测试运行

npx webpack-dev-server 

四、Envoy

Envoy主要是转发服务,只在liunx 下运行成功了

参照菜鸟教程

Envoy 的配置文件,
配置文件中的注释要去掉

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
  - name: listener_0
    address:
    # grpc 经过docker 转发的端口
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          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_grpc_timeout: 0s
              cors:
                allow_origin:
                - "*"
                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
                enabled: true
          http_filters:
          - name: envoy.grpc_web
          - name: envoy.cors
          - name: envoy.router
  clusters:
  - name: greeter_service
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    # grpc 的服务端口
    hosts: [{ socket_address: { address: localhost, port_value: 9090 }}]

编译文件

$ docker build -t helloworld/envoy -f ./envoy.Dockerfile .
$ docker run -d -p 8080:8080 --network=host helloworld/envoy

五、gowebproxy代理

说明见gith网址

  1. 主要使用

执行命令

./grpcwebproxy --backend_addr=192.168.0.17:50051 --run_tls_server=FALSE --server_http_debug_port=8892 --allow_all_origins=true --use_websockets=true --server_http_max_read_timeout=50s --server_http_max_write_timeout=50s
  • 命令参数解释
参数名说明
backend_addr192.168.0.17:50051要转发的服务ip和端口
run_tls_servertrue 或false默认为true 是否开启tls_server
server_http_debug_port8080转发的新的端口
allow_all_originstrue 或false默认false,http 是否允许跨域请求
use_websocketstrue 或false默认false 是否启用websockets
server_http_max_read_timeout10shttp 服务读取连接超时
server_http_max_write_timeout10shttp 服务连接读取超时时间
backend_max_call_recv_msg_size4 * 1024 * 1024传输消息最大内容限制,默认4Mb

六、grpc web js使用方式

  • 普通的使用方式
// 请求服务参数
  var unaryRequest = new this.ctors.EchoRequest();
  unaryRequest.setMessage(msg);
  /** echoAbort 服务接口方法
   *unaryRequest 发送数据
   *param {} 可以不填写
   *param callback 服务返回数据回调函数
   */
  this.echoService.echoAbort(unaryRequest, {}, function(err, response) {
    if (err) {
      echoapp.EchoApp.addRightMessage('Error code: '+err.code+' "'+
                                      err.message+'"');
    }
  });

-双向流的方式

  var streamRequest = new this.ctors.ServerStreamingEchoRequest();
  streamRequest.setMessage(msg);
  streamRequest.setMessageCount(count);
  streamRequest.setMessageInterval(echoapp.EchoApp.INTERVAL);

  var stream = this.echoService.serverStreamingEcho(
    streamRequest,
    {"custom-header-1": "value1"});
  var self = this;
  //接收服务发送的数据
  stream.on('data', function(response) {
    echoapp.EchoApp.addRightMessage(response.getMessage());
  });
  //当前状态
  stream.on('status', function(status) {
    self.handlers.checkGrpcStatusCode(status);
    if (status.metadata) {
      console.log("Received metadata");
      console.log(status.metadata);
    }
  });
  //错误信息
  stream.on('error', function(err) {
    echoapp.EchoApp.addRightMessage('Error code: '+err.code+' "'+
                                    err.message+'"');
  });
  //连接断开
  stream.on('end', function() {
    console.log("stream end signal received");
  });
 类似资料: