时间:2025-11-24 23:39
人气:
作者:admin
掘金原文(个人技术文章优先在掘金发布):https://juejin.cn/post/7559981310472470562
记得刚工作那会儿,第一次接触RPC概念时,我内心满是疑惑——明明HTTP用得好好的,为什么要搞出个RPC?直到参与了几个微服务项目后,我才真正能理解它们各自的价值。今天,就让我们一起理清这些协议之间的关系。
刚开始接触网络编程时,我觉得TCP已经足够完美——它能够建立稳定的连接、保证数据可靠传输、处理网络拥塞,这似乎就是网络通信的全部需求。
但在实际开发中,我遇到了一个基础却关键的问题:
// 发送方连续发送两条独立消息
socket.write("Hello");
socket.write("World");
// 接收方可能一次收到:"HelloWorld"
// 完全无法区分原始的消息边界
这一现象常被称作TCP粘包问题,但这其实是一种误解。其本质是TCP作为字节流协议的无边界特性:TCP只负责可靠地传输字节序列,却不关心这些字节应该如何被组织成有意义的业务消息。
TCP的三个核心特性:
个人理解: TCP就像是一个可靠的物流系统,保证把所有的货物(字节)都按顺序送达,但它会把所有货物都装进一条连续的传送带(字节流)——货物确实都到了,但接收方需要自己根据包裹上的信息(应用层协议)来重新拆分和识别每个独立的包裹。
所谓“粘包”,其实是一个伪命题。TCP传输的是字节流,而非消息包。如何在流中界定消息,是应用层协议需要解决的问题。
面对TCP的局限性,应用层协议应运而生。HTTP协议通过在TCP之上定义明确的报文格式,解决了消息边界和语义表达的问题。
HTTP通过标准的报文结构定义消息边界:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 48
{"name": "Alice", "email": "alice@example.com"}
关键就在于Content-Length: 48这个头部——它明确告诉接收方消息体的确切长度,从而解决了TCP的粘包问题。
HTTP协议的主要价值:
结论: TCP解决了"可靠传输"的问题,而HTTP等应用层协议解决了"传输什么"和"如何解析"的问题。
随着分布式系统的发展,大家都能发现基于HTTP的服务间调用会存在一些不便:
// 基于HTTP的服务调用需要大量样板代码
HttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost("http://user-service/getUser");
post.setHeader("Content-Type", "application/json");
String jsonBody = "{\"user_id\": 123}";
post.setEntity(new StringEntity(jsonBody));
HttpResponse response = client.execute(post);
if (response.getStatusLine().getStatusCode() == 200) {
String responseBody = EntityUtils.toString(response.getEntity());
User user = objectMapper.readValue(responseBody, User.class);
}
// 太多的底层细节需要处理!
每次调用都需要处理HTTP状态码、异常情况、序列化反序列化等重复工作。这让我们开始思考:能否让远程服务调用像调用本地方法一样简单?
RPC(Remote Procedure Call),又叫做远程过程调用,其目标就是让远程服务调用对开发者透明。
// 理想的RPC调用方式
User user = userService.getUser(123);
// 而不是处理各种网络通信细节
重要概念澄清(基于个人理解):
RPC本身不是具体的协议,而是一种调用范式或技术思想。它的核心目标是让程序员能够像调用本地方法那样调用远程服务。
但是我们不能说“使用RPC协议”,因为RPC本身不是协议。
正确的表述方式:
因为RPC本身不是协议,而gRPC、Thrift、Dubbo等才是具体的协议实现。
RPC与HTTP的关系这是最容易产生混淆的地方。通过学习和实践,我个人理解为:
RPC和HTTP根本不在同一个技术层级:
比如gRPC选择基于HTTP/2协议实现,而很多早期的RPC框架使用自定义的TCP二进制协议。
协议主要定义三个核心方面:
现代RPC框架在基础协议之上提供了企业级的能力:
总结: 协议定义了机器之间如何对话,框架让开发者无需关心对话过程而专注业务逻辑。
通过参与实际项目,我逐渐理解了HTTP和RPC在现代架构中的分工原则。针对大部分公司而言,基本上都是如此。
在微服务架构内部,RPC框架因其性能优势成为首选:
RPC的高性能主要源于:
高效的序列化
// JSON序列化:可读性好但体积大
{"id": 123, "name": "Alice", "age": 30} // 约40字节
// Protobuf二进制:体积小,解析快
\x08\x7B\x12\x05Alice\x18\x1E // 仅11字节
// 体积减少70%以上,序列化速度提升明显
协议开销优化
专为性能设计
当需要向外部提供API时,HTTP协议展现出其独特价值:
HTTP的通用性优势:
// 前端调用HTTP API简单直接
fetch('/api/users/123')
.then(response => response.json())
.then(user => {
displayUser(user);
});
现代互联网公司的典型架构体现了清晰的分层设计:

这种架构的智慧:
针对文章内容,整体总结一下:
技术演进脉络:
现代架构的最佳实践:
公司内部服务调用:优先采用RPC框架(如gRPC、Dubbo)
对外暴露接口:普遍采用HTTP协议(及RESTful风格)
核心结论:
这是一个"内外有别"的最佳实践——性能至上的内部集群采用RPC框架,兼容性优先的对外开放接口采用HTTP协议。
本文内容是作者在学习过程中的个人理解和总结,可能存在不准确或理解有误的地方,欢迎倔友们指正。
当然我也已经练习长达两年半了????,理论上????应该没问题。
文章的最后,想和你多聊两句。
技术之路,常常是热闹与孤独并存。那些深夜的调试、灵光一闪的方案、还有踩坑爬起后的顿悟,如果能有人一起聊聊,该多好。
为此,我建了一个小花园——我的微信公众号「[努力的小郑]」。
这里没有高深莫测的理论堆砌,只有我对后端开发、系统设计和工程实践的持续思考与沉淀。它更像我的数字笔记本,记录着那些值得被记住的解决方案和思维火花。
如果你觉得今天的文章还有一点启发,或者单纯想找一个同行者偶尔聊聊技术、谈谈思考,那么,欢迎你来坐坐。
愿你前行路上,总有代码可写,有梦可追,也有灯火可亲。