Fluent Bit 内置 nghttp2:nghttp2_session_terminate_session2() 主动终止 HTTP/2 连接的原理与实现解析

发布时间:2026/9/17 16:45:14

Fluent Bit 内置 nghttp2:nghttp2_session_terminate_session2() 主动终止 HTTP/2 连接的原理与实现解析 Fluent Bit 内置 nghttp2nghttp2_session_terminate_session2() 主动终止 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本文围绕 Fluent Bit 仓库中随库 vendored 的 nghttp2 1.65.0 的 API 文档nghttp2_session_terminate_session2.rst展开。该函数是 HTTP/2 会话的受控终止入口调用方可以精确指定 GOAWAY 帧中的last_stream_id从而告知对端哪些流仍可处理、哪些必须放弃。读完后你将掌握该函数的签名语义、参数约束奇偶性、单调不增、返回值与错误码并能结合 Fluent Bit 仓库中的实际源码理解它内部如何构造 GOAWAY 帧、如何冻结会话状态、以及它对后续帧发送的影响。1. API 概览函数签名与文档定义API 文档位于 lib/nghttp2-1.65.0/doc/nghttp2_session_terminate_session2.rst其 Synopsis 部分给出的原型为#include nghttp2/nghttp2.h int nghttp2_session_terminate_session2(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code);文档对该函数的描述可以归纳为三点核心语义目的向会话发出信号表示连接应当被终止Signals the session so that the connection should be terminated。与nghttp2_session_terminate_session()的区别行为与后者一致但允许应用层显式指定last_stream_id实现对流级的细粒度控制。单调性约束HTTP/2 规范不允许last_stream_id增大。因此实际作为last_stream_id发出的值是传入值与此前已向对端发送过的last_stream_id两者中的较小值。关于参数last_stream_id本身文档明确了身份约束它是对端的流 ID或者为 0。因此若session被初始化为clientlast_stream_id必须是偶数或 0若session被初始化为serverlast_stream_id必须是奇数或 0。返回值语义与文档一致成功返回0失败返回以下负数错误码之一错误码含义NGHTTP2_ERR_NOMEM内存不足Out of memoryNGHTTP2_ERR_INVALID_ARGUMENT传入的last_stream_id非法在仓库中该函数的头文件声明位于 nghttp2.h文档注释与上述.rst文件内容一一对应NGHTTP2_EXTERN int nghttp2_session_terminate_session2(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code);2. 源码实现调用链与 GOAWAY 帧构造2.1 入口nghttp2_session_terminate_session2只是薄封装在 fluent-bit 仓库中的 nghttp2_session.c 中实现仅有两行int nghttp2_session_terminate_session2(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code) { return session_terminate_session(session, last_stream_id, error_code, NULL); }它与相邻的三个姊妹函数nghttp2_session_terminate_session、nghttp2_session_terminate_session_with_reason及无 reason 版本共用同一个静态函数session_terminate_session()区别只在于last_stream_id的来源不带2后缀的版本使用session-last_proc_stream_id会话记录的最后处理流 ID而terminate_session2把决定权交给调用者。2.2 核心逻辑静态函数session_terminate_session静态实现位于 nghttp2_session.c 第 223-249 行执行顺序为幂等检查若session-goaway_flags已含NGHTTP2_GOAWAY_TERM_ON_SEND标志直接返回 0——终止 GOAWAY 只提交一次即可重复调用是安全的忽略所有入站帧将session-iframe.state置为NGHTTP2_IB_IGN_ALL。源码注释写明原因Ignore all incoming frames because we are going to tear down the session.既然要拆除会话就忽略所有传入帧提交 GOAWAY调用nghttp2_session_add_goaway(session, last_stream_id, error_code, debug_data, debug_datalen, NGHTTP2_GOAWAY_AUX_TERM_ON_SEND)把终止意图放入出站帧队列打上终止标志session-goaway_flags | NGHTTP2_GOAWAY_TERM_ON_SEND;。2.3 参数校验last_stream_id为什么必须是对端的流 IDnghttp2_session_add_goawaynghttp2_session.c 第 6882-6940 行首先做身份校验if (nghttp2_session_is_my_stream_id(session, last_stream_id)) { return NGHTTP2_ERR_INVALID_ARGUMENT; }即这是本端流 ID时直接返回NGHTTP2_ERR_INVALID_ARGUMENT。而nghttp2_session_is_my_stream_id第 271-282 行的规则是stream_id 0永远不属于本端奇偶性与角色互补——server 端的本端流是偶数 IDclient 端的本端流是奇数 ID。这正好解释了文档中的约束client 会话的last_stream_id必须是偶数或 0server 会话必须是奇数或 0传反了就会落入NGHTTP2_ERR_INVALID_ARGUMENT分支。2.4 单调不增nghttp2_min_int32钳制紧接着nghttp2_session_add_goaway实现了文档所述的取最小值语义第 6919-6922 行/* last_stream_id must not be increased from the value previously sent */ last_stream_id nghttp2_min_int32(last_stream_id, session-local_last_stream_id);session-local_last_stream_id在 GOAWAY 帧真正被打包写出时更新第 2185-2191 行case NGHTTP2_GOAWAY: ... session-local_last_stream_id frame-goaway.last_stream_id;。因此无论应用传入多大的值实际写上线的last_stream_id只减不增严格符合 HTTP/2 规范中GOAWAY 的 last_stream_id 不得递增的要求。此外add_goaway成功后还会置位NGHTTP2_GOAWAY_SUBMITTED表示一条 GOAWAY 已经在出站队列中等待发送。3. 调用之后的会话行为终止状态如何生效terminate_session2成功后会话进入关闭中状态从源码结构看NGHTTP2_GOAWAY_TERM_ON_SEND标志会影响以下几类行为均在 nghttp2_session.c 中会话是否处于关闭态session_is_closing()第 1372-1376 行只要看到NGHTTP2_GOAWAY_TERM_ON_SEND即判定为 closing此时session_predicate_for_stream_send()会对所有流发送返回NGHTTP2_ERR_SESSION_CLOSING不再接收新流session_allow_incoming_new_stream()第 1364-1367 行要求NGHTTP2_GOAWAY_TERM_ON_SEND与NGHTTP2_GOAWAY_SENT均不存在才允许对端发起新流客户端不再发起新请求session_predicate_request_headers_send()第 1424-1437 行在会话关闭时返回NGHTTP2_ERR_START_STREAM_NOT_ALLOWEDPING 也被拦截打包出站 PING 时第 2178-2182 行注释明确 PING frame is allowed to be sent unless termination GOAWAY is sent即终止 GOAWAY 提交后 PING 发送直接失败。需要区分的是这只是信号而非立即断开。函数注释与实现都表明它是Signals the session so that the connection should be terminated——真正的断开由应用层根据nghttp2_session_want_read()/nghttp2_session_want_write()等到帧排空后自行关闭底层传输这也解释了session_is_closing()中want_read 与 want_write 均为 0的另一个关闭条件。4. 在 Fluent Bit 中的位置vendored 依赖与 HTTP/2 集成Fluent Bit 将 nghttp2 1.65.0 完整 vendored 在 lib/nghttp2-1.65.0/ 下用于其 HTTP/2 能力。仓库内两处直接与 nghttp2 会话交互的代码HTTP/2 客户端src/flb_http_client_http2.c 中通过nghttp2_submit_settings()第 518 行、nghttp2_submit_request()第 777 行发起请求回调失败时返回NGHTTP2_ERR_CALLBACK_FAILUREHTTP/2 服务端src/http_server/flb_http_server_http2.c 中同样以NGHTTP2_ERR_CALLBACK_FAILURE作为回调错误约定第 481、811 行。从源码结构看Fluent Bit 自身并未直接调用nghttp2_session_terminate_session2但理解该 API 对把握 Fluent Bit 内置 HTTP/2 客户端/服务的连接拆除行为至关重要任何经由 nghttp2 发出的 GOAWAY 终止信号都遵循本文所述的参数校验、单调钳制与状态机语义。若你基于 Fluent Bit 的 HTTP/2 模块做二次开发例如通过fluent-bit.h公共 API 定制下游连接terminate_session2就是带流边界声明的连接终止这一需求对应的底层原语。5. 使用要点与错误排查清单结合文档与源码调用nghttp2_session_terminate_session2时的实践要点要点依据last_stream_id传对端流 ID 或 0client 端传偶数/0server 端传奇数/0文档约束 nghttp2_session_is_my_stream_id校验传错即NGHTTP2_ERR_INVALID_ARGUMENT传入值过大会被静默钳制为与历史 GOAWAY 的最小值不会报错nghttp2_min_int32钳制逻辑重复调用安全已提交则直接返回 0NGHTTP2_GOAWAY_TERM_ON_SEND幂等检查成功后会话进入关闭态不再收新流、不再发新请求、PING 被拦截session_is_closing、session_allow_incoming_new_stream、PING 打包分支成功仅表示 GOAWAY 已排队实际断开仍需应用层驱动读写直至排空Signals the session... 语义 want_read/want_write关闭判定常见排查若调用返回负值优先核对last_stream_id的奇偶性是否与端角色匹配NGHTTP2_ERR_INVALID_ARGUMENT返回NGHTTP2_ERR_NOMEM则说明出站项或 opaque data 分配失败。6. 小结nghttp2_session_terminate_session2是 nghttp2 提供的应用层指定流边界的会话终止 API它在nghttp2_session_terminate_session的基础上允许显式指定last_stream_id并内建了身份校验对端流 ID 或 0、单调不增钳制与历史 GOAWAY 取最小值与幂等保护。在 Fluent Bit 仓库中该 API 的文档、声明与实现分别位于 doc/nghttp2_session_terminate_session2.rst、lib/includes/nghttp2/nghttp2.h 与 lib/nghttp2_session.c三者内容相互印证为 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),仅供参考
延伸阅读

更多相关文章

2026/9/17 16:45:14

wagmi getProof 动作详解:获取账户与存储槽的 Merkle 证明

wagmi getProof 动作详解:获取账户与存储槽的 Merkle 证明 【免费下载链接】wagmi Reactive primitives for Ethereum apps 项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi 本文围绕 wagmi 核心包 wagmi/core 中的 getProof 动作展开,讲…

2026/9/17 16:45:14

MCP协议:让大模型主动提问的交互范式革命

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/17 17:40:20

Excel VBA一键批量生成进度条:条件格式数据条自动化指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/17 17:40:20

MATLAB电力系统潮流计算:牛拉法、雅可比矩阵与前推回代详解

简介:这是一份针对电气工程及其自动化专业学生的课程设计文档,聚焦基于MATLAB的电力系统复杂潮流计算,完整呈现从理论推导到编程实现的全过程。文档围绕牛顿-拉夫逊法展开,详细介绍了潮流计算的基本原理、雅可比矩阵构建与迭代求解…

2026/9/17 17:40:20

项目结构可视化实战:用Graph与图嵌入找回AI编码的掌控感

写在前面:这系列写到这里,已经有四篇聊“Vibe 时代怎么活下来”的内容,这一篇我想认真聊聊一个绝大多数人忽略但迟早要还债的问题——当你面前是一个三个月前、甚至三天前 AI 帮你写出来的大型项目,你真的“知道”这个项目长什么样…

2026/9/17 17:40:20

全域旅游大数据平台:数据要素治理与大模型落地实践

简介:这是一份面向旅游信息化规划者、大数据平台架构师及政府文旅管理者的专题方案演示文档,聚焦如何运用大模型与多维旅游数据要素,如游客、景区、酒店、交通等,推动全域旅游大数据平台升级。内容覆盖行业现状与痛点,…

2026/9/17 17:40:20

IIS配置FTP与WWW服务器:用户隔离、被动模式与防火墙全解析

简介:这是一份Windows 2000网络服务配置实验资料,面向高校计算机网络课程学生和刚接触服务器搭建的IT初学者,系统讲解FTP与WWW服务器的安装、配置和调试方法。资源为1个PDF文档,大小1.34MB,内容以实验报告形式组织&…

2026/9/17 17:35:19

Source Insight 4.0超级配置指南:从安装到代码阅读效率翻倍

如果你搜索过“VSCode有没有类似Source Insight的Relation视图”,那说明你已经踩到了大型代码阅读的痛点:代码能打开,但读不透。Source Insight 4.0这个名字在嵌入式、C/C老工程师圈子里几乎不需要解释,但真正把它用明白、把显示和…

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/17 0:03:13

WiFi密码安全测试:从原理到实战的字典暴力破解指南

1. 写在前面:我为什么要研究WiFi密码这件事先交代一下背景。我身边有不少朋友,家里的WiFi密码常年是"12345678"或者"88888888",问就是"好记"。直到有一次,隔壁邻居蹭网蹭到我家路由器后台都进不去&…

2026/9/17 0:03:13

redis-py服务控制与监控函数实战:从ping到slowlog的巡检指南

我用 redis-py 写了快五年的业务代码,坦白说,真正让我觉得这个客户端“像一个成熟工具箱”的,不是 get/set 那套基本操作,而是它那批专门做服务控制与状态监控的辅助函数。日常开发里,大家把redis.Redis(host..., deco…

2026/9/17 0:03:13

SpringBoot+Vue3实现中小企业设备管理系统开发实践

1. 项目概述与核心价值中小企业设备管理系统是制造业、服务业等领域的基础信息化工具。传统设备管理往往依赖Excel表格或纸质记录,存在数据孤岛、流程混乱、维护成本高等痛点。这套基于Java SpringBootVue3MyBatis的技术方案,通过前后端分离架构实现了设…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码