概念解析
grpc
gRPC是一个现代的开源高性能远程过程调用(Remote Procedure Call, RPC)框架,可以在任何环境中运行。通过对负载平衡、跟踪、运行状况检查和身份验证的可插拔支持
更多介绍:www.grpc.io/
grpc-web
gRPC-Web 提供了一个 Javascript 库,允许浏览器客户端访问 gRPC 服务
protobuf
protobuf 是 Google 的语言中立、平台中立、可扩展的结构化数据序列化机制——想想 XML,但更小、更快、更简单。您可以定义一次数据的结构化方式,然后您可以使用特殊生成的源代码轻松地使用各种语言在各种数据流中写入和读取结构化数据。
envoy
Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线 这里我们主要使用http2.0代理
grpc(node server)
- 新建 helloworld.proto
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 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;
- 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 代理,如果没有进行代理浏览器无法访问到接口
- 安装envoy (mac安装,其他系统自行百度)
brew install envoy
- 新建 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
使用端口:
代理端口:
- 启动代理
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文件
- 走到这里基本完事,随便一个项目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>
效果展示
如图所示 使用grpc protobuf 相比传统http json的数据通信方式使得数据更小,节省带宽,数据传输快。在数据量大,数据交互频繁的项目中是必不可少的,年纪大了记录一下,方便以后使用😄。