新闻详情

新闻详情

首页 / 资讯中心 / 详情

服务器复习2

发布时间:2026/9/27 8:59:15来源:尧图网络
服务器复习2
Reactor1. 它是什么原理是什么Reactor 是一种事件驱动的并发处理模式。把多个连接的读写事件注册到事件多路复用器由事件循环等待事件就绪再分发给对应的处理函数。这样一个线程就能管理多个连接不需要为每个连接创建一个线程。2.我的项目怎么用它为什么用它我的项目采用主从多 Reactor。Main Reactor 负责接收新连接和管理服务器生命周期新连接按轮询分配给 Worker EventLoop。每条连接建立后固定归属于一个 Worker连接的读写、HTTP 解析、路由回调和关闭都在这个线程中串行执行。3.你的方案有什么不足当前主要代价是事件驱动代码需要维护状态机并认真处理部分读写、对象生命周期和跨线程任务。另一方面Worker 内的耗时回调会拖慢同一个 EventLoop 上的其他连接。如果以后接入耗时计算、同步数据库访问可以把这部分工作交给业务线程池完成后再将结果投递回 owner loop同时处理连接是否已关闭、HTTP pipeline 响应顺序等问题。另外非阻塞 socket 不意味着整条业务路径都不会阻塞。例如文件冷页读取以及当前示例路由中的同步文件操作仍可能占用 Worker。4.遇到什么坑怎么发现和解决将连接操作排进 EventLoop 后任务可能稍后才执行。如果只捕获裸this连接提前销毁就可能发生释放后使用如果其他线程直接修改连接状态还可能与读写回调产生竞争。解决:异步任务捕获shared_ptrConnection保证执行期间对象存活。状态修改回到 owner loop保证线程归属。关闭统一进入ReleaseInLoop通过DISCONNECTED状态保证幂等。回收时移除 Channel清理 socket、定时器和输出资源。非阻塞读取暂时没有数据与对端关闭是两回事。发送也可能只成功一部分如果错误后仍移动输出偏移会破坏缓冲区状态。解决:发送队列清空后撤销EPOLLOUT。否则在 LT 下socket 通常持续可写会反复触发无意义回调形成忙循环。慢客户端接收不及时输出队列不断积压。即使暂停 socket 读事件输入 Buffer 中可能已经有多个完整请求HTTP parser 如果继续循环就仍会产生更多响应。另一个问题是恢复时仅打开EPOLLIN如果内核没有新数据而用户态 Buffer 中还有请求这些请求可能迟迟不被处理。解决:输出积压达到4 MiB HIGH暂停EPOLLIN并用CanProcessInput()停止 parser。积压降到1 MiB LOW恢复读事件异步投递任务继续处理已缓冲的请求。续跑任务合并为至多一个避免重复排队。不从写回调直接递归调用 parser避免业务重入。这里可以提炼成一句话背压必须同时控制内核读取和用户态请求处理恢复时也要主动推进已经读入的数据。连接生命周期1它是什么原理是什么我理解连接生命周期管理的核心是用状态机明确连接当前允许做什么用所有权保证异步访问期间对象有效再通过统一清理路径保证资源及时且只释放一次。2.我的项目里怎么用它为什么用它你的实现可以按“建立—运行—关闭—销毁”讲。① 建立先明确所有权再注册事件。TcpServer::NewConnection()给连接分配所属 EventLoop设置回调并先把连接放入服务器连接表再调用Established()。真正的EstablishedInLoop()在所属线程执行将状态改为CONNECTED开启读事件再调用连接建立回调。HTTP 层在这个回调中创建HttpContext。这样做保证了连接开始接收事件之前服务器已经持有它协议上下文也会在开始处理请求前准备好。② 运行一个连接由一个 EventLoop 负责修改。连接的状态、Channel、定时器和输出队列都交给所属的 owner loop 操作。其他线程调用Send()、Shutdown()时通过DispatchToOwner()投递任务异步任务捕获shared_ptr保证执行期间对象还活着。这里的分工很关键shared_ptr解决“对象还在不在”owner loop 解决“多个线程会不会同时修改连接”。引用计数安全并不代表连接成员天然线程安全。项目也不是完全没有锁跨线程投递入口有短临界区保护“检查是否允许投递任务入队”避免停机过程中向已销毁的 EventLoop 投递。③ 关闭区分排空输出和强制清理。正常Shutdown()的流程是进入 DISCONNECTING → 停止读事件和请求解析 → 尽量发送完已提交的输出 → Release()例如 HTTP 响应决定Connection: close时先提交响应再调用Shutdown()。这样不会因为立刻关闭 socket把仍在用户态输出队列里的响应丢掉。遇到致命读写错误或服务器StopNow()则走强制清理不保证排空输出。这里的Shutdown()是项目自己的关闭流程不能直接等同于系统调用shutdown(fd, SHUT_WR)输出排空也不代表对端应用已经处理了响应。④ 清理统一进入ReleaseInLoop()。它在 owner loop 中完成检查是否已DISCONNECTED避免重复清理关闭新任务投递入口设置终态从 Poller 移除 Channel关闭 socket清除请求 deadline、取消空闲定时器清空输出队列释放队列中的文件 FD归还输出预算执行关闭回调通知主循环从连接表移除连接。最后一个强引用消失才会触发对象析构。关键 I/O 资源和输出资源在关闭阶段释放不等待对象最终析构。顺序输出与 FIFO1.它是什么原理是什么FIFO 是 First In, First Out先进先出入队A - B - C 出队A - B - C网络输出中FIFO 的关键不是“一次 send 完整发送”而是只发送队首数据部分写入后记录offset / remainingEAGAIN时保留队首等待下一次EPOLLOUT队首完全发送后才能pop_front()处理下一个数据段。2. 项目里怎么用为什么用项目中核心实现位于Connection的_output_queue类型是std::listOutputSegment _output_queue;OutputSegment可以是MemorySegment普通响应头、动态响应体FileSegment静态文件通过sendfile发送。HTTP 层的WriteResPonse()会先构造一个ResponseBatchHeader Body或者Header File然后一次性提交到连接的 FIFO 队列。项目通过list::splice()把整批响应追加到队尾保证一个响应要么完整进入队列要么完全不进入队列。写出时HandleWrite()永远只处理_output_queue.front()具体行为是普通内存数据使用非阻塞send文件数据使用sendfile部分写入只推进当前段的offsetEINTR重试当前发送EAGAIN/EWOULDBLOCK保留队首并开启EPOLLOUT当前段发送完成后才出队。例如 Pipeline 请求产生H1, B1, H2, B2即使H1只发出去一部分也不会越过H1去发送B1或H2。使用 FIFO 的原因有三个保证 HTTP 响应和请求顺序一致兼容非阻塞 socket 的部分写入让内存响应和sendfile文件响应共用一套写状态机。另外项目还用_flow_backlog_bytes做背压控制。积压达到 4 MB 时暂停读降到 1 MB 时恢复读防止慢客户端导致输出队列无限增长。慢客户端资源治理1.它是什么原理是什么慢客户端资源治理的核心是识别慢发送请求慢长时间只发送几个字节。接收响应慢服务端send频繁返回EAGAIN。限制资源限制一个连接的输入缓冲、输出内存、排队文件数和输出段数。限制全局连接数和全局输出内存。施加背压或关闭输出积压高时暂停读取避免继续产生响应。请求阶段超时或超过缓冲上限时关闭连接。连接关闭时一次性释放所有队列、fd、计数和 timer。服务端写数据不能假设一次send就能完成。非阻塞 socket 可能出现短写只发送了一部分EINTR需要重试EAGAIN/EWOULDBLOCK对端暂时收不动需要等待EPOLLOUT。因此项目使用一个 FIFOOutputQueue只发送队首保存每个 segment 的offset和remaining。慢读请求则使用绝对 deadline。收到请求首字节时启动 Header 或 Body 阶段的 deadline后续字节不会刷新这个时间从而避免“每隔几百毫秒发一个字节”永久续命。2. 项目里怎么用为什么用对慢写客户端OutputQueue 背压项目把响应统一封装成MemorySegment普通响应数据通过send发送FileSegment静态文件通过sendfile发送两者进入同一个 FIFO 队列保证Header → Body → 下一个响应的顺序。当队列积压达到FLOW_HIGH 4 MiB关闭EPOLLIN暂停读取请求FLOW_LOW 1 MiB重新打开EPOLLIN并异步处理已经进入用户态的 pipeline 请求。代码中明确区分了flow_backlog_bytes和accounted_output_payload_bytesflow_backlog_bytes表示对端还没收走多少数据文件数据也计入accounted_output_payload_bytes表示当前占用多少用户态输出内存文件段不计入。这样设计的原因是如果只关闭EPOLLIN用户态缓冲区里已经存在的 pipeline 请求仍然可能继续被解析继续生成响应。因此项目还在CanProcessInput()和ProcessInputInLoop()中增加了 parser gate真正停止请求处理恢复时通过异步任务继续处理避免从写回调递归进入 HTTP 业务代码。对慢读客户端阶段 deadline 输入上限HTTP 层默认配置是Keep-Alive 空闲超时15 秒Header deadline10 秒Body deadline30 秒单连接输入缓冲上限1 MiB。请求解析过程是收到请求首字节 ↓ 启动 Header 绝对 deadline ↓ Header 完成、Body 未完成 ↓ 切换到 Body 绝对 deadline ↓ 请求完整后取消阶段 deadline恢复 idle timer输入缓冲采用“写入前预检”。如果本次recv会导致缓冲超过上限就不再扩容、不写入并由 HTTP 层返回 413 后关闭连接。对资源本身硬预算和 RAII项目还限制最大连接数4096全局输出 memory payload256 MiB单连接排队文件 fd64单连接输出 segment1024。响应不是逐段提交而是先计算整批成本再一次性预留内存、fd 和 segment 配额。成功后通过list::splice原子提交失败或异常由Reservation自动回滚。连接 teardown 时统一清理从 epoll 移除 Channel关闭 socket清空 OutputQueue归还全局和本地预算UniqueFd自动关闭静态文件 fd取消 timer更新 metrics。为什么要这样做因为项目采用多连接共享的 EventLoop。一个慢客户端如果阻塞发送、无限积压或长期占用 fd可能拖垮同一个 Worker 上的所有正常客户端。RAII 与失败回滚1. RAII 与失败回滚是什么RAII 是 C 的资源管理思想对象构造成功后就拥有资源析构时自动释放资源。资源不仅包括内存也包括文件描述符、锁、定时器、连接和配额。项目中的Socket、UniqueFd、OwnedBuffer都是 RAII 封装Socket析构时自动close(fd)并且只能移动不能复制。UniqueFd独占文件描述符析构时关闭。OwnedBuffer用unique_ptrchar[]持有响应数据。失败回滚是在 RAII 基础上增加“提交状态”先预留资源或配额尝试构造对象、队列节点所有步骤成功后Commit()中途异常、提前返回或状态变化时由析构函数自动释放预留资源。项目中的Reservation就是一个回滚卫士构造后表示配额已经预留Commit()后表示配额正式转移给输出队列如果没有Commit()析构函数调用Release()退回配额移动构造会把回滚责任转移给新对象避免重复释放。它提供的是强异常安全保证要么整批响应提交成功要么队列和配额恢复到提交前状态。2. 项目里怎么用为什么用最典型的场景是 HTTP 响应发送。HTTP 响应由 Header 和 Body/File 组成。项目先构造ResponseBatch然后计算整批响应需要多少内存、文件 FD 和队列段预留本地配额和全局配额构造MemorySegment或FileSegment用一次list::splice把完整批次放入 FIFO调用Reservation::Commit()。如果 Header 构造成功但 Body 构造时抛异常临时list自动析构已构造的MemorySegment自动释放内存FileSegment内部的UniqueFd自动关闭文件Reservation析构退回本地和全局预算输出队列不会出现“只有 Header、没有 Body”的半个响应。HTTP 层正是把 Header 和 Body/File 放进同一个ResponseBatch静态文件也使用同样的所有权转移openat2得到 fd先放进局部UniqueFdfstat失败时自动关闭成功时通过std::move转交给FileSegment最终使用sendfile发送。连接关闭时项目也有统一的显式 teardown移除 Channel关闭 socket取消 timer清空输出队列归还全局输出预算释放文件 FD只允许执行一次。之所以这样设计是因为这个项目有大量非正常路径EAGAIN、EINTR、客户端断开、超时、预算不足、构造异常、服务器停止。如果依赖每条路径手工清理很容易出现 fd 泄漏、配额不归还或半个响应进入队列。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

用 PHP SDK 调用 Claude Message Batches API:异步批量处理与结果收集实战指南 2026/9/27 9:58:24

用 PHP SDK 调用 Claude Message Batches API:异步批量处理与结果收集实战指南

人工智能大模型AI 应用移动开发交互助手 【免费下载链接】rikkahub RikkaHub is an Android APP that supports for multiple LLM providers. 项目地址: https://gitcode.com/gh_mirrors/ri/rikkahub 点击查看 免费下载 导读 本文以 .agents/skills/claude-api/ph…

阅读更多 →
wp-calypso 数据表格组件 Table 详解:语义化 HTML、无障碍支持与 compact 紧凑模式实践 2026/9/27 9:58:17

wp-calypso 数据表格组件 Table 详解:语义化 HTML、无障碍支持与 compact 紧凑模式实践

前端CMS 【免费下载链接】wp-calypso The JavaScript and API powered WordPress.com 项目地址: https://gitcode.com/gh_mirrors/wp/wp-calypso 点击查看 免费下载 Table 是 wp-calypso 中用于展示表格型数据的 React 组件族,由 Table、TableRow、Tabl…

阅读更多 →
Rustls 测试证书体系(test-ca)完全指南:目录结构、证书属性与重新生成方法 2026/9/27 9:58:11

Rustls 测试证书体系(test-ca)完全指南:目录结构、证书属性与重新生成方法

网络安全密码学网络 【免费下载链接】rustls A modern TLS library in Rust 项目地址: https://gitcode.com/gh_mirrors/ru/rustls 点击查看 免费下载 test-ca/ 是 Rustls 仓库中专用的测试证书签发中心,为集成测试预生成了一整套自签名根 CA、二级中间…

阅读更多 →
网络推广方式有哪些推广思路怎么选避开网站被黑挂马坑 2026/9/27 9:58:04

网络推广方式有哪些推广思路怎么选避开网站被黑挂马坑

网络推广方式有哪些推广思路怎么选避开网站被黑挂马坑 网站被黑挂马不知道怎么办?这是很多站长半夜惊醒时的第一反应。屏幕一闪,弹窗满屏,SEO权重瞬间归零,这种崩溃感我见过太多次。很多新手一慌就乱删文件,结果把数据库搞丢,彻底死机。这时候最关键…

阅读更多 →
网站开发要什么专业?3个核心技能避开性能优化坑 2026/9/27 9:58:04

网站开发要什么专业?3个核心技能避开性能优化坑

网站开发要什么专业?3个核心技能避开性能优化坑 域名解析失败、服务器响应慢如蜗牛,这是不少初学者接手项目后的第一反应。很多人以为搞懂代码就行,却忽略了底层架构对 性能优化 的决定性影响。其实, 网站开发要什么专业…

阅读更多 →
网站建设发言材料2026最新:防黑挂马实战指南 2026/9/27 9:57:57

网站建设发言材料2026最新:防黑挂马实战指南

网站建设发言材料2026最新:防黑挂马实战指南 昨晚三点,成都高新区某科技公司老板给我打电话,声音都在抖。他的企业官网首页突然变成了一片乱码,浏览器地址栏跳出红色“不安全”警告,后台被植入了博彩广告。他问我:“我的网站怎么一夜之间被黑了?这…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉