平时Spring web开发的时候使用的都是JSON作为数据交互,今天我们来学习一点不一样的,使用Protobuf来作为数据交互,同时来比较一下JSON作为数据交互和Protobuf作为数据交互的快慢以及优缺点。
使用前准备:
-
新建一个maven Spring Boot项目(版本2.6.3)
-
pom.xml配置文件增加Protobuf编译配置插件,以及Protobuf相关maven依赖
<dependencies> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.19.2</version> </dependency> </dependencies> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protoSourceRoot>${basedir}/src/main/resources</protoSourceRoot> <protocArtifact>com.google.protobuf:protoc:3.19.1:exe:${os.detected.classifier}</protocArtifact> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.43.1:exe:${os.detected.classifier}</pluginArtifact> <outputDirectory>src/main/java</outputDirectory> <clearOutputDirectory>false</clearOutputDirectory> <pluginId>grpc-java</pluginId> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>1. Spring 接入Protobuf
原理和JSON的原理一样:通过消息转换器将服务器的返回数据转换成对应的格式。
Protobuf的使用详情参考官网:developers.google.com/protocol-bu…
1.1 定义proto文件
proto文件是用来定义Java类似的Bean。下面就定义一个mxsm.proto文件
syntax = "proto3"; package mxsm; option java_package = "com.github.mxsm.springboot.protobuf"; option java_outer_classname = "ProtobufMessage"; message Course { int32 id = 1; string course_name = 2; repeated Student student = 3; } message Student { int32 id = 1; string first_name = 2; string last_name = 3; string email = 4; repeated PhoneNumber phone = 5; message PhoneNumber { string number = 1; PhoneType type = 2; } enum PhoneType { MOBILE = 0; LANDLINE = 1; } }1.2 将proto文件编译为Java类
通过前面配置的Protobuf maven编译成Java Bean.
通过这样就编译完成了,生成了 ProtobufMessage 类
1.3 配置Spring消息转换器
@Configuration
public class Config {
@Bean
public ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
ProtobufHttpMessageConverter Spring提供了支持。
到这里就完成了整个的配置过程:
1.4 测试Protobuf
@SpringBootTest(classes = SpringProtobufBootstrap.class)
public class ApplicationTest {
// Other declarations
private static final String COURSE1_URL = "http://localhost:8080/courses/2";
private RestTemplate restTemplate = new RestTemplate();
@Test
public void whenUsingRestTemplate_thenSucceed() {
List<HttpMessageConverter<?>> list = new ArrayList<>();
list.add(new ProtobufHttpMessageConverter());
restTemplate.setMessageConverters(list);
ResponseEntity<Course> course = restTemplate.getForEntity(COURSE1_URL, Course.class);
System.out.println(course.toString());
}
}
测试结果:
2. Spring JSON和Protobuf性能比较
接口的测试工具用的Apache JMeter.
首先编写测试接口
@RestController
public class JsonProtobufController {
@RequestMapping("/student/{id}")
Student protobuf(@PathVariable Integer id) {
return Student.newBuilder().setId(id).setFirstName("maxsm").setLastName("sdfsdfsdfsdfsdfsdsdfsdfsdfsdfsdfsdfsdfsdf")
.setEmail("1224sdfsfsdf344552@163.com").addPhone(Student.PhoneNumber.newBuilder().setNumber("12345sdfsdfsd6566666").setType(
Student.PhoneType.MOBILE).build()).build();
}
@RequestMapping("/studentjson/{id}")
StudentJson json(@PathVariable Integer id) {
StudentJson json = new StudentJson();
json.setId(id);
json.setFirstName("maxsm");
json.setLastName("sdfsdfsdfsdfsdfsd");
json.setEmail("1224344552@163.com");
json.setPhoneNumber(new PhoneNumber("123456566666",PhoneType.MOBILE));
return json;
}
}
JSON的测试结果:
Protobuf测试结果:
对比两者的性能测试结果Protobuf优于JSON。 这个之前文章《Protobuf与JSON的优劣-用数据说话》中的JSON与Protobuf的性能对比一致。
3. JSON和Protobuf的优缺点
- JSON有点在于对开发者友好,而Protobuf的有点在于序列化的时间以及相同的数据JSON的空间比Protobuf大。这就导致Protobuf在网络传输更加具有优势
- Protobuf的劣势在于,需要定义一个proto文件,在接收方和发送方都需要同样的一个proto文件然后编译成为对应的平台数据结构。增加了开发的复杂度。同时也增加上手的难度。
对于两者的优缺点能不能尝试把JSON的有点和Protobuf的有点结合起来,取一个折中的办法。取JSON的对开发者的友好和Protobuf的序列化占用空间小的特点。
上面用到的代码地址:github.com/mxsm/spring…
我是蚂蚁背大象,文章对你有帮助点赞关注我,文章有不正确的地方请您斧正留言评论~谢谢