从网络基础说起:TCP的能力与局限
刚开始接触网络编程时我觉得TCP已经足够完美——它能够建立稳定的连接、保证数据可靠传输、处理网络拥塞这似乎就是网络通信的全部需求。但在实际开发中我遇到了一个基础却关键的问题// 发送方连续发送两条独立消息 socket.write(Hello); socket.write(World); // 接收方可能一次收到HelloWorld // 完全无法区分原始的消息边界这一现象常被称作TCP粘包问题但这其实是一种误解。其本质是TCP作为字节流协议的无边界特性TCP只负责可靠地传输字节序列却不关心这些字节应该如何被组织成有意义的业务消息。TCP的三个核心特性面向连接通信前需要通过三次握手建立连接可靠传输通过确认、重传、排序等机制保证数据可靠送达基于字节流数据没有自然边界只是连续的字节序列二进制个人理解TCP就像是一个可靠的物流系统保证把所有的货物字节都按顺序送达但它会把所有货物都装进一条连续的传送带字节流——货物确实都到了但接收方需要自己根据包裹上的信息应用层协议来重新拆分和识别每个独立的包裹。所谓“粘包”其实是一个伪命题。TCP传输的是字节流而非消息包。如何在流中界定消息是应用层协议需要解决的问题。HTTP协议的出现为数据赋予意义面对TCP的局限性应用层协议应运而生。HTTP协议通过在TCP之上定义明确的报文格式解决了消息边界和语义表达的问题。HTTP通过标准的报文结构定义消息边界HTTP/1.1 200 OKContent-Type: application/jsonContent-Length: 48{name: Alice, email: aliceexample.com}关键就在于Content-Length: 48这个头部——它明确告诉接收方消息体的确切长度从而解决了TCP的粘包问题。HTTP协议的主要价值定义消息边界通过Content-Length或chunked编码标识消息范围标准化通信语义GET、POST、PUT、DELETE等标准方法丰富的能力扩展缓存控制、内容协商、状态管理通用兼容性被所有主流平台和语言支持结论TCP解决了可靠传输的问题而HTTP等应用层协议解决了传输什么和如何解析的问题。新的困惑为什么要在HTTP之上再引入RPC随着分布式系统的发展大家都能发现基于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的核心理念透明化的远程调用RPCRemote Procedure Call又叫做远程过程调用其目标就是让远程服务调用对开发者透明。// 理想的RPC调用方式 User user userService.getUser(123); // 而不是处理各种网络通信细节重要概念澄清基于个人理解RPC本身不是具体的协议而是一种调用范式或技术思想。它的核心目标是让程序员能够像调用本地方法那样调用远程服务。但是我们不能说“使用RPC协议”因为RPC本身不是协议。正确的表述方式✅ 我们使用gRPC协议进行RPC调用❌ 我们使用RPC协议因为RPC本身不是协议而gRPC、Thrift、Dubbo等才是具体的协议实现。RPC与HTTP的关系不同维度的技术RPC与HTTP的关系这是最容易产生混淆的地方。通过学习和实践我个人理解为RPC和HTTP根本不在同一个技术层级RPC是一种调用范式对标的是本地方法调用HTTP是一种具体的应用层协议RPC可以通过HTTP实现也可以通过自定义的TCP或UDP协议实现比如gRPC选择基于HTTP/2协议实现而很多早期的RPC框架使用自定义的TCP二进制协议。RPC协议与RPC框架的完整生态RPC协议通信的基础规范协议主要定义三个核心方面消息格式定义消息如何开始、结束头部和体部的结构序列化方式规定数据如何编码和解码传输规则确定通信流程和交互模式RPC框架基于协议的完整解决方案现代RPC框架在基础协议之上提供了企业级的能力核心层实现通信协议本身组件层提供序列化、服务发现、负载均衡等基础组件治理层包含容错、监控、注册中心等运维能力应用层让开发者透明地进行远程方法调用总结协议定义了机器之间如何对话框架让开发者无需关心对话过程而专注业务逻辑。现代架构中的技术选型各司其职的分工通过参与实际项目我逐渐理解了HTTP和RPC在现代架构中的分工原则。针对大部分公司而言基本上都是如此。内部服务调用RPC框架的优势领域在微服务架构内部RPC框架因其性能优势成为首选RPC的高性能主要源于高效的序列化// JSON序列化可读性好但体积大 {id: 123, name: Alice, age: 30} // 约40字节 // Protobuf二进制体积小解析快 \x08\x7B\x12\x05Alice\x18\x1E // 仅11字节 // 体积减少70%以上序列化速度提升明显协议开销优化长连接减少TCP握手开销多路复用提升连接利用率头部压缩减少传输数据量专为性能设计精简的协议头设计二进制编码效率零拷贝等技术应用对外API暴露HTTP协议的不可替代性当需要向外部提供API时HTTP协议展现出其独特价值HTTP的通用性优势无与伦比的生态系统所有平台、语言、设备都支持HTTP成熟的工具链浏览器、Postman、curl等调试工具网络友好性80/443端口普遍开放易于测试调试直接通过浏览器或命令行工具测试// 前端调用HTTP API简单直接 fetch(/api/users/123) .then(response response.json()) .then(user { displayUser(user); });真实世界的架构实践现代互联网公司的典型架构体现了清晰的分层设计这种架构的智慧内外有别对外保证兼容性对内追求性能关注点分离网关处理横切关注点业务服务专注核心逻辑协议转换在网关层完成HTTP到RPC的协议转换