资讯动态

nghttp2_session_get_remote_window_size 解析:nghttp2 中 HTTP/2 连接级流控窗口查询 API

发布时间:2026/9/17 5:57:24 来源:尧图企业网站定制
nghttp2_session_get_remote_window_size 解析nghttp2 中 HTTP/2 连接级流控窗口查询 API【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit本篇围绕 nghttp2 库的nghttp2_session_get_remote_window_size()API 展开它是查询一条 HTTP/2 连接上“连接级远端窗口大小”的只读接口是理解 nghttp2 流控Flow Control机制的关键入口。读完本篇你将掌握该函数的原型、返回值语义、底层字段session-remote_window_size的完整生命周期初始化、消耗、回补以及它在发送调度和实际服务端代码中如何被使用。函数原型与基本语义该 API 的官方参考文档位于 nghttp2_session_get_remote_window_size.rst其核心内容如下#include nghttp2/nghttp2.h int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session);功能Returns the remote window size for a connection返回该连接的远端窗口大小参数session—— 指向nghttp2_session结构体的指针即当前这条 HTTP/2 会话返回值int32_t类型的连接级远端窗口大小可靠性文档明确说明This function always succeeds该函数永远成功。这里需要澄清一个 HTTP/2 协议的常见混淆点“远端窗口”指对端remote endpoint允许本端发送的流量额度而不是本端允许接收的额度。按 HTTP/2 流控规则发送方在发出受流控的载荷如 DATA 帧前必须同时满足流级窗口和连接级窗口的限制对端会通过WINDOW_UPDATE帧归还额度。因此这个值越大本端可“在途”发送的数据越多。初始值与常量定义nghttp2 中连接级窗口的初始值由常量NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE决定在头文件中的定义为/* lib/includes/nghttp2/nghttp2.h#L237 */ #define NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ((1 16) - 1)即65535 字节与 HTTP/2 协议默认初始窗口一致。会话创建时该值被写入 session 结构体见 nghttp2_session.c#L458(*session_ptr)-remote_window_size NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;实现分析一个“直读字段”的只读函数从 nghttp2_session.c#L7414-L7416 可以看到该函数的实现极为直接int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session) { return session-remote_window_size; }没有任何锁、校验或失败路径——这与文档“永远成功”的描述完全吻合。要理解这个 API 的价值关键是弄清session-remote_window_size字段在源码中被哪些路径修改即它的生命周期1. 消耗发送 DATA 帧时扣减每当向对端发出 DATA 帧连接级与流级窗口同步扣减见 nghttp2_session.c#L2474-L2476session-remote_window_size - (int32_t)frame-hd.length; ... stream-remote_window_size - (int32_t)frame-hd.length;2. 回补收到 WINDOW_UPDATE 时增加当解析到对端发来的WINDOW_UPDATE帧时按目标区分连接级/流级回补见 nghttp2_session.c#L4631-L4635session-remote_window_size frame-window_update.window_size_increment;流级的对应逻辑在同文件稍后位置stream-remote_window_size ...。此外若对端通过SETTINGS_INITIAL_WINDOW_SIZE调整初始窗口也会对窗口值做相应修正这一点在流级窗口的注释中有明确提示见下文。3. 发送调度门槛窗口 0 时阻塞数据发送session-remote_window_size不只是“可查询的统计值”它还是 nghttp2 出站调度的硬性闸门。在获取/弹出下一个待发帧项时只有连接级窗口为正才会从调度器中取出受流控的待发项典型为 DATA 相关载荷见 nghttp2_session.c#L2279-L2281if (session-remote_window_size 0) { return session_sched_get_next_outbound_item(session); } return NULL;同一判断也出现在nghttp2_session_pop_next_ob_item()中nghttp2_session.c#L2313-L2317。也就是说连接级远端窗口耗尽时nghttp2 会主动挂起受流控数据的发送直到 WINDOW_UPDATE 回补窗口。这也是该 API 对流控排障最重要的意义——它直接反映了“本端现在能不能继续发数据”。与流级窗口的关系min(流级, 连接级)nghttp2 对每个窗口都成对提供“连接级”与“流级”查询函数二者缺一不可。头文件注释明确给出了两者关系见 nghttp2.h#L3891-L3906* Returns the remote window size for a given stream |stream_id|. * * This is the amount of flow-controlled payload (e.g., DATA) that the * local endpoint can send without stream level WINDOW_UPDATE. There * is also connection level flow control, so the effective size of * payload that the local endpoint can actually send is * min(nghttp2_session_get_stream_remote_window_size(), * nghttp2_session_get_remote_window_size()).即本端实际可发送的受流控载荷上限为min(nghttp2_session_get_stream_remote_window_size(), nghttp2_session_get_remote_window_size())两者的实现差异也值得注意。流级版本在找不到对应流时返回 -1且会把负值钳制为 0见 nghttp2_session.c#L7400-L7412int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session *session, int32_t stream_id) { nghttp2_stream *stream; stream nghttp2_session_get_stream(session, stream_id); if (stream NULL) { return -1; } /* stream-remote_window_size can be negative when SETTINGS_INITIAL_WINDOW_SIZE is changed. */ return nghttp2_max_int32(0, stream-remote_window_size); }注意源码注释当对端通过SETTINGS_INITIAL_WINDOW_SIZE缩小初始窗口时流级窗口可能出现负值因此查询接口将其钳制为 0。相比之下连接级的nghttp2_session_get_remote_window_size()直接返回原始字段值、不做钳制这与文档“always succeeds”指调用本身不会失败并不矛盾——调用必成功但读到的数值语义需要调用方结合流控状态理解。另外不要把它与“本端接收窗口”系列 API 混淆。同区域的nghttp2_session_get_local_window_size()本端还能接收多少数据实现为local_window_size - recv_window_size见 nghttp2_session.c#L7396-L7398与nghttp2_session_get_effective_local_window_size()见 nghttp2_session.c#L7391-L7394描述的是接收方向的额度方向恰好相反API方向语义nghttp2_session_get_remote_window_size()发送方向对端允许本端发送的连接级额度nghttp2_session_get_stream_remote_window_size()发送方向对端允许本端发送的流级额度nghttp2_session_get_local_window_size()接收方向本端允许对端发送的剩余连接级额度nghttp2_session_get_effective_local_window_size()接收方向本端接收窗口的有效配置值已计入本地nghttp2_submit_window_update()调整实际使用示例判断流控阻塞nghttp2 自带示例服务器中有一个典型用法在on_frame_sent回调里利用该 API 判断某条流是否已被流控阻塞从而决定是否为该流启用写超时见 HttpServer.cc#L1590-L1601} else if (std::min(nghttp2_session_get_stream_remote_window_size( session, frame-hd.stream_id), nghttp2_session_get_remote_window_size(session)) 0) { // If stream is blocked by flow control, enable write timeout. add_stream_read_timeout_if_pending(stream); add_stream_write_timeout(stream); }这正是前述min(流级, 连接级)判断的直接落地两者任一为 0或更小即认为数据发送被流控挂起。这一模式对需要监控 HTTP/2 客户端/服务端吞吐的应用有参考价值——当观察到发送停滞而连接未断时首先应检查这两个窗口值。在 fluent-bit 中的位置在 fluent-bit 仓库中nghttp2 以 vendored 源码形式内置于 lib/nghttp2-1.65.0/支撑其 HTTP/2 客户端见 flb_http_client_http2.c 等文件与使用 HTTP/2 的后端交互。从源码结构看fluent-bit 自身的代码并未直接调用nghttp2_session_get_remote_window_size()连接级与流级窗口的扣减、回补、发送挂起均由 nghttp2 会话内部机制透明处理该 API 更适合作为底层诊断与集成扩展时的观测手段。该 API 文档也是 nghttp2 官方 API 参考的组成部分被收录在文档构建清单 CMakeLists.txt#L101 与 Makefile.am#L149 中。使用建议小结发送前预估发送大块 DATA 前用min(get_stream_remote_window_size(), get_remote_window_size())估算可发额度流控排障发送停滞时优先观察连接级窗口是否为 0并确认对端是否停止发送WINDOW_UPDATE区分方向涉及“本端能收多少”时请改用nghttp2_session_get_local_window_size()系列避免把发送窗口误读为接收窗口数值语义调用本身永不失败但数值语义受对端SETTINGS_INITIAL_WINDOW_SIZE调整影响流级查询接口对负值的钳制处理nghttp2_max_int32(0, ...)是理解这类边界情况的直接依据。【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价