gRPC 用一条 HTTP/2 连接复用多条流
gRPC 的 HTTP/2 传输允许多个 RPC 尝试共享一条连接,同时保留每条流内部的消息顺序。这对短调用和长时间交换都可能有用,但并不意味着每个调用获得了一条无限且完全独立的传输通道。带宽、TCP 交付、连接级流控以及实现中的资源仍然共享,理解这些边界才能准确判断哪些阻塞能够隔离,哪些会影响其他调用。 让调用形式匹配实际工作 一次基于 HTTP/2 的 RPC 尝试占用一条流;重试会发起另一次尝试,而不是把字节重新写入已经结束的流。复用连接能够摊薄建连和 TLS 的成本,但一个 channel 可以管理多条连接,访问不同后端也不会自动共用同一个 TCP 端点。每次调用仍然包含序列化、元数据、帧处理、调度和业务工作,不能把额外成本说成只剩几个帧头。 gRPC 提供单次请求响应、客户端流、服务器流和双向流四类方法。只有双向流允许双方在同一次 RPC 内独立发送消息序列。每个方向的消息顺序得以保留,但不要求每条请求消息都对应一条回复。应当根据应用契约选择调用形式,而不是认为只要采用 gRPC,所有方法就自然具备双向持续推送能力;什么时候读取和写入,仍需应用合理安排。 HTTP/1.1 可以复用持久连接,WebSocket 本身也支持双向消息,二者都不要求每发送一条应用消息就重新握手。因此,不能用虚构的“一次消息一次连接”来证明 gRPC 总是更省。更有意义的比较包括 RPC 契约、生成接口、状态模型和 HTTP/2 多路复用,再结合完整负载和运维约束测量,才能判断实际延迟、内存和连接开销。 分开调用期限与共享传输 截止时间属于某次 RPC,并不会自动成为同一连接上所有流的统一期限。应通过语言支持的上下文机制向下游传递剩余预算;每经过一层就重新领取完整超时,可能让工作持续到调用方早已不愿等待之后。取消还需要业务代码配合停止工作,已经提交的副作用不会因此自动回滚,客户端未收到成功也不等于服务端没有完成修改。 HTTP/2 对 DATA 帧同时实施流级和连接级流控。某条流的窗口耗尽时,只要连接信用仍足够,其他流就可能继续传输。某个方向的连接信用耗尽,会阻止该方向各条流发送非空 DATA;带 END_STREAM 的零长度 DATA 以及控制帧仍可发送。接收端实现可以独立补充连接信用,所以一个慢读者并不必然拖到整条连接都没有额度;应观察真实实现如何管理缓冲和更新。 ...