vue2.0项目集成Web-gRPC

日常记录一下项目中grpc的应用

一.准备工作

        1、安装grpc-web和google-protobuf,如下

npm i grpc-web 
npm i google-protobuf

        2、安装 protoc ,选择适用于自己系统的版本安装

        

          配置环境变量,以上下载安装/解压完后,在系统设置中配置环境变量,具体步骤如下:

                右键我的电脑,选择属性,在弹出的页面中选择“高级系统设置”,

        选择环境变量

        在系统变量里找到“Path”,选择编辑,添加路径指向上述安装的文件夹bin文件

         检验protoc是否安装成功:

         3、安装 protoc-gen-grpc-web (用于生成web.js的工具),选择适用于自己系统的版本安装

        

         或者直接执行

npm i -g protoc-gen-js protoc-gen-grpc-web

二.编写测试demo

        我是在src文件夹下新建了proto文件夹,编写example.proto文件:

// 步骤 1. 基本配置
// ================================================ ====
// 第一行告诉编译器这个文件中使用了什么语法。
// 第二行属于命名空间,用来防止不同的消息类型有命名冲突

syntax = "proto3";
package example;


// 步骤 2. 定义消息结构
// ================================================ ====
// 这定义了请求负载。 此处进入消息的每个属性都与其类型一起定义。
// 需要为每个属性分配一个唯一的编号,称为标签。 协议缓冲区使用此标记来表示属性,而不是使用属性名称。
// 所以,不像 JSON 我们每次都会传递属性名称 name,protocol buffer 会使用数字 1 来表示 name。 响应负载定义类似于请求。


message ExampleRequest {
  string name = 1;
}

message ExampleResponse {
  string message = 1;
}

// 步骤 3. 定义服务契约
// ================================================ ====
// 最后,让我们定义服务契约。 对于我们的 HelloService,我们定义了一个 GetHelloReq() 操作:

service ExampleService {
  rpc GetExampleMessage(ExampleRequest) returns (ExampleResponse);
}

         进入当前文件夹下图执行命令生成文件,用于在 Vue 组件中调用 gRPC 服务。:

        example_grpc_web_pb.js

        example_pb.js

protoc --proto_path=. --js_out=import_style=commonjs,binary:. --grpc-web_out=import_style=commonjs,mode=grpcwebtext:. example.proto

        --proto_path指proto文件所在的目录,如果是当前目录,用“.”表示

        --js_out=import_style=commonjs指利用commonjs编译js文件

        --grpc-web_out=import_style=commonjs,mode=grpcwebtext指利用commonjs编译后的grpc-web的js文件模式是grpcwebtext

        如果想要把生成的js文件存储到其他文件夹,在当前example.proto目录下执行:

protoc --proto_path=. --js_out=import_style=commonjs,binary:./../../proto/ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./../../proto/ example.proto

指定生成的文件放在 ./../../proto/目录中。

三、 在 Vue 组件中调用 gRPC 服务:

        在需要调用 gRPC 服务的 Vue 组件中导入生成的 gRPC-Web 客户端代码,并使用它来调用 gRPC 服务。例如,在 App.vue 组件中调用 GetExampleMessage 方法:

import { ExampleServiceClient } from './proto/example_grpc_web_pb';
import { ExampleRequest } from './proto/example_pb';

export default {
  name: 'App',
  methods: {
    callGrpcService() {
      const request = new ExampleRequest();
      request.setName('John');

      const client = new ExampleServiceClient('http://localhost:8080', null, null);
      client.getExampleMessage(request, {}, (err, response) => {
        if (err) {
          console.error('Error:', err.message);
        } else {
          console.log('Response:', response.getMessage());
        }
      });
    },
  },
};

四、实际场景中的应用:

        1、SwitchService.proto文件代码:

        

// Copyright 2015 The 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";

//import "google/api/annotations.proto";
option java_multiple_files = true;
option java_package = "SwitchService";
option java_outer_classname = "SwitchServiceRpc";

package SwitchService;

service SwitchApi
{
  rpc execRpcCommandSync(Request) returns (Reply);
  rpc execRpcCommand(Request) returns (Reply);
  rpc sendHeartbeat(HeartbeatRequest) returns (HeartbeatResponse);

}
message HeartbeatRequest {
  string request = 1;
}

message HeartbeatResponse {
  string rply = 1;
}
message Request
{
  string request = 1;
}
message Reply
{
  string rply = 1;
}

        2、使用上面(二)中的方法生成js文件SwitchService_pb、SwitchService_grpc_web_pb

        3、封装方法公共方法:

        

import {Request, Reply} from "@/proto/SwitchService_pb";
import { SwitchApiClient } from "@/proto/SwitchService_grpc_web_pb";
import { Message } from "element-ui";
import store from '@/store'


// 执行指令获取grpc数据
export function executeInstructions(url, Id, commandType, otherParameter) {
    return new Promise(function(resolve){
        // 创建grpc-web客户端,填入enovy的地址
        var client = new SwitchApiClient(url,null, null)
        // 创建请求参数并赋值
        var request = new Request();
        //固定指令传参
        var data = {
            Id:'',
            commandType:commandType,//指令id
            utcTime:getUtcTime(),//当前utc时间
            timeStamp:getTimeStamp()//当前时间戳
        }
        //如果传入ID,取传入ID,否则生成guid
        if(Id){
            data.Id = Id
        }else{
            data.Id = getGUID()
        }
        var allParameter = Object.assign(data,otherParameter)
        // 数据转换
        var s = JSON.stringify(allParameter)
        console.log('grpc传参+++++++++++++++++++++++++:'+s)
        request.setRequest(s);
        //  调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
        // TODO : 换方法
        client.execRpcCommand(request, {}, (err, response) => {
            console.log('grpc返回---------------------:'+response)
            if (err) {//grpc链接异常
                var errMessage = `Unexpected error for execRpcCommand: code = ${err.code}` +`, message = "${err.message}"`
                response = {
                    code:'error',
                    data:errMessage
                }
                // handle(response)
                // if (errMessage.indexOf('400') !== -1) {
                //     Message.warning(errMessage);
                // }
                resolve(response)
            } else {//grpc链接正常
                // 数据解析
                var parsingData = JSON.parse(response.array[0])
                if(parsingData.success){//请求正常
                    if(parsingData.content){//非空
                        try {//判断是否是json
                            parsingData.content = JSON.parse(parsingData.content)
                            response = {
                                code:'success',
                                data:parsingData
                            }
                        } catch (e) {//不是json
                            response = {
                                code:'success',
                                data:parsingData.content
                            }
                        }
                    }else{
                        response = {
                            code:'success',
                            data:'成功'
                        }
                    }
                    
                }else{//请求异常
                    response = {
                        code:'error',
                        data:parsingData.content
                    }
                }
                resolve(response)
                // handle(response)
            }
        })
    });
    
}


// 发送指令sendHeartbeat方法
export function sendHeartbeatInstructions(url,Id,commandType,otherParameter){
    return new Promise(function(resolve){
        // 创建grpc-web客户端,填入enovy的地址
        var client = new SwitchApiClient(url,null,null)
        // 创建请求参数并赋值
        var request = new Request();
        //固定指令传参
        var data = {
            Id:'',
            commandType:commandType,//指令id
            utcTime:getUtcTime(),//当前utc时间
            timeStamp:getTimeStamp()//当前时间戳
        }

        //如果传入ID,取传入ID,否则生成guid
        if(Id){
            data.Id = Id
        }else{
            data.Id = getGUID()
        }
        // console.log(data)
        var allParameter = Object.assign(data,otherParameter)
        // 数据转换
        var s = JSON.stringify(allParameter)
        // console.log('grpc传参+++++++++++++++++++++++++:'+s)
        request.setRequest(s);
        //  调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
        // TODO : 换方法
        let time1 =new Date().getTime()
        client.sendHeartbeat(request, {}, (err, response) => {
            let time2 =new Date().getTime()
            // console.log('grpc返回---------------------:'+response)
            if (err) {//grpc链接异常
                var errMessage = `Unexpected error for sendHeartbeat: code = ${err.code}` +`, message = "${err.message}"`
                response = {
                    code:'error',
                    data:errMessage,
                    time: time2-time1
                }
                // handle(response)
                // Message.warning(errMessage);
                response = {
                    code:'error',
                    data:{},
                    rowData:otherParameter,
                    time: time2-time1
                }
                resolve(response)
                // reject(response)
            } else {//grpc链接正常
                // 数据解析
                var parsingData = JSON.parse(response.array[0])
                response = {
                    code:'success',
                    data:parsingData,
                    rowData:otherParameter,
                    time: time2-time1
                }
                
                resolve(response)
            }
        })
    });
    
}

        4、页面中使用:

        

this.$grpcFun.executeInstructions(this.$store.state._grpcurl, "", 46, {}).then((response) => {
      if (response.code == "success") {
        **********************
            自己的方法
        **********************
      }else{
        this.$message.error("错误!")
      }
    })

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值