在多年工作中,游戏的前端、后端的消息传输传输协议中,最常见的是json和probobuf,作为服务器人员,在打架整体服务器架构时候,一定要知道,自己项目适合于选择哪种协议,我们今天就用具体数据来说明他们之间的优缺点。
包体长度来对比:
proto文件
message data{ required string title = 1 ; //App名字 required string author = 2; //作者 } message data1{ repeated ListData data=1; message ListData{ required string title = 1 ; //App名字 required string author = 2; //作者 } }
java代码:
//json数据封装 JSONObject data=new JSONObject(); data.put("title","今日头条"); data.put("author","北京字节跳动科技有限公司"); System.out.println("json 包体长度:"+data.toString().getBytes().length); System.out.println("**********************分割线******************************"); //protobuf数据封装 GameMessage.data.Builder data1=GameMessage.data.newBuilder(); data1.setTitle("今日头条"); data1.setAuthor("北京字节跳动科技有限公司"); System.out.println("proto 包体长度:"+data1.build().toByteArray().length);
打印结果:
json 包体长度:72 **********************分割线****************************** proto 包体长度:52
为了公平性,json和protobuf封装的消息我们都是打印了二进制流的长度,从上面的打印结果我们可以看出protobuf协议比json协议少28%的io量。意味着可以节约用户流量和服务器socket缓存内存使用量。
执行效率对比
java代码:
int length=100000; //json数据封装 long jsonEncoderStartTime= System.currentTimeMillis(); //json开始封装协议的开始时间 JSONArray data=new JSONArray(); for (int i=0;i<length;i++) { JSONObject data1=new JSONObject(); data1.put("title", "今日头条"); data1.put("author", "北京字节跳动科技有限公司"); data.put(data1); } byte[] jsonBody=data.toString().getBytes(); long jsonEncoderEndTime=System.currentTimeMillis(); //封装结束时间 long jsonEncoderTime=jsonEncoderEndTime-jsonEncoderStartTime; //封装耗时 System.out.println("json封装数据时间:"+jsonEncoderTime+"ms"); System.out.println("json长度:"+jsonBody.length); System.out.print("\n"); long jsonDecStartTime=System.currentTimeMillis(); //解析开始 JSONArray readJsonData=new JSONArray(data.toString()); for (int i=0;i<readJsonData.length();i++){ JSONObject readOne=readJsonData.getJSONObject(i); String title=readOne.getString("title"); String author=readOne.getString("author"); } long jsonDecEndTime=System.currentTimeMillis(); //解析开始 long jsonDecTime=jsonDecEndTime-jsonDecStartTime; //解析耗时 System.out.println("json解析数据时间:"+jsonDecTime+"ms"); System.out.println("\n**********************分割线******************************\n"); //protobuf数据封装 long protoEncoderStartTime= System.currentTimeMillis(); //json开始封装协议的开始时间 GameMessage.data1.Builder data1=GameMessage.data1.newBuilder(); for (int i=0;i<length;i++) { GameMessage.data1.ListData.Builder dataOne=GameMessage.data1.ListData.newBuilder(); dataOne.setTitle("今日头条"); dataOne.setAuthor("北京字节跳动科技有限公司"); data1.addData(dataOne); } byte[] protoBody=data1.build().toByteArray(); long protoEncoderEndTime=System.currentTimeMillis(); //封装结束时间 long protoEncoderTime=protoEncoderEndTime-protoEncoderStartTime; System.out.println("proto封装数据时间:"+protoEncoderTime+"ms"); System.out.println("proto包体长度:"+protoBody.length); System.out.print("\n"); long protoDecStartTime=System.currentTimeMillis(); //解析开始 try { GameMessage.data1 proReaddate = GameMessage.data1.parseFrom(protoBody); for (int i=0;i<proReaddate.getDataCount();i++){ GameMessage.data1.ListData dataone=proReaddate.getData(i); String title=dataone.getTitle(); String author=dataone.getAuthor(); } }catch (InvalidProtocolBufferException i){ } long ptotoDecEndTime=System.currentTimeMillis(); //解析开始 long protoDecTime=ptotoDecEndTime-protoDecStartTime; //解析耗时 System.out.println("proto解析数据时间:"+protoDecTime+"ms");
打印结果:
json封装数据时间:348ms json长度:7300001 json解析数据时间:489ms **********************分割线****************************** proto封装数据时间:143ms proto包体长度:5400000 proto解析数据时间:374ms
从打印结果来看,在封装和解析方面,protobuf都有一定优势。
从测试结果来看,无论是socket内存,带宽,cpu性能方面,protobuf协议是比json协议有明显的优势,所有在一些要求比较高的项目时候最好使用protobuf协议传递,比如游戏服务器(简单h5小游戏排除哈)、电商数据服务器等。这里并不是说json不好,json也有自己优势,那就是相对于protobuf来说,使用简单,更多编程语言支持(包括很多前端脚本语言),而proto官方支持java,c++等,所以在通用性方面json比protobuf更好。
最后感谢json和protobuf ,还要感谢我的那几十个粉丝支持。
本文暂时没有评论,来添加一个吧(●'◡'●)