ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Fluent Bit 依赖的 nghttp2:解析 nghttp2_session_get_next_stream_id 的 HTTP/2 流 ID 分配机制

Fluent Bit 依赖的 nghttp2:解析 nghttp2_session_get_next_stream_id 的 HTTP/2 流 ID 分配机制 Fluent Bit 依赖的 nghttp2解析 nghttp2_session_get_next_stream_id 的 HTTP/2 流 ID 分配机制【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bitFluent Bit 将 nghttp2当前仓库内置版本为 1.65.0位于 lib/nghttp2-1.65.0作为 HTTP/2 客户端库支撑其 HTTPS 输出插件与 HTTP/2 数据发送能力。nghttp2_session_get_next_stream_id是 nghttp2 会话 API 中一个看似简单却关键的低层函数它返回会话下一个即将发出的流 IDoutgoing stream ID是理解 HTTP/2 流编号空间、流 ID 耗尽哨兵值以及 Fluent Bit HTTP/2 客户端如何提交请求的基础。读完本文你将掌握该函数的签名、返回值语义、底层session-next_stream_id字段的初始化与递增规则以及它与nghttp2_submit_request、nghttp2_session_set_next_stream_id的协作关系。函数原型与返回语义该函数的权威文档见 nghttp2_session_get_next_stream_id.rst其原型为#include nghttp2/nghttp2.h uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session);文档对返回值的描述只有两句但信息量很大返回下一个 outgoing本端发出的流 ID——注意是“将要使用”的 ID而不是“最近已使用”的 ID返回类型是uint32_t即无符号 32 位整数当该会话的流 ID 耗尽run out of stream ID时函数返回1 31。这个1 31哨兵值需要从 HTTP/2 协议层面理解按 RFC 9113端点发出的流 ID 使用 31 位有符号整数空间最高位为保留位因此合法流 ID 的最大值为2^31 - 1。nghttp2 内部将流 ID 存储在uint32_t字段中当编号空间用尽、下一个 ID 将越过2^31 - 1时nghttp2 无法再产生新的有效流 ID此时get_next_stream_id统一返回1 31作为“已耗尽”的标识。调用方若据此发起新流nghttp2 会拒绝通常表现为会话必须被终止后重建实践中即需要关闭连接并重新建连。源码实现一个字段读取在 nghttp2_session.c 中该函数的实现极其直接uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) { return session-next_stream_id; }它只是读取nghttp2_session结构体中的next_stream_id字段。因此要完整理解这个函数真正需要关注的是这个字段何时被初始化、何时被推进、能否被外部修改。初始值客户端从 1 开始服务器从 2 开始nghttp2 在创建会话时就根据端点角色设定了起始流 ID。从 nghttp2_session.c 可以看到int nghttp2_session_client_new3(nghttp2_session **session_ptr, ...) { ... /* IDs for use in client */ session-next_stream_id 1; ... } int nghttp2_session_server_new3(nghttp2_session **session_ptr, ...) { ... session-next_stream_id 2; ... }客户端会话的next_stream_id初始化为1最小奇数服务器会话的next_stream_id初始化为2最小偶数。这对应 HTTP/2 协议规定客户端只能使用奇数流 ID服务器只能使用偶数流 ID流 ID 0 保留给连接级根流。Fluent Bit 作为纯 HTTP/2 客户端库消费者其内部会话始终是客户端角色因此其下一个流 ID永远从 1 起步、按奇数递增。外部推进nghttp2_session_set_next_stream_id与 get 成对的是 set 函数用于在连接迁移connection migration、会话状态恢复等场景下告诉会话下一个流 ID 应该是多少。nghttp2.h 中的文档注释明确了两条约束next_stream_id必须大于或等于当前nghttp2_session_get_next_stream_id()的返回值奇偶性必须与端点角色匹配客户端不能设偶数服务器不能设奇数。对应的实现在 nghttp2_session.cint nghttp2_session_set_next_stream_id(nghttp2_session *session, int32_t next_stream_id) { if (next_stream_id 0 || session-next_stream_id (uint32_t)next_stream_id) { return NGHTTP2_ERR_INVALID_ARGUMENT; } if (session-server) { if (next_stream_id % 2) { return NGHTTP2_ERR_INVALID_ARGUMENT; } } else if (next_stream_id % 2 0) { return NGHTTP2_ERR_INVALID_ARGUMENT; } session-next_stream_id (uint32_t)next_stream_id; return 0; }可以看到校验逻辑与文档一一对应非正值、小于当前值、奇偶不匹配都会返回NGHTTP2_ERR_INVALID_ARGUMENT。校验通过后直接覆写next_stream_id字段——这从源码结构上印证了 get/set 是一对围绕同一字段的读写操作。流 ID 如何被消费nghttp2_submit_request 与 Fluent Bitnext_stream_id字段并不是由调用方手动递增的而是由 nghttp2 在每次创建新流新请求时自动分配并推进。典型流程是调用nghttp2_submit_request提交一个请求nghttp2 取出当前next_stream_id作为该流 ID并将内部计数器前移到下一个合法奇数/偶数函数返回值就是新分配的流 ID。Fluent Bit 的 HTTP/2 客户端正是按此模式使用 nghttp2。在 flb_http_client_http2.c 中提交请求并获取流 ID 的核心代码为result nghttp2_submit_request(session-inner_session, NULL, headers, header_count, data_provider, stream); if (result 0) { stream-status HTTP_STREAM_STATUS_ERROR; flb_free(headers); return -5; } stream-id result;这里result即 nghttp2 为本次请求分配的新流 IDFluent Bit 将其保存在stream-id中用于后续数据回调与流状态跟踪。随后调用nghttp2_session_send将 HEADERS/DATA 帧推上网络。结合前述机制可以推断在 Fluent Bit 的一次 HTTP/2 连接生命周期内每提交一个请求session-inner_session的next_stream_id就自动前移 2奇数步进。当连接长期复用、请求量极大理论上最终会逼近2^31 - 1的编号上限此时nghttp2_session_get_next_stream_id将返回1 31nghttp2 拒绝再分配新流 ID正确的恢复方式是关闭该连接并新建会话——这也解释了为什么 HTTP/2 客户端在超长连接上普遍需要连接回收connection recycling策略。对普通日志/指标转发负载而言达到该上限的概率极低但理解哨兵值1 31的语义对排查连接复用很久之后提交请求突然失败这类问题有直接帮助。使用要点小结关注点说明依据函数签名uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session)nghttp2.h返回值下一个将用于本端发出流的流 ID耗尽时返回1 31文档实现直接读取session-next_stream_id字段nghttp2_session.c初始值客户端 1奇数、服务器 2偶数nghttp2_session.c配对 setternghttp2_session_set_next_stream_id要求不小于当前值且奇偶匹配nghttp2_session.c在 Fluent Bit 中的角色流 ID 由nghttp2_submit_request隐式分配Fluent Bit 仅保存返回值flb_http_client_http2.c需要说明的适用前提以上行号与实现细节对应仓库内 vendored 的 nghttp2 1.65.0 源码lib/nghttp2-1.65.0。该 API 的语义在 nghttp2 各版本间保持稳定但若替换库版本建议重新对照版本头文件确认哨兵值与错误码行为。【免费下载链接】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),仅供参考
返回列表