python socket select 错误 Filedescriptor out of range in select 解决方法

本文详细解析了STPClient在高并发环境下遇到的bug——文件描述符超出范围问题。通过深入研究,确定了问题根源在于大量短连接导致的文件描述符数量激增,并提出了两种解决方案:一是调整内核参数,二是采用epoll替换select。

目录

寻找原因

解释现象

解决方法


今天晚上,有同学给我报了一个内部网络协议包 stpclient 的 bug,如下:

File "/data/apps/column-web/eggs/snow-3.2.1-py2.7.egg/snow/client.py", line 146, in service
  stp_response = self._client.call(stp_request.argv)
File "/data/apps/column-web/eggs/snow-3.2.1-py2.7.egg/snow/client.py", line 51, in call
  self.send_request(request)
File "/data/apps/column-web/eggs/stpclient2-0.0.15-py2.7.egg/stpclient2/client.py", line 221, in send_request
  self._timeout)
ValueError: filedescriptor out of range in select()

这个异常已经发生过好几次了,所以我决定弄清楚原因。

寻找原因

首先,坊间流传的版本是,当 select 中监听的 fd 个数超过 1024 的时候,就会出现这个异常,我分析了一下,这个异常是 stp 的客户端抛出的,因为这个版本的客户端是我写的,所以我清楚的知道,不可能有超过1024个fd,同时被 select,那么问题就来了,到底是因为啥呢?

这个时候,能想到的问题就是,肯定就是坊间的版本有问题,于是首先我看了一下,select 系统调用中的说明,如下:

An fd_set is a fixed size buffer. Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal to or larger than FD_SETSIZE will result in undefined behavior. Moreover, POSIX requires fd to be a valid file descriptor.

select 的 notes 中写到:

fd_set 是一个固定大小的 buffer,当设置的 fd 为负或者是超过 FD_SETSIZE 的时候,就会产生 undefined behavior,POSIX 要求 fd 是一个合法的 fd

从这面来看,和坊间的传闻是有差别的,并不是同时监听的 fd 超过 FD_SETSIZE 就会有问题,而是 fd 大小超过 FD_SETSIZE 就会有问题,FD_SETSIZE 是定义在 select.h 中的,大小为1024(出问题的机器上),所以应该是 fd 大小超过 1024 就会有问题.

/usr/include/linux/posix_types.h

#undef __FD_SETSIZE
#define __FD_SETSIZE 1024

但是,到这里,并没有知道我们看到的那行异常是怎么抛出来的

ValueError: filedescriptor out of range in select()

明显,这是 python 抛出来的异常,系统调用只是说会产生 undefined behavior 而已。

这个时候,顺着 python 的 socket 模块,找到了 select 模块 的 python 源代码,我们发现了如下几行:

Modules/selectmodule.c

#if defined(_MSC_VER)
    max = 0; /* not used for Win32 */
#else /* !_MSC_VER */
    if (!_PyIsSelectable_fd(v)) {
        PyErr_SetString(PyExc_ValueError,
            "filedescriptor out of range in select()");
        goto finally;
    }
    if (v >= max)
        max = v;
#endif /* _MSC_VER */

然后我们发现,当调用 _PyIsSelectable_fd 返回 false 的时候,会产生我们上面的那个异常,接下来我们看一下 _PyIsSelectable_fd 的实现:

Include/fileobject.h

#ifdef HAVE_SELECT
    #define _PyIsSelectable_fd(FD) (((FD) >= 0) && ((FD) < FD_SETSIZE))
#else
    #define _PyIsSelectable_fd(FD) (1)
#endif /* HAVE_SELECT */

因为 POSIX 里面仅仅规定了 select 系统调用传入的 fd 需要合法,那就需要调用方检测 fd,所以在 python 里面,当 fd 为负,或者是超过 FD_SERSIZE 就会被当做不合法,抛出 ValueError

那么现在问题明确了,肯定是因为执行 select 调用的时候,传入了大于 1024 或者是小于 0 的fd,导致了上面异常的出现,接下来的问题就是需要找到为啥会出现大于1024的 fd 了

解释现象

通过基础架构的同学了解到,我们对于进程最大能开启的进程数做了调整,supervisor 里面每个进程最大能开启的 fd 个数是 655360,所以完全有可能出现 fd 超出 1024 的情况.
这个异常是出现在 web 机器上,因为一部分 zone 的服务使用了短链接,所以会导致单进程拥有的 fd 个数很高,超过 1024.

至此,这个问题算是得到了一个合理的解释,因为大量使用短链接,所以导致单进程的 fd 个数升高,超出了 1024 限制,出现了最开始的异常

解决方法

  • 因为这个值是定义在内核里面,所以如果在维持目前方案不变的前提下,解决这个问题就需要重新编译 Linux-kernel,将这个值提高
  • 修改 stpclient 的客户端,使用epoll,代替比较老旧的 select,当时使用 select 的原因是,fd 个数很少,性能上没有问题,同时 select 在其他平台上也可以得到支持

 

 

内容概要:本文针对高渗透率分布式光伏与储能变流器接入配电网所带来的运行挑战,深入研究了传统跟网型(GFL)逆变器在电网故障、弱电网及孤岛工况下易失稳脱网,以及构网型(GFM)虚拟同步发电机(VSG)逆变器在并网状态下缺乏同步调节能力的技术瓶颈,提出了一种可实现GFL与GFM双向平滑切换的先进控制策略。研究首先构建了GFL与GFM共用的硬件平台与内环控制基础,继而系统性地设计了基于关键电气量实时监测的切换判据、精确的双向切换时序逻辑,并创新性地引入了过渡过程的平滑抑制策略,以有效抑制切换瞬间的有功功率冲击、电压闪变与频率突变。全文在Matlab/Simulink环境中搭建了完整的仿真模型,通过对并网转孤岛、孤岛转并网等多种工况的动态仿真,全面验证了所提策略的有效性,结果表明该方法能确保系统在模式切换过程中电压、电流与频率的平稳过渡,显著提升了微电网在复杂运行条件下的韧性、稳定性与供电可靠性。; 适合人群:从事电力电子、新能源并网、微电网控制、智能配电网等领域的高校研究生、科研院所研究人员及电力系统相关企业的工程技术人员。; 使用场景及目标:① 解决高比例可再生能源接入引发的电网稳定性与电能质量问题;② 实现微电网在并网与孤岛两种运行模式间的无缝、可靠切换,保障重要负荷的不间断供电;③ 为构网型与跟网型逆变器的协同运行、新型电力系统构建提供先进的控制理论依据与可落地的技术解决方案。; 阅读建议:建议结合文中提供的Simulink仿真模型进行深入学习,重点剖析切换逻辑模块的设计原理与参数整定方法,通过反复观察和分析不同工况下的仿真波形,深刻理解平滑切换过程中的动态响应机理与控制思想。
内容概要:本文提出了一种基于粒子群算法(PSO)优化模糊C均值(FCM)聚类的居民用电行为分析方法,旨在解决传统FCM算法对初始聚类中心敏感、易陷入局部最优解的问题。通过引入PSO算法全局寻优能力,优化FCM的初始聚类中心选择,显著提升了聚类结果的准确性与稳定性。研究结合Matlab平台实现了算法仿真与实证分析,有效挖掘出居民用电负荷的典型模式,为电力系统的需求侧管理、精细化负荷预测及个性化用电服务提供了可靠的数据分析基础和技术支撑。; 适合人群:具备一定电力系统基础知识与Matlab编程能力,从事电力大数据分析、智能电网、负荷特性研究、需求响应等相关领域的科研人员、高校研究生及工程技术开发者。; 使用场景及目标:①应用于居民用电数据的聚类分析,识别不同用户的典型用电模式与行为特征;②优化传统FCM算法性能,提升聚类过程的鲁棒性与收敛效率;③为电力公司制定差异化电价策略、实施精准需求响应措施以及开展用户画像构建提供科学依据。; 阅读建议:读者应结合Matlab代码实现部分,深入理解PSO优化FCM的整体流程,重点关注适应度函数的设计原则、PSO关键参数(如惯性权重、学习因子)的设定及其对聚类效果的影响,并建议使用真实的居民用电数据集进行实验验证与参数调优,以充分掌握该方法的实际应用技巧。
内容概要:本文系统研究了可切换构网型(Grid-Forming)与跟网型(Grid-Following)逆变器在微电网运行中的双向平滑切换控制策略,旨在解决孤岛与并网模式切换过程中常见的频率、电压突变问题,提升系统稳定性与电能质量。研究融合事件触发机制与分布式协同控制理论,设计了高效的二次频率与电压恢复控制策略,并通过Simulink搭建完整的微电网仿真模型进行验证。文中还深入探讨了通信优化、抗DoS攻击的弹性控制机制等关键技术,体现了对现代智能微电网在高可靠性、高灵活性运行方面的综合控制需求,适用于IEEE/SCI高水平期刊研究成果的复现与拓展。; 适合人群:具备电力电子、自动控制或微电网相关专业知识,从事新能源发电、智能电网、分布式能源系统等方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 深入理解构网型与跟网型逆变器的工作原理及其模式切换的技术难点;② 掌握基于事件触发与分布式协同的微电网二次控制策略设计方法;③ 在Simulink环境中实现微电网多运行模式的建模与仿真,支撑学术论文复现、科研课题推进或实际工程项目开发; 阅读建议:建议结合文中提及的IEEE/SCI顶刊复现案例,循序渐进地学习控制策略的设计逻辑与仿真实现细节,重点关注模式切换的触发条件设定、控制器参数整定及系统稳定性分析,同时可利用提供的网盘资源获取完整仿真模型与代码,以加快学习与研究进程。
内容概要:本文提出了一种融合元胞自动机邻域驱动遗传算法与关键工序定向随机重启爬山算法(GA-RRHC)的混合优化方法,用于求解高柔性柔性作业车间调度问题(FJSSP),以实现最小化最大完工时间的目标。该算法通过元胞自动机构建动态邻域结构,增强种群多样性与搜索效率,结合遗传算法的全局探索能力和随机重启爬山算法的局部精细化优化能力,并引入关键路径识别机制指导搜索方向,有效避免陷入局部最优。整个方法在Matlab平台上实现了完整的算法流程与仿真实验,验证了其在复杂调度场景下的优越性能与鲁棒性,适用于高柔性制造系统的生产调度优化需求。; 适合人群:具备一定编程基础和运筹优化背景,从事智能制造、工业工程、自动化或相关领域研究的研发人员及研究生(工作或学习年限1-3年)。; 使用场景及目标:①解决高柔性作业车间中多工序、多设备、多约束条件下的调度优化难题;②研究混合智能优化算法的设计与实现机制,特别是遗传算法与局部搜索策略的融合方式;③为实际生产系统提供高效的调度方案,缩短生产周期,提高资源利用率。; 阅读建议:此资源以Matlab代码为核心载体,强调算法实现与仿真实验的结合,建议读者在阅读过程中动手运行并调试代码,深入理解元胞邻域构造、关键路径识别及随机重启机制的作用,同时可拓展应用于其他组合优化问题。
内容概要:本文针对孤岛微电网在遭受DoS(拒绝服务)攻击情况下的控制挑战,提出了一种混合动态事件触发的分布式二次弹性协同控制策略。该策略结合分层控制架构与事件触发机制,有效应对网络攻击导致的通信中断与延迟问题,在保证系统频率和电压稳定的同时,提升了微电网的鲁棒性与弹性。通过Simulink搭建多机协同仿真模型,验证了所提方法在恢复系统二次控制性能方面的有效性,尤其适用于高比例清洁能源接入的复杂微电网环境。研究涵盖控制器设计、事件触发条件优化及系统稳定性分析,实现了对频率与电压偏差的精确补偿。; 适合人群:从事电力系统自动化、微电网控制、网络安全与能源互联网研究的研究生、科研人员及工程技术人员,具备一定的控制理论与仿真基础者更佳。; 使用场景及目标:①研究微电网在网络安全威胁下的韧性控制解决方案;②掌握事件触发机制在分布式控制中的应用;③实现孤岛微电网频率与电压的二次协同恢复控制;④为SCI级别论文复现与创新提供仿真技术支持。; 阅读建议:此资源以Simulink仿真实现为核心,建议读者结合提供的完整代码与模型进行逐步调试与参数优化,深入理解事件触发机制与分布式控制算法的设计逻辑,并尝试在不同攻击场景下测试控制策略的鲁棒性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值