ARTICLE DETAIL

资讯详情

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

Fluent Bit 内嵌 nghttp2:nghttp2_submit_headers() API 深入解析

Fluent Bit 内嵌 nghttp2:nghttp2_submit_headers() API 深入解析 Fluent Bit 内嵌 nghttp2nghttp2_submit_headers() API 深入解析【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bitnghttp2_submit_headers()是 nghttp2 库中提交 HEADERS 帧的核心低层 API。Fluent Bit 在输出端启用 HTTP/2如net.http_version 2的 HTTP 客户端时其内嵌的 nghttp2 1.65.0位于 lib/nghttp2-1.65.0/正是通过这一系列 submit 接口把请求头组装成 HTTP/2 帧序列。读完本文你将掌握该函数的完整签名语义、参数与标志位、伪头字段约束、内存拷贝策略、返回值与错误码体系以及 Fluent Bit HTTP/2 客户端如何在上层封装调用链。函数原型声明位于 lib/nghttp2-1.65.0/lib/includes/nghttp2/nghttp2.h实现在 lib/nghttp2-1.65.0/lib/nghttp2_submit.c#include nghttp2/nghttp2.h int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, void *stream_user_data);它的作用是向会话提交一个 HEADERS 帧。各参数含义如下对应文档 lib/nghttp2-1.65.0/doc/nghttp2_submit_headers.rst参数说明session已初始化的 nghttp2 会话客户端或服务端会话flags帧标志位目前仅支持NGHTTP2_FLAG_END_STREAM值0x01见 nghttp2.hstream_id目标流 ID传-1表示由库分配新的客户端流请求 HEADERS打开新流pri_spec优先级规格当前实现中被忽略源码中有显式(void)pri_spec;nva/nvlen头字段 name/value 数组及其元素个数类型为nghttp2_nvstream_user_data与流关联的用户指针仅当本帧把流从 idle/reserved 状态转为 open 时生效参数语义详解flags 与 CONTINUATION 的透明处理应用层只需关心NGHTTP2_FLAG_END_STREAM0x01设置后该 HEADERS 帧携带 END_STREAM 标志表示流在本帧结束。NGHTTP2_FLAG_END_HEADERS0x04对应用层不可见——库内部处理 CONTINUATION 帧拆分时会在 PUSH_PROMISE 或最后一组 CONTINUATION 帧上正确设置 END_HEADERS。源码印证了这一点nghttp2_submit.c 中入口处先做flags NGHTTP2_FLAG_END_STREAM把非法标志位全部剔除随后在submit_headers_shared()里强制 OR 上NGHTTP2_FLAG_END_HEADERSnghttp2_submit.c。stream_id 的三种取值-1仅客户端会话可用。库把本帧归类为请求NGHTTP2_HCAT_REQUEST从session-next_stream_id取 ID 并使后续 ID 加 2保持客户端流奇数编号成功时返回新分配的流 ID见 nghttp2_submit.c。若next_stream_id已超出INT32_MAX则无可用 ID。0非法返回NGHTTP2_ERR_INVALID_ARGUMENTHTTP/2 规范中 0 是连接级流。正奇数具体值对已存在的流提交 HEADERS响应头、trailer 等归类为NGHTTP2_HCAT_HEADERS成功时返回 0。注意文档中的 warningstream_id -1成功返回的流 ID 只是预分配流尚未打开在nghttp2_before_frame_send_callback对该帧被调用之前不得向该流 ID 提交其他帧。nva伪头字段由应用负责nghttp2_nv是{flags, name, namelen, value, valuelen}五元组。文档明确要求必需的伪头字段:前缀如:method、:scheme、:path、:status必须由应用放入nva且必须排在普通头字段之前函数会拷贝nva中所有 name/value并自动将名称转为小写元素顺序保持不变若某个nghttp2_nv设置了NGHTTP2_NV_FLAG_NO_COPY_NAME0x02/NGHTTP2_NV_FLAG_NO_COPY_VALUE0x04见 nghttp2.h对应部分不拷贝其中NO_COPY_NAME要求应用自行保证名称是小写。对于不拷贝的部分应用必须保证指针引用在nghttp2_on_frame_send_callback或nghttp2_on_frame_not_send_callback被调用之前持续有效。低层定位何时用它何时用替代品文档明确把nghttp2_submit_headers()定位为低层函数——它允许应用直接指定 flags。对常规 HTTP 请求应优先用nghttp2_submit_request2()对 HTTP 响应优先用nghttp2_submit_response2()两者内部同样最终提交 HEADERS 帧。此外nghttp2_submit_trailer()等价于flags NGHTTP2_FLAG_END_STREAM、pri_spec与stream_user_data为 NULL 的nghttp2_submit_headers()见 nghttp2_submit.c 的实现——它正是直接调用submit_headers_shared_nva()复用同一条路径。实现剖析从 submit 到出站队列完整调用链为nghttp2_submit_headers()→submit_headers_shared_nva()→submit_headers_shared()源码在 lib/nghttp2-1.65.0/lib/nghttp2_submit.c参数校验L149-L155stream_id -1且session-server为真 →NGHTTP2_ERR_PROTOstream_id 0且非 -1 →NGHTTP2_ERR_INVALID_ARGUMENT。深拷贝头数组submit_headers_shared_nva()L112-L130通过nghttp2_nv_array_copy()复制nva此后所有权交给nghttp2_frame_headers_init()源码注释nghttp2_frame_headers_init() takes ownership of nva_copyL104失败路径负责释放。分配出站项并初始化 HEADERS 帧nghttp2_mem_malloc()分配nghttp2_outbound_item内存不足返回NGHTTP2_ERR_NOMEMnghttp2_outbound_item_init()初始化stream_user_data存入item-aux_data.headers.stream_user_data。入队nghttp2_session_add_item()将项挂入会话的 outbound 队列此后帧何时真正写包、是否被拆为 CONTINUATION都由nghttp2_session_send()驱动。返回值请求类新流返回新流 ID其余情况返回 0。需要强调submit 只是入队并不发送字节。应用随后调用nghttp2_session_send()才会触发nghttp2_before_frame_send_callback并真正序列化帧。返回值与错误码成功且stream_id -1时返回新分配的流 ID否则成功返回 0。失败返回以下负值错误码常量取值见 nghttp2.h错误码常量值触发条件NGHTTP2_ERR_NOMEM-901内存分配失败NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE-509next_stream_id达到INT32_MAX无可用流 IDNGHTTP2_ERR_INVALID_ARGUMENT-501stream_id为 0NGHTTP2_ERR_DATA_EXIST-529该流的 DATA/HEADERS 已提交且尚未处理完例如流处于 reserved 状态时重复提交NGHTTP2_ERR_PROTO-505stream_id为 -1 但session是服务端会话服务端不能打开新流判断错误码是否致命时可配合nghttp2_is_fatal()辅助函数见 lib/nghttp2-1.65.0/doc/nghttp2_is_fatal.rst。Fluent Bit 中的实际使用模式Fluent Bit 的 HTTP/2 客户端位于 src/flb_http_client_http2.c。从源码结构看它并没有直接调用裸的nghttp2_submit_headers()而是按上文建议采用了更高层的封装在flb_http2_request_submit()中组装nghttp2_nv头数组用户头 HostContent-length并绑定data_provider.read_callback即http2_data_source_read_callback提供请求体然后调用nghttp2_submit_request(session-inner_session, NULL, headers, header_count, data_provider, stream)src/flb_http_client_http2.c。最后一个参数stream_user_data正是stream指针——对应本文参数表中仅当流从 idle 变为 open 时生效的用户指针语义提交后立刻调用nghttp2_session_send()驱动帧发送并把流状态机推进到HTTP_STREAM_STATUS_PROCESSING→HTTP_STREAM_STATUS_RECEIVING_HEADERS会话建立阶段还通过nghttp2_submit_settings()下发 SETTINGS 帧src/flb_http_client_http2.c。这正体现了文档给出的选型指引常规 HTTP 请求走nghttp2_submit_request2()系列nghttp2_submit_headers()则留给需要直接操控 flags 的场景如服务器推送 trailer、自定义扩展头块等。理解这条低层 API 的完整语义有助于阅读 Fluent Bit HTTP/2 路径的调试与二次开发。小结nghttp2_submit_headers()提交的是逻辑 HEADERS 帧入队于 outbound 队列END_HEADERS/CONTINUATION 拆分与 END_STREAM 之外的标志位全部由库接管stream_id -1仅客户端可用且返回新流 ID但该流在nghttp2_before_frame_send_callback触发前不可复用伪头字段由应用负责按序提供名称默认被拷贝并小写化NO_COPY_*标志下生命周期责任转移到应用五个错误码-901/-509/-501/-529/-505分别对应内存、流 ID 耗尽、非法 0、重复提交与服务端误用可直接用于错误处理分支Fluent Bit 在实际请求路径上选择nghttp2_submit_request()stream_user_data回调的组合与该 API 文档的低层/高层定位一致。【免费下载链接】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),仅供参考
返回列表