网站首页 > 技术文章 正文
ProtoBuffer的介绍
google有一款非常高效的数据传输格式框架ProtoBuffer。在java中使用protobuffer作为序列化效率比jdk自身的serializable接口效率高的多(github上有个对于序列号性能的研究https://github.com/eishay/jvm-serializers/wiki),这在缓存的时候效率非常高。当然,如此优秀的数据格式框架并不是仅仅使用在缓存上的,既然压缩(姑且将其简单理解为压缩算法吧)如此高效,那么使用在网络IO传输中比JSON或许XML而言效率也为提升很多吧。
gRPC的介绍
gRPC是google开发的一款RPC框架,RPC Server与RPC Clinet之间的数据传输就是刚刚提到的ProtoBuffer,并且该RPC框架还是基于HTTP2的。因此,HTTP2的多路复用,基于流的传输在gRPC上也有相应的实现。
ProtoBuffer格式的定义
PrototBuffer的官方文档:https://developers.google.com/protocol-buffers/docs/proto3
笔者贴出在实际使用中的格式定义文件.proto:
syntax = "proto3"; package vsig; service VSIGProto { rpc setAcl (ACLRequest) returns (Reply) {} rpc openNtp (NTPConfig) returns (Reply) {} } message ACLRequest { string extranetIp = 1; int32 devType = 2; string intranetIp = 3; } message InterfaceInfoRequest { string name =1; string ip = 2; string mask=3; string gateway=4; } message NTPInfoRequest{ bool state = 1; string ntpServerIp =2; int32 ntpServerPort =3; } message NTPConfig{ NTPInfoRequest ntpInfo = 1; InterfaceInfoRequest br0Info = 2; } message Reply { string message = 1; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
.proto文件中主要定义了三部分东西:
- RPC的方法名以及接受的参数和返回的参数
- RPC方法接受参数的格式
- RPC方法返回的格式
一个方法仅能接受一个参数,因为笔者定义NTPConfig里面又包含了两个对象,这样保证了openNtp方法仅接收了一个对象
对于定义的message,每个值都有一个唯一的number类型的数字,根据官方文档的解释:它是用于以消息二进制格式标识字段,并且在使用过程中不能随便更改,否则会导致数据无法还原。同时,如果数字定义为1~15则使用一个字节来存储,而16~2047需要使用两个字节来存储。
gRPC Server的实现
定义好.proto之后就可以使用该文件来使用grpc客户端与服务器端了,gRPC的客户端与服务器端必须使用同一个.proto文件
gRPC支持众多常见的编程语言,笔者使用java与node两种语言实现gRPC。
NodeJS gRPC Server实现
package.json:
{ "name": "grpc-examples", "version": "0.1.0", "dependencies": { "async": "^1.5.2", "google-protobuf": "^3.0.0", "grpc": "^1.0.0", "lodash": "^4.6.1", "minimist": "^1.2.0" } }
gRPC服务器的编码实现:
//上述定义的.proto的路径 const PROTO_PATH = '../../vsig.proto'; const grpc = require( 'grpc' ); //最后vsig是.proto中的package const proto = grpc.load( PROTO_PATH ).vsig; //定义rpc Server的ip与端口 const rpcHost = '127.0.0.1'; const rpcPort = 50051; //定义方法的映射,因为方法最终是在该类中实现的,因此定义改类与.proto中的方法的映射。左边为.proto中的方法名,右边为实现 const methodCover = { setAcl: setAcl, openNtp: openNTP }; function setAcl( call, callback ) { //call.request即为该方法在.proto中定义的参数接收的message对象 console.log( call.request); //该回调即为对客户端的方法,参数1是error,参数二与.proto中方法的返回值对应 callback( null, { message: "rpc call setAcl method success" } ) } function openNTP( call, callback ) { const ntpInfo = call.request; console.log(ntpInfo); callback(null,{ message:"rpc call openNTP call success" }) } function main() { var server = new grpc.Server(); //VSIGProto即为.proto中的server的名称,参数二为方法映射 server.addProtoService( proto.VSIGProto.service, methodCover ); const grpcIn = grpc.ServerCredentials.createInsecure(); //绑定端口 server.bind( rpcHost + ":" + rpcPort, grpcIn ); //启动 server.start(); } main();
Java gRPC Server的实现
gRPC Client的实现
如上定义好服务端之后,将监听指定的端口,客户端只需要对改端口发送请求即可。
Node gRPC Client的实现
const PROTO_PATH = '../vsig.proto'; const grpc = require( 'grpc' ); //最后vsig是.proto中的package const proto = grpc.load( PROTO_PATH ).vsig; const rpcHost = '127.0.0.1'; const rpcPort = 50051; //VSIGProto是.proto中service中的VSIGProto const client = new proto.VSIGProto( rpcHost + ":" + rpcPort, grpc.credentials.createInsecure() ); class RpcClient { setAcl( acl, cb ) { //执行rpc调用 client.setAcl( acl, function( err, response ) { cb( err, response ) } ); } //封装RPC的方法 openNTP( ntpconfig, cb ) { //执行rpc调用 client.openNtp( ntpconfig, function( err, response ) { cb( err, response ); } ); } } const rpcClient = new RpcClient(); module.exports = rpcClient;
猜你喜欢
- 2024-09-30 SpringCloud 远程调用为啥要采用HTTP,而不是RPC?
- 2024-09-30 PRA10.3平台API接口调用 api接口调用教程
- 2024-09-30 程序员2022年你不懂RPC远程过程调用,RPC框架的话真的要被淘汰了
- 2024-09-30 Spring Cloud Gateway一次请求调用源码解析
- 2024-09-30 Go教程34:Go微服务间Http+Json调用
- 2024-09-30 接口测试:A13_HttpRunner_hook_01_钩子机制及用例层面的调用
- 2024-09-30 Spring 框架里的 HTTP 调用,RestTemplate 还是 WebClient
- 2024-09-30 HarmonyOS如何调用http/https接口?
- 2024-09-30 Feign : 优雅的调用 API 调用feign接口
- 2024-09-30 Spring Boot调用http接口的简单方法
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- mybatis返回int (51)
- jsonproperty注解无效 (52)
- jtextfield (48)
- flaskrequest.data (53)
- preflight请求 (48)
- request.getheader (57)
- pomexclusion (55)
- javassh连接远程服务器 (80)
- java-jar输出日志 (71)
- mybatis.type-aliases-package (63)
- arraystoreexception (56)
- 线程池submit (67)
- sshshell (49)
- vue2props (57)
- 微信小程序form表单提交 (55)
- javabase64转图片 (55)
- javaobject转map (74)
- java接口文档生成工具 (49)
- tcpflags (59)
- 虚拟机共享文件夹在哪 (60)
- shiro设置session过期时间 (61)
- python-msimpleserver (48)
- map转list对象 (50)
- resttemplate文件上传 (57)
- networkmanager是什么服务 (69)
本文暂时没有评论,来添加一个吧(●'◡'●)