Protobuf和Thrift其实优势不在性能,而在于强类型,或者说接口的一致性。
JSON虽然也可以有Schema,但是用的地方不多。在超大规模的项目上,弱类型或者没有类型是很糟糕的。最典型的例子是前后端类型统一。这也就是为什么JS代码里诸如下面这种模式很不好。
function handleResponse(responseString) {
try {
const response = JSON.parse(responseString);
if (response.fieldA != null) {
// do something with field A }
} catch (error) {
// ... }
}
因为没法保证response里一定有fieldA,并且fieldA的类型和预期的一致。即便用TypeScript, 也只能在编译期间保证客户端代码本身的类型一致,但是无法保证和服务端保持一致。一种解决方法是,所有RESTful API都要在后端写好类型定义,并且通过工具自动生成前端的代码的类型定义(TypeScript或者Flow),然后前端就可以直接用。
当然,因为HTTP协议本身是文本协议,所以在HTTP协议上面用Protobuf就不太合适了。但是如果是一个C++服务和一个Python的客户端之间通讯,直接走TCP协议,那么Protobuf就是一个不错的选择。又或者传输的数据本身包含二进制的内容,用JSON得先用Base64等编码,再来压缩的话,性能就比Protobuf差了。
还有一些答主提到的开发效率/开发体验的问题,那都可以通过工具来解决的。只是小一点的公司可能没有足够的资源投入到提高开发体验上。比如二进制数据不可读,那么只要在调试的框架里加一个解析器就行了。