java protobuf负载比JSON大?
我有一个对象,它是一个“级别”对象列表,我正在用Spring Boot Rest Controller以两种方式测试传输它们:
对于JSON,我在Rest控制器中使用如下内容:
@RequestMapping(value = "/api/v1/layers/{layername}", method = RequestMethod.GET, produces = "application/json") public @ResponseBody List<Level> query(@PathVariable String layername, @RequestParam("northEastLat") Float northEastLat, @RequestParam("northEastLng") Float northEastLng, @RequestParam("northWestLat") Float northWestLat, @RequestParam("northWestLng") Float northWestLng, @RequestParam("southEastLat") Float southEastLat, @RequestParam("southEastLng") Float southEastLng, @RequestParam("southWestLat") Float southWestLat, @RequestParam("southWestLng") Float southWestLng ) { List<Level> poligons=levelService.obtainLevels(layername,southWestLng,southWestLat,northWestLng,northWestLat,northEastLng,northEastLat,southEastLng,southEastLat); int i=1; for (Level p : poligons) { System.out.println("poligon" + i++ + " is:" + p.toString()); } return poligons; }
对于Protostuff Protobuf格式,我使用如下内容:
@RequestMapping(value = "/api/v1/layers/{layername}", method = RequestMethod.GET,produces = "text/plain") public String query(@PathVariable String layername, @RequestParam("northEastLat") Float northEastLat, @RequestParam("northEastLng") Float northEastLng, @RequestParam("northWestLat") Float northWestLat, @RequestParam("northWestLng") Float northWestLng, @RequestParam("southEastLat") Float southEastLat, @RequestParam("southEastLng") Float southEastLng, @RequestParam("southWestLat") Float southWestLat, @RequestParam("southWestLng") Float southWestLng ) { List<Level> poligons=levelService.obtainLevels(layername,southWestLng,southWestLat,northWestLng,northWestLat,northEastLng,northEastLat,southEastLng,southEastLat); LevelList list = new LevelList(poligons); byte[] bytes; int i=1; for (Level p : poligons) { System.out.println("poligon" + i++ + " is:" + p.toString()); } Schema<LevelList> schema = RuntimeSchema.getSchema(LevelList.class); LinkedBuffer buffer = LinkedBuffer.allocate(); try { bytes = ProtostuffIOUtil.toByteArray(list, schema, buffer); } finally { buffer.clear(); } return new String(bytes); }
级别对象格式为: [{“wkb_几何”:“{”类型“:”多边形“,”坐标“:[[[24.446822,45.34997],[24.706508,45.352485]]}”,“id”:199,“级别”:“3”,“类型”:null}
级别对象是:
@Entity(name = "Level")
@Table(name="Level2G")
@SecondaryTables({
@SecondaryTable(name="Level3G"),
@SecondaryTable(name="Level4G")
})
public class Level implements Serializable {
private static final long serialVersionUID = 1L;
// @Column(name = "wkb_geometry",columnDefinition="Geometry")
//@Type(type = "org.hibernate.spatial.GeometryType")
@Column(name="wkb_geometry")
private /*Geometry */ String wkb_geometry;
@Id
@Column(name="id")
private Integer id;
@Column(name="level")
private String level;
@Transient
private String type;
public Level() {
}
public Level(String wkb_geometry, Integer id, String level) {
this.wkb_geometry = wkb_geometry;
this.id = id;
this.level = level;
this.type = "Feature";
}
public Level(String wkb_geometry, Integer id, String level, String type) {
this.wkb_geometry = wkb_geometry;
this.id = id;
this.level = level;
this.type = type;
}
public Object getWkb_geometry() {
return wkb_geometry;
}
public void setWkb_geometry(String wkb_geometry) {
this.wkb_geometry = wkb_geometry;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Level{" +
"wkb_geometry=" + wkb_geometry +
", id=" + id +
", level='" + level + '\'' +
", type='" + type + '\'' +
'}';
}
}
LevelList对象只是级别对象的列表
问题是,与JSON(3.7kb)相比,Protostuff的有效负载(26KB)更大。为什么?
同样对于第二个选项,我也尝试设置“application/octetstream”直接返回字节,但结果仍然相同。我还比较了JSON和protobuf的速度;protobuf即使在负载更大的情况下也具有更好的性能。知道为什么吗
# 1 楼答案
Protostuff和Protobuf不是一回事。Protostuff是一个包装器库,可以使用多种不同的序列化格式。它还支持运行时模式生成,您似乎正在使用它。该运行时模式需要随消息一起发送额外的元数据,以告知接收方消息的模式。我猜您看到的大消息主要来自此运行时模式数据
使用标准Protobuf,模式不会与消息一起发送,因为假定发送方和接收方已经同意由编译到两个程序中的
.proto
文件提供的模式。如果将Protobuf与标准的.proto
文件一起使用,您会发现它生成的消息比JSON小得多# 2 楼答案
您的测试中至少有一个问题
从字节数组到字符串的转换无效:
此字符串构造函数将尝试将字节数组解析为UTF-8字符串(很可能,这取决于您的语言环境设置),但根据定义提供的数据不是有效的UTF-8字符串
如果要进行更好的大小比较,应按以下形式编写测试:
这里的要点是使您的测试具有可复制性,以便其他人可以重复它