拓冰建站拓冰建站
首页 / 资讯中心 / 正文

解析 nghttp2_session_get_hd_deflate_dynamic_table_size:从 fluent-bit 的 nghttp2 依赖看 HPACK 动态表大小查询 API

解析 nghttp2_session_get_hd_deflate_dynamic_table_size从 fluent-bit 的 nghttp2 依赖看 HPACK 动态表大小查询 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 库的一个 API 参考页展开讲解nghttp2_session_get_hd_deflate_dynamic_table_size函数的用途、返回值语义特别是 RFC 7541 规定的每条目 32 字节开销并结合本仓库中 vendored 的 nghttp2-1.65.0 源码还原该函数的完整调用链、容量管理逻辑以及它在 fluent-bit HTTP/2 客户端栈中的位置。读完本文你可以准确理解 HPACK 动态表容量的定义方式并能在自定义 HTTP/2 客户端中正确查询与监控 deflater 侧的动态表状态。一、API 概览函数原型与返回语义该 API 的官方文档页位于 nghttp2_session_get_hd_deflate_dynamic_table_size.rst其内容可概括为两部分头文件#include nghttp2/nghttp2.h函数原型与返回值语义size_t nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session);文档对返回值的定义是返回 HPACK deflater压缩侧当前的动态表大小数值中已包含 RFC 7541 所述的每条目 32 字节开销overhead。在 公共头文件 中可以看到与之完全一致的声明及注释/** * function * * Returns the current dynamic table size of HPACK deflater including * the overhead 32 bytes per entry described in RFC 7541. */ NGHTTP2_EXTERN size_t nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session);要点说明作用对象是 deflater不是 inflater。HTTP/2 两端各自维护一份 HPACK 动态表发送方压缩方deflater缓存最近发送过的头接收方解压方inflater缓存最近收到的头。本函数查询的是本端已发送头对应的那份动态表返回值单位是字节且含编码开销。RFC 7541 规定每个动态表条目在内存中除 name/value 数据外还要计入 32 字节的元数据开销索引编码、动态表长度前缀等nghttp2 把这部分开销一并计入返回值因此该数值可直接与动态表容量上限SETTINGS_HEADER_TABLE_SIZE做比较判断表是否接近占满。二、HPACK 动态表大小与每条目 32 字节开销RFC 7541HPACK: HTTP/2 Header Compression为了解决动态表可能占用任意内存的问题定义了统一的内存计量规则每个动态表条目占用的内存 NAME 长度 VALUE 长度 32 字节这 32 字节是条目级的固定开销用于覆盖索引数字前缀、动态表长度前缀等编码字段。nghttp2 在源码中把这个常数直接定义为宏见 nghttp2_hd.h#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE #define NGHTTP2_HD_ENTRY_OVERHEAD 32NGHTTP2_HD_ENTRY_OVERHEAD的 32 正对应文档中including the overhead 32 bytes per entry的说法默认的最大动态表容量则由NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE宏给出取 RFC 规定的默认表容量。理解了这组宏就理解了为什么 API 返回的是含开销的总字节数而不是单纯的 namevalue 字节数——这与 RFC 7541 规定的容量计量口径是一致的。三、源码调用链从 session 到 hd_table_bufsize该函数在 nghttp2_session.c 中的实现只有两行size_t nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session) { return nghttp2_hd_deflate_get_dynamic_table_size(session-hd_deflater); }即nghttp2_session内部持有一个hd_deflater成员本函数只是把查询透传给 HPACK 压缩器模块。继续向下在 nghttp2_hd.c 中size_t nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) { return deflater-ctx.hd_table_bufsize; }hd_table_bufsize是压缩器上下文里维护的当前动态表已用字节数含每条目 32 字节开销它是增量累计得到的从 nghttp2_hd.c 的源码结构看新条目插入前若hd_table_bufsize room hd_table_bufsize_max会先把最老的条目逐出并同步减去其占用room即该条目的 namevalue32 开销条目真正落表后执行context-hd_table_bufsize room。因此本函数的返回值是实时表大小而非表容量上限。若要取上限nghttp2 提供了独立的nghttp2_hd_deflate_get_max_dynamic_table_sizenghttp2_hd.c 返回hd_table_bufsize_max。四、动态表容量的运行时管理动态表上限并非一成不变它受 HTTP/2SETTINGS_HEADER_TABLE_SIZE设置帧驱动。从 nghttp2_hd.c 的实现可以确认以下行为压缩侧deflater在收到对端设置时取本端发起的容量与对端 SETTINGS 通知的容量中的较小者作为新的hd_table_bufsize_max同时用min_hd_table_bufsize_max记录历史最小值——这是为了在后续重发reindex/再同步时能发出一条足够小的SET_TABLE_SIZE指令让对端 inflater 把表缩到双方都能接受的范围解压侧inflater在nghttp2_hd_inflate_set_setting路径中更新settings_hd_table_bufsize_max如果本地表已超出新上限则触发逐出nghttp2_hd.c当已用容量长期超过上限的 3/4 时压缩侧会在下次编码时主动发出EMIT_TABLE_SIZE指令调整对端表容量见 nghttp2_hd.c 附近的逻辑。这意味着nghttp2_session_get_hd_deflate_dynamic_table_size的返回值是随流量波动、随 SETTINGS 协商变化的实时量连接空闲、表被清空时返回 0持续发送大量可缓存头时趋近于当前容量上限。五、成对 APIdeflate 侧与 inflate 侧的对称设计nghttp2 为两个方向各提供了同名不同侧的查询函数便于应用层做内存审计函数查询对象返回nghttp2_session_get_hd_deflate_dynamic_table_size本端压缩器session-hd_deflater已发送头动态表大小含 32B/条目开销nghttp2_session_get_hd_inflate_dynamic_table_size本端解压器session-hd_inflater已接收头动态表大小含 32B/条目开销两者实现对称见 nghttp2_session.csize_t nghttp2_session_get_hd_inflate_dynamic_table_size(nghttp2_session *session) { return nghttp2_hd_inflate_get_dynamic_table_size(session-hd_inflater); }头文件中的注释nghttp2.h对 inflate 侧的描述与本函数完全平行。典型用法是周期性调用这两个函数监控双向动态表的内存占用或在连接池回收前确认表状态。六、该 API 在 fluent-bit HTTP/2 栈中的位置fluent-bit 的 HTTP/2 客户端flb_http_client_http2.c直接构建在 nghttp2 的 session API 之上从源码可以看到它通过nghttp2_session_callbacks_new、nghttp2_session_client_new创建客户端会话并注册 send/frame_recv/stream_close/header 等回调flb_http_client_http2.c。fluent-bit 支持 HTTP/2 的输入与输出插件如对接支持 h2 的 Loki、OpenTelemetry 等后端在传输层都依赖这套 nghttp2 会话机制而每个nghttp2_session内部天然携带上述hd_deflater/hd_inflater动态表状态。从源码结构看fluent-bit 当前自身并未直接调用nghttp2_session_get_hd_deflate_dynamic_table_size在src/下检索不到调用点因此该 API 对本仓库的价值主要体现在它是 nghttp2 会话对象上随取随查的诊断接口任何基于同一套 nghttp2 构建的 fluent-bit 二次开发如自定义输出插件内部自建 h2 连接都可以直接调用它做动态表水位监控理解它的语义有助于排查连接建立后头越来越小、但内存占用不符合预期这类 HPACK 相关问题——因为返回值的口径含 32B/条目开销与SETTINGS_HEADER_TABLE_SIZE的上限是同一计量体系可直接比较。七、小结nghttp2_session_get_hd_deflate_dynamic_table_size返回本端 HPACK 压缩侧动态表的实时已用字节数口径包含 RFC 7541 规定的每条目 32 字节开销因此可与动态表容量上限直接比较其实现链路为nghttp2_session→nghttp2_hd_deflate_get_dynamic_table_size→ 上下文字段hd_table_bufsizenghttp2_hd.c该字段随条目插入累加、随逐出扣减表上限受SETTINGS_HEADER_TABLE_SIZE协商驱动压缩/解压两侧分别维护各自的容量状态nghttp2_hd.c与nghttp2_session_get_hd_inflate_dynamic_table_size成对使用可完整观测一个 h2 会话双向头压缩的内存水位。相关参考文件API 文档页、函数声明、会话层实现、HPACK 容量宏定义、fluent-bit HTTP/2 客户端。【免费下载链接】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),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门