个人专题目录
1. Google Protobuf
1.1 编码和解码的基本介绍
-
编写网络应用程序时,因为数据在网络中传输的都是二进制字节码数据,在发送数据时就需要编码,接收数据时就需要解码
-
codec(编解码器) 的组成部分有两个:decoder(解码器)和 encoder(编码器)。encoder 负责把业务数据转换成字节码数据,decoder 负责把字节码数据转换成业务数据
1.2 Netty 本身的编码解码的机制和问题分析
-
Netty 自身提供了一些 codec(编解码器)
-
Netty 提供的编码器
-
StringEncoder,对字符串数据进行编码
-
ObjectEncoder,对 Java 对象进行编码
- Netty 提供的解码器
-
StringDecoder, 对字符串数据进行解码
-
ObjectDecoder,对 Java 对象进行解码
- Netty 本身自带的 ObjectDecoder 和 ObjectEncoder 可以用来实现 POJO 对象或各种业务对象的编码和解码,底层使用的仍是 Java 序列化技术 , 而Java 序列化技术本身效率就不高,存在如下问题
- 无法跨语言
- 序列化后的体积太大,是二进制编码的 5 倍多。
- 序列化性能太低
- => 引出 新的解决方案 [Google 的 Protobuf]
序列化对象
JBoss Marshalling序列化
Java是面向对象的开发语言。传递的数据如果是Java对象,应该是最方便且可靠。
影响序列化性能的关键因素总结如下:
- 序列化后的码流大小(网络带宽占用);
- 序列化&反序列化的性能(CPU资源占用);
- 并发调用的性能表现:稳定性、线性增长、偶现的时延毛刺等;
Netty默认提供了对Google Protobuf的支持,通过扩展Netty的编解码接口,用户可以实现其它的高性能序列化框架,例如Thrift的压缩二进制编解码框架。
不同的应用场景对序列化框架的需求也不同,对于高性能应用场景Netty默认提供了Google的Protobuf二进制序列化框架,如果用户对其它二进制序列化框架有需求,也可以基于Netty提供的编解码框架扩展实现。
1.3 Protobuf
- Protobuf 是Google 发布的开源项目,全称Google Protocol Buffers,是一种轻便高效的结构化数据存储格式,
可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或RPC[远程过程调用remote procedure
call ] 数据交换格式。
目前很多公司http+json tcp+protobuf - 参考文档: https://developers.google.com/protocol-buffers/docs/proto 语言指南
- Protobuf 是以message 的方式来管理数据的.
- 支持跨平台、跨语言,即[客户端和服务器端可以是不同的语言编写的] (支持目前绝大多数语言,例如C++、
C#、Java、python 等) - 高性能,高可靠性
- 使用protobuf 编译器能自动生成代码,Protobuf 是将类的定义使用.proto 文件进行描述。说明,在idea 中编
写.proto 文件时,会自动提示是否下载.ptotot 编写插件. 可以让语法高亮。 - 然后通过protoc.exe 编译器根据.proto 自动生成.java 文件
1.4 Protobuf 快速入门实例
syntax = "proto3"; //版本
//生成的外部类名,同时也是文件名
option java_outer_classname = "StudentPOJO";
//protoBuf 使用message 管理数据
//会在 StudentPOJO 外部类生成一个内部类 Student, 他是真正发送的POJO对象
message Student {
// Student 类中有 一个属性 名字为 id 类型为int32(protoBuf类型) 1表示属性序号,不是值
int32 id = 1;
string name = 2;
}
编译
protoc.exe --java_out=. Student.proto
将生成的StudentPOJO 放入到项目使用
1.5 Protobuf 快速入门实例2
syntax = "proto3";
option optimize_for = SPEED; // 加快解析
//指定生成到哪个包下
option java_package = "com.xubh.netty.codec2";
// 外部类名, 文件名
option java_outer_classname = "MyDataInfo";
//protoBuf 可以使用message 管理其他的message
message MyMessage {
//定义一个枚举类型
enum DataType {
//在proto3 要求enum的编号从0开始
StudentType = 0;
WorkerType = 1;
}
//用data_type 来标识传的是哪一个枚举类型
DataType data_type = 1;
//表示每次枚举类型最多只能出现其中的一个, 节省空间
oneof dataBody {
Student student = 2;
Worker worker = 3;
}
}
message Student {
//Student类的属性
int32 id = 1;
string name = 2;
}
message Worker {
string name = 1;
int32 age = 2;
}
网友评论