brynet源码阅读——解决文件描述符耗尽问题mIdle

news2024/11/26 11:06:08

1、背景

在高并发服务器程序中,文件描述符资源是有限的。当一个程序同时处理多个网络连接时,每个连接都会占用一个文件描述符。如果系统没有足够的文件描述符可用,调用 accept()(用于接收新的连接)或其他文件操作时可能会失败,导致程序无法继续处理请求。在 Linux 和 macOS 等操作系统中,文件描述符是有限资源,并且每个进程通常只能使用一定数量的文件描述符。如果应用程序的并发连接数接近或者超过了操作系统的文件描述符限制(可以通过 ulimit 设置),系统会返回 EMFILE 错误,表示文件描述符已经用尽。在这种情况下,程序通常需要采取一些策略来优化文件描述符的使用,避免因资源枯竭导致整个系统宕机或无法响应新的请求。

2、mIdle机制

在 Brynet 网络库中,mIdle 作为一个占位符文件描述符,帮助缓解了文件描述符不足的情况。简单来说,mIdle 机制通过释放并占用一个文件描述符槽,提高后续 accept() 调用成功的几率,从而有效降低了由于文件描述符不足导致的连接失败。

class ListenSocket : public brynet::base::NonCopyable
{
public:
    TcpSocket::Ptr accept()
    {
        const auto clientFD = brynet::net::base::Accept(mFD, nullptr, nullptr);
        if (clientFD == BRYNET_INVALID_SOCKET)
        {
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN || defined BRYNET_PLATFORM_FREEBSD
            if (BRYNET_ERRNO == EMFILE) // 这个错误表示文件描述符被耗尽
            {
                // Thanks libev and muduo.
                // Read the section named "The special problem of
                // accept()ing when you can't" in libev's doc.
                // By Marc Lehmann, author of libev.
                /*
                mIdle.reset() 会释放掉 mIdle 占用的文件描述符槽,
                从而让系统“腾出”一些空间,以便后续的 accept() 可以成功接收新的连接。
                */
                mIdle.reset();
                TcpSocket::Create(brynet::net::base::Accept(mFD, nullptr, nullptr), true);
                // 再次尝试获取一个文件描述符,这里个人理解是打了一个时间差,如果其它的地方有释放,这里就会成功
                mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
            }
#endif 
            // 这里个人认为写的不是很好,如果上面accept成功了,是不是可以考虑不抛出error呢
            if (BRYNET_ERRNO == EINTR)
            {
                throw EintrError();
            }
            else
            {
                throw AcceptError(BRYNET_ERRNO);
            }
        }

        return TcpSocket::Create(clientFD, true);
    }

protected:
    explicit ListenSocket(BrynetSocketFD fd)
        : mFD(fd)
    {
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN || defined BRYNET_PLATFORM_FREEBSD
        mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
#endif
    }

    virtual ~ListenSocket()
    {
        brynet::net::base::SocketClose(mFD);
    }

private:
    const BrynetSocketFD mFD;
    /*
    mIdle 是一个占用文件描述符的套接字,
    但它并不用于处理实际的连接或数据传输,
    而是通过打开 /dev/null 文件来占用一个文件描述符。
    /dev/null 是一个特殊的设备,它不做任何 I/O 操作,写入的数据会被丢弃,读取会立即返回 EOF。
    */
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN || defined BRYNET_PLATFORM_FREEBSD
    brynet::net::TcpSocket::Ptr mIdle;
#endif
};

3、mIdle机制的优势

  • 缓解文件描述符不足问题,当系统文件描述符池接近耗尽时,mIdle 机制通过释放占用的文件描述符并重新分配,提高了文件描述符池的流动性。这种策略能显著减少因文件描述符枯竭导致的 accept() 失败,提升高并发场景下程序的稳定性。
  • 无需额外的资源开销,mIdle 机制通过使用 /dev/null 文件作为占位符,不涉及任何实际的 I/O 操作。因此,它不会带来额外的性能开销,也不会对系统资源产生负担。它仅通过占用一个文件描述符槽来实现文件描述符的释放与占用,从而保持系统的高效运行。

4、mIdle机制的局限

虽然 mIdle 机制对文件描述符的管理和高并发连接的处理起到了缓解作用,但它并不能从根本上解决文件描述符耗尽的问题。当文件描述符池完全耗尽时,单纯依赖 mIdle 是无法解决问题的。

  • 文件描述符池的限制是操作系统层面的问题,mIdle 机制只能作为一种缓解策略,而不是根本解决方案。程序仍然需要对文件描述符使用情况进行合理规划,避免无意义的连接占用过多资源。
  • 当系统的负载过高,文件描述符用尽的速度非常快时,mIdle 机制可能会遇到极限,它无法完全阻止 EMFILE 错误的发生。在这种情况下,需要通过增加操作系统的文件描述符限制(如通过 ulimit 调整)来从根本上扩展可用文件描述符数量。

5、总结

mIdle 机制是一个非常巧妙的设计,它通过释放和占用文件描述符来缓解文件描述符不足的问题,尤其适用于高并发场景。它通过合理管理文件描述符,提高了 accept() 操作的成功率,进而增强了程序的并发处理能力。然而,mIdle 并非解决文件描述符不足的根本方法,它更多的是一种优化策略,在并发负载较大时发挥作用。要想彻底解决文件描述符枯竭的问题,仍然需要通过系统配置和程序层面的优化来拓宽文件描述符的使用空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2247803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024智能机器人与自动控制国际学术会议 (IRAC 2024)

主办,承办,支持单位 会议官网 www.icirac.org 大会时间:2024年11月29-12月1日 大会简介 2024智能机器人与自动控制国际学术会议 (IRAC 2024)由华南理工大学主办,会议将于2024年11月29日-12月1日在中国广…

Linux网络——NAT/代理服务器

一.NAT技术 1.NAT IP转换 之前我们讨论了, IPv4 协议中, IP 地址数量不充足的问题,NAT 技术就是当前解决 IP 地址不够用的主要手段, 是路由器的一个重要功能。 NAT 能够将私有 IP 对外通信时转为全局 IP. 也就是一种将私有 IP 和全局IP 相互转化的技术方法: 很…

【架构】主流企业架构Zachman、ToGAF、FEA、DoDAF介绍

文章目录 前言一、Zachman架构二、ToGAF架构三、FEA架构四、DoDAF 前言 企业架构(Enterprise Architecture,EA)是指企业在信息技术和业务流程方面的整体设计和规划。 最近接触到“企业架构”这个概念,转念一想必定和我们软件架构…

亚信安全发布《2024年第三季度网络安全威胁报告》

《亚信安全2024年第三季度网络安全威胁报告》的发布旨在从一个全面的视角解析当前的网络安全威胁环境。此报告通过详尽梳理和总结2024年第三季度的网络攻击威胁,目的是提供一个准确和直观的终端威胁感知。帮助用户更好地识别网络安全风险,并采取有效的防…

【c++】模板详解(2)

🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:C 目录 前言 一、非类型模板参数 二、模板的特化 1. 概念 2. 场景举例 3. 函数模板的特化 4. 类模板的特化 全特化 偏特化 1. 部分特化 2. 对参数的…

红队笔记--W1R3S、JARBAS、SickOS、Prime打靶练习记录

W1R3S(思路为主) 信息收集 首先使用nmap探测主机,得到192.168.190.147 接下来扫描端口,可以看到ports文件保存了三种格式 其中.nmap和屏幕输出的一样;xml这种的适合机器 nmap -sT --min-rate 10000 -p- 192.168.190.147 -oA nmapscan/ports…

Qt/C++基于重力模拟的像素点水平堆叠效果

本文将深入解析一个基于 Qt/C 的像素点模拟程序。程序通过 重力作用,将随机分布的像素点下落并水平堆叠,同时支持窗口动态拉伸后重新计算像素点分布。 程序功能概述 随机生成像素点:程序在初始化时随机生成一定数量的像素点,每个…

十一月二十五

双向循环链表 class Node:#显性定义出构造函数def __init__(self,data):self.data data #普通节点的数据域self.next None #保存下一个节点的链接域self.prior None #保存前一个节点饿链接域 class DoubleLinkLoop:def __init__(self, node Node):self.head nodeself.siz…

Python + 深度学习从 0 到 1(00 / 99)

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【深度学习从 0 到 1】谢谢你的支持! ⭐ 什么是深度学习? 人工智能、机器学习与…

UG NX二次开发(C++)-UIStyler-指定平面的对象和参数获取

文章目录 1、前言2、在UG NX中创建平面和一个长方体,3、在UI Styler中创建一个UI界面4、在VS中创建一个工程4.1 创建并添加工程文件4.2 在Update_cb方法中添加选择平面的代码4.3 编译完成并测试效果1、前言 在采用NXOpen C++进行二次开发时,采用Menu/UIStyler是一种很常见的…

C# 命令行运行包

环境:net6 nuget包:Cliwrap 3.6.7 program: 相当于cmd运行命令:nuget search json static async Task Main(string[] args) {var cmd Cli.Wrap("D:\\软件\\Nuget\\nuget.exe").WithArguments(args >args.Add("…

长三角文博会:Adobe国际认证体系推动设计人才评价新标准

2024年11月22日,由上海、江苏、浙江、安徽三省一市党委宣传部共同发起的第五届长三角文化博览会(简称“长三角文博会”)在上海国家会展中心盛大启幕。长三角文博会自2018年起已成功举办多届,已成为展示区域文化产业发展成果、推动…

音视频基础扫盲之视频码率控制策略(CBR、VBR还是ABR)

视频码率控制策略 CBR(Constant Bit Rate)、VBR(Variable Bit Rate)和ABR(Average Bit Rate)是三种常见的比特率控制方式,以视频码率控制为例,视频码率控制策略主要是在保证视频质量…

【C语言】传值调用与传址调用:深度解析与实现

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯什么是传值调用和传址调用?1. 传值调用(Call by Value)2. 传址调用(Call by Reference) 💯传值调…

C++《二叉搜索树》

在初阶数据结构中我学习了树基础的概念以及了解了顺序结构的二叉树——堆和链式结构二叉树该如何实现,那么接下来我们将进一步的学习二叉树,在此会先后学习到二叉搜索树、AVL树、红黑树;通过这些的学习将让我们更易于理解后面set、map、哈希等…

Leetcode647. 回文子串(HOT100)

链接 代码&#xff1a; class Solution { public:int countSubstrings(string s) {int res 0;for(int i 0;i<s.size();i){for(int j i,k i;j>0&&k<s.size();j--,k){if(s[j]!s[k])break;else res;}for(int j i,k i1;j>0&&k<s.size();j--…

ubuntu, 安装部署comfyui,记录2:下载模型GGuf及测试

0.清除工作流 1.安装manager 2024年最新ComfyUI汉化及manager插件安装详解&#xff01;_comfyui-manager-CSDN博客 ComfyUI Manager安装 转到ComfyUI的安装目录ComfyUI/custom_nodes; 使用git拉取ComfyUI Manager&#xff0c;git clone https://github.com/ltdrdata/Comf…

【Y20030006】基于php+mysql的课程学习网站的设计与实现(附源码 配置 文档)

网络购物商城的设计与实现 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 随着互联网的普及和在线教育的兴起&#xff0c;课程学习网站已经成为越来越多人获取知识和提升技能的重要途径。在这样的背景下&#xff0c;开发一个基于Laravel框架的课程学习…

O2O: (BOORL) Bayesian Design Principles for Offline-to-Online RL

ICML 2024 paper code Intro O2O如何避免悲观学习导致sample efficiency较低&#xff0c;亦或者乐观估计导致的performance drop。本文提出贝叶斯准则&#xff0c;指导在线学习过程中的探索和利用。通过构建一个Q值相关的信念分布&#xff0c;agent可以对不同策略的优劣有一个…

Hyper-V配置-cnblog

启用Hyper-V以在 Windows 10上创建虚拟机 &#xff08;1&#xff09;控制面板检查系统要求&#xff1a; 确保您的计算机符合 Hyper-V 的系统要求。通常情况下&#xff0c;您的计算机需要运行 Windows 10 专业版、企业版或教育版&#xff0c;并且具有启用了虚拟化技术的处理器。…