blog
blog copied to clipboard
.proto 协议缓冲文件介绍
前言
介绍 .proto 协议缓冲文件的基本用途,我们下面以一个helloworld 示例介绍。 示例项目:https://github.com/huangshuwei/vue-grpc-demo
什么是 .proto 协议缓冲文件
协议缓冲(Protocol Buffers),官方有很详细的协议缓冲的介绍。总结下有这些功能点:
- Defining A Message Type
- Scalar Value Types
- Optional And Default Values
- Enumerations
- Using Other Message Types
- Nested Types
- Updating A Message Type
- Extensions
- Oneof
- Maps
- Packages
- Defining Services
- Options
- Generating Your Classes
helloword 示例
我们只看客户端实现部分,假设已经定义好了一个 helloworld.proto 文件,内容如下:
syntax = "proto3";
package helloworld;
service Greeter {
// unary call
rpc SayHello(HelloRequest) returns (HelloReply);
// server streaming call
rpc SayRepeatHello(RepeatHelloRequest) returns (stream HelloReply);
}
message HelloRequest {
string name = 1;
}
message RepeatHelloRequest {
string name = 1;
int32 count = 2;
}
message HelloReply {
string message = 1;
}
生成Protobuf消息和客户端服务存根
根据 helloworld.proto文件我们可以生成Protobuf消息和客户端服务存根,如何生成可以参考windows环境生成Protobuf消息和客户端服务存根
操作成功后,会生成 helloworld_pb.js 和 helloworld_grpc_web_pb.js 文件。
helloworld_pb.js 文件会包含协议信息,而 helloworld_grpc_web_pb.js 文件则包含客户端操作的信息
helloworld.proto 文件分析-消息类型
通过关键字 message 定义了3个消息类型,分别是 HelloRequest、RepeatHelloRequest以及HelloReply
HelloRequest 消息,包含 string
类型的参数 name
message HelloRequest {
string name = 1;
}
RepeatHelloRequest 消息,包含 string
类型的参数 name
和 int32
类型的参数 count
message RepeatHelloRequest {
string name = 1;
int32 count = 2;
}
HelloReply 消息,包含 string
类型的参数 message
message HelloReply {
string message = 1;
}
helloworld.proto 文件分析-服务
通过关键字 service 定义服务(接口):
service Greeter {
// unary call(一元模式)
rpc SayHello(HelloRequest) returns (HelloReply);
// server streaming call(服务端流模式)
rpc SayRepeatHello(RepeatHelloRequest) returns (stream HelloReply);
}
可以看到,Greeter 对象包含两个服务。一元模式服务SayHello 和 服务端流模式SayRepeatHello服务。一元模式可以理解为客户端单次请求的方式,而服务端流模式可以理解为服务端推送方式。
客户端编写
获取消息类型对象,以及请求客户端对象
通过 helloworld_pb.js 文件获取消息类型对象。通过 helloworld_grpc_web_pb.js 文件获取客户端请求对象
// client.js
const {
HelloRequest,
HelloReply,
} = require("./service/proto/helloworld_pb.js");
const { GreeterClient } = require("./service/proto/helloworld_grpc_web_pb.js");
var client = new GreeterClient("http://" + window.location.hostname + ":8080", null, null);
SayHello 一元模式
此时我们可以通过 helloworld_pb.js 文件获取到这些协议信息。
给参数赋值,是通过消息类型的示例设置的。如HelloRequest 消息类型,它有一个 name 参数,name 赋值是通过 new HelloRequest().setName("参数值");
// client.js
// simple unary call
var request = new HelloRequest();
request.setName("World");
client.sayHello(request, {}, (err, response) => {
if (err) {
console.log(
`Unexpected error for sayHello: code = ${err.code}` + `, message = "${err.message}"`
);
} else {
console.log(response.getMessage());
}
});
SayRepeatHello 服务端流模式
和一元模式不同的是,对于请求的接收,是通过流的模式。如下:
// client.js
// simple unary call
var request = new HelloRequest();
request.setName("World");
client.sayHello(request, {}, (err, response) => {
if (err) {
console.log(
`Unexpected error for sayHello: code = ${err.code}` + `, message = "${err.message}"`
);
} else {
console.log(response.getMessage());
}
});
客户端请求完整代码:
// client.js
const {
HelloRequest,
RepeatHelloRequest,
HelloReply,
} = require("./service/proto/helloworld_pb.js");
const { GreeterClient } = require("./service/proto/helloworld_grpc_web_pb.js");
var client = new GreeterClient("http://" + window.location.hostname + ":8080", null, null);
// simple unary call
var request = new HelloRequest();
request.setName("World");
client.sayHello(request, {}, (err, response) => {
if (err) {
console.log(
`Unexpected error for sayHello: code = ${err.code}` + `, message = "${err.message}"`
);
} else {
console.log(response.getMessage());
}
});
// server streaming call
var streamRequest = new RepeatHelloRequest();
streamRequest.setName("World");
streamRequest.setCount(5);
var stream = client.sayRepeatHello(streamRequest, {});
stream.on("data", (response) => {
console.log(response.getMessage());
});
stream.on("error", (err) => {
console.log(`Unexpected stream error: code = ${err.code}` + `, message = "${err.message}"`);
});
总结
此时我们距离代码可以运行还有一段距离,下一篇将介绍 windows10 基于grpc-web 的 envoy 代理配置