记住我这句话,对于追求极致性能的基础设施来说,那些所谓的方便,全是累赘。
我很理解你的想法,TCP 还要自己处理粘包拆包,多麻烦啊,WebSocket 和 HTTP/2 都帮你切好帧了,直接拿来用不香吗?
一、 真有那么麻烦吗?
你觉得处理粘包、拆包、计算长度很麻烦,是由于你站在应用层开发的视角。但在 RPC 框架开发者眼里,这就是10 行代码的事儿。
粘包拆包完全不难啊,定一个协议头 Header,里面放一个 Length 字段。读的时候先读头,拿到长度,再读 Body。Netty 里一个
LengthFieldBasedFrameDecoder 就搞定了。
压缩也不难,拿到 Body 的字节数组,调用一下 Snappy 或 Gzip 压缩,完事。
为了省下这几十行通用的底层代码,去引入 WebSocket 或 HTTP 2 有点得不偿失吧!
二、 WebSocket 烦琐
WebSocket 主要是为浏览器设计的,它的许多机制在服务器内部RPC通信场景下,显得许多余。
Web 环境本身不安全,为了安全浏览器发出的 WebSocket 帧是要进行掩码处理的。服务端收到消息后,又会消耗 CPU 去做一次异或运算解密,才能拿到数据。
那都在内网微服务调用里,大家都是自己人,你防谁呢? 这不纯纯浪费算力嘛。
而且 WebSocket 握手流程也繁琐,建连接前先发一个 HTTP 升级协议的请求,服务器响应 101,才能升级Upgrade。
RPC 的核心设计要求就是快,没有比直接 TCP 三次握手直连效率更快的了。WebSocket 应用主要是解决穿透防火墙和浏览器兼容上,并不太擅长高性能传输。
三、 HTTP2 冗余
gRPC 底层选择 HTTP/2,应该是看中了它的标准化和生态,毕竟谁都认识HTTP。但如果要追求极致吞吐的场景,相比之下 HTTP/2 还是显得冗余。
你发一个HTTP请求,Header 还得带上 method, path 这些伪头。但要弄一个私有 TCP 协议,我就定义一个字节 Magic Number,一个字节 Type,一个 RequestID,剩下的全是数据,没有一个字节是多余的。
四、 可操作性
RPC 框架要对网络层有强的可控性,列如我要准确控制连接的生老病死,心跳检测 KeepAlive 就要自己实现,由于 TCP 层的 KeepAlive 太慢太呆了。
还有缓冲区管理,Netty + TCP 可以做到零拷贝,直接把网卡的 Buffer 指针指来指去,不需要把数据在用户态内存里拷来拷去。如果中间隔了一层 HTTP/2 或 WebSocket 的库,你很难深入到底层去做这种优化。
服务器内部通信场景,WebSocket 给浏览器设计的,有一些没用的安全机制,HTTP 又不够精简,TCP + 私有协议用一点点开发成本换高性能,实则很划算






写的不错的,重点还是性能与流量治理
关键是rpc大部分都是微服务,在调用,根本不会在乎Http这一点点消耗呀,你要做流服务,那你用TCP
rpc不在乎http损耗?如果美团淘宝这种内部那么多微服务调用http浪费大了去了。。小公司无所谓,都不用上这种框架,走内部http调用完事
tcp也不是最好的,三次握手导致效率低下,而流式处理也不适合这种一来一回的调用。更好的是基于udp的定制协议,…那不就是QUIC么?