1、什麼是Google Protocol Buffer(protobuf官方網站)
下面是官網給的解釋: Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data. – think XML, but smaller, faster, and simpler. 協議緩衝區是一種和語言無關、平臺無關的可擴展機制,用於序列化結構化的數據。相比於xml,它更小,更快,更簡單。數據緩衝區經常使用語通訊協議和數據存儲。html
2、ProtoBuf的性能
序列化測試對比: Ser Time + Deser Time(ns)java
下面兩個網站是效率測試實驗:git
- https://code.google.com/archive/p/thrift-protobuf-compare/wikis/Benchmarking.wiki
- https://github.com/eishay/jvm-serializers/wiki
3、使用Intellij IDEA插件自動生成Java類
參考個人另外一篇文章:Google Protocol Buffer 的使用(一)github
4、Netty和protobuf整合
準備咱們的proto文件
syntax = "proto3"; package com.netty.protobuf; option java_outer_classname = "UserInfoProto"; //用戶信息 message UserInfo{ //姓名 string name = 1; //住址 repeated Address address= 2; //年齡 uint32 age = 3; } //用戶經常使用住址 message Address{ string addressname = 1; uint32 adressno = 2; }
服務器中設置protobuf編碼器和解碼器
@Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //protobuf解碼器 pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(UserInfoProto.UserInfo.getDefaultInstance())); //protobuf編碼器 pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.addLast(new ProtobufEncoder()); pipeline.addLast(new NettyServerHandler()); }
- ProtobufVarint32FrameDecoder是protobuf方式的解碼器,用於解決TCP粘包和拆包問題
- ProtobufDecoder 中設置咱們的proto文件生成的實例,其實就是咱們的目標Java類,設置方式爲:UserInfoProto.UserInfo.getDefaultInstance()
- ProtobufVarint32LengthFieldPrepender和ProtobufEncoder是protobuf方式的編碼器
處理類中寫protobuf數據
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { LOGGER.info("client {} connected.", ctx.channel().remoteAddress()); UserInfoProto.UserInfo user = UserInfoProto.UserInfo.newBuilder() .setName("server") .setAge(18) .addAddress( UserInfoProto.Address.newBuilder() .setAddressname("beijing 001") .setAdressno(911)) .build(); ctx.writeAndFlush(user); }
- 這裏經過UserInfoProto.UserInfo.newBuilder()使用的時間其類的建造者模式設置用戶相關信息。
- 再經過ChannelHandlerContext的writeAndFlush方法寫用戶數據。
處理器中讀protobuf數據
private int count = 0; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { UserInfoProto.UserInfo message = (UserInfoProto.UserInfo) msg; LOGGER.info("server received message {}:{}", ++count, message); }
- channelRead中的Object對象經過解碼以後就是一個protobuf類對象,因此能夠強轉:UserInfoProto.UserInfo message = (UserInfoProto.UserInfo) msg;
5、注意事項(TCP讀半包處理)
這裏咱們只是簡單使用了netty自帶的ProtobufVarint32FrameDecoder解碼器來處理讀半包問題,咱們還能夠本身繼承ByteToMessageDecoder類實現一個定製化的解碼器。好比咱們使用Java客戶端和C++服務器經過protobuf協議來通訊時,就須要本身實現,同時還須要考慮大端、小端模式的轉換問題。服務器