Fluent Bit 内置 nghttp2 流半关闭状态查询 API nghttp2_session_get_stream_local_close 解析【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit本文以 Fluent Bit 源码树中内置的 nghttp2 1.65.0 子模块为对象深入讲解nghttp2_session_get_stream_local_close()这一 API 的函数签名、三态返回值语义以及它在 HTTP/2 流状态机中如何由shut_flags位标志位驱动。读完本文你将理解 HTTP/2 中half close半关闭概念的底层实现机制并知道在 Fluent Bit 的 HTTP/2 客户端src/flb_http_client_http2.c中如何使用这套接口管理请求流的结束阶段。1. 函数原型与返回值语义API 文档见 nghttp2_session_get_stream_local_close.rst其内容非常精炼#include nghttp2/nghttp2.h int nghttp2_session_get_stream_local_close(nghttp2_session *session, int32_t stream_id);Returns 1 if local peer half closed the given streamstream_id. Returns 0 if it did not. Returns -1 if no such stream exists.即三态返回值返回值含义1本地端本进程所在的 endpoint已将该流单向半关闭即本端不再向该流写入数据0该流存在但本地端尚未半关闭-1不存在stream_id对应的流流已被完全关闭并从 session 中移除或 ID 非法头文件中的注释与文档保持一致见 nghttp2.h。与它成对存在的是nghttp2_session_get_stream_remote_close()查询远端是否半关闭两者共同构成对 HTTP/2 流双向关闭状态的完整视图。需要强调local peer这个措辞它指的是当前进程所属的一端而不是客户端。nghttp2 是同时支持 client 和 server 会话的库因此这里的 local 是相对于当前nghttp2_session实例而言的——在 Fluent Bit 的 HTTP/2 客户端场景里local 就是 Fluent Bit 自己。2. 实现剖析shut_flags 位标志实现位于 nghttp2_session.cint nghttp2_session_get_stream_local_close(nghttp2_session *session, int32_t stream_id) { nghttp2_stream *stream; stream nghttp2_session_get_stream(session, stream_id); if (!stream) { return -1; } return (stream-shut_flags NGHTTP2_SHUT_WR) ! 0; }逻辑分两步通过nghttp2_session_get_stream()按stream_id查找流对象查不到流已销毁或 ID 不存在直接返回-1检查流上的shut_flags字段中NGHTTP2_SHUT_WR位是否被置位置位返回 1否则返回 0。注意这里的对应关系local close 检查的是NGHTTP2_SHUT_WR写方向关闭——本地端half close意味着本地端声明自己不再写入即写方向 shutdownremote close 检查的是NGHTTP2_SHUT_RD读方向关闭见同文件 L7597-L7608。相关常量定义在 nghttp2_stream.hNGHTTP2_SHUT_NONE 0x00, NGHTTP2_SHUT_RD 0x01, NGHTTP2_SHUT_WR 0x02, NGHTTP2_SHUT_RDWR NGHTTP2_SHUT_RD | NGHTTP2_SHUT_WRshut_flags是nghttp2_stream结构体中的一个uint8_t字段见 nghttp2_stream.h L193。位操作由 nghttp2_stream.c 中的nghttp2_stream_shutdown(stream, flag)完成——它只做一次按位或stream-shut_flags | flag并在两个方向都关闭时触发流的最终销毁可参考 nghttp2_stream.c L163-L176 中对双向均关闭的判定。3. shut_flags 在 HTTP/2 状态机中的语义理解这个 API 的关键是理解 RFC 7540 的流状态机HTTP/2 流不是一刀切地关闭而是每个方向独立关闭两个方向都关闭后流才进入 Closed 状态并释放资源。nghttp2 正是用两个独立的 shutdown 位来映射这四个状态状态SHUT_RDSHUT_WR典型触发场景Open00正常收发中的流本地半关闭local close01本端发送 END_STREAM 后不再写远端半关闭remote close10收到对端 END_STREAM不再收到数据完全关闭11shut_flags NGHTTP2_SHUT_RDWR NGHTTP2_SHUT_RDWR流将被移除从源码结构看NGHTTP2_SHUT_RD位通常在收到对端 END_STREAM 帧时被置位例如 nghttp2_session.c L3623 等收到 RST_STREAM / END_STREAM 路径而NGHTTP2_SHUT_WR位在本端提交请求时即带 END_STREAM 标志、或流被本地关闭时置位如 L2498、L2548。一个值得注意的实现细节在流的创建路径nghttp2_session.c L1224-L1249PUSH_PROMISE创建的 reserved 流会立即半关闭一侧——reserved (local)本端已隐式拒绝/预留该流的读方向置NGHTTP2_SHUT_RDreserved (remote)本端永远不会向远端发起的预留流置NGHTTP2_SHUT_WR且不计入并发流上限源码注释指出这是防 DoS 的考虑。因此在 reserved (remote) 状态下调用nghttp2_session_get_stream_local_close()会返回 1——这正符合 API 定义本地端不再写入该流的字面含义也说明该 API 返回的 1 并不总意味着请求已完成而只是写方向已关闭。HTTP/2 Upgrade 场景nghttp2_session.c L7520-L7528同样印证了这一点client 端 upgrade 后对 stream 1 置NGHTTP2_SHUT_WRserver 端置NGHTTP2_SHUT_RD各自从初始状态就半关闭了一个方向。4. 在 Fluent Bit HTTP/2 客户端中的位置Fluent Bit 内置 nghttp2 作为其 HTTP/2 传输实现客户端封装在 flb_http_client_http2.c。从源码结构看它采用回调驱动的用法通过nghttp2_session_client_new()创建会话L498注册http2_stream_close_callback等一组回调L490在流关闭事件时清理每流的用户数据L319-L326通过nghttp2_submit_request()提交请求L777。Fluent Bit 的封装层主要依赖on_stream_close回调来感知流的最终关闭而不是主动轮询nghttp2_session_get_stream_local_close()但从源码结构可以推断任何基于 nghttp2 自研的 HTTP/2 应用包括扩展 Fluent Bit 的 HTTP/2 下游或调试场景在需要判断我是否还允许向该流发送 DATA/END_STREAM时标准做法就是成对调用int local nghttp2_session_get_stream_local_close(session, stream_id); int remote nghttp2_session_get_stream_remote_close(session, stream_id); if (local -1 || remote -1) { /* 流不存在或已被移除 */ } else if (local 1 remote 1) { /* 双向均已半关闭流已完成生命周期 */ }使用边界提示查询前需确认流仍处于 session 的流表中流被完全销毁后返回-1是正常语义而非错误该函数只做只读查询不改变流状态可安全地穿插在任何帧处理间隙调用判断流是否还能发送数据时应同时考虑流控窗口nghttp2_session_get_stream_remote_window_size()见 nghttp2.h L3891-L3906半关闭只是其中的单向条件。5. 小结nghttp2_session_get_stream_local_close()是 nghttp2 流状态查询接口中最小但最基础的一块它以shut_flags的NGHTTP2_SHUT_WR位为唯一事实来源把 RFC 7540 状态机中的本地写方向关闭映射为三态返回值1/0/-1。在 Fluent Bit 的构建中该 API 随内置子模块 lib/nghttp2-1.65.0 一并提供是理解 Fluent Bit HTTP/2 传输层流生命周期管理的底层依据之一配合nghttp2_session_get_stream_remote_close()即可完整还原任意流在状态机中的位置。【免费下载链接】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),仅供参考