单个 epoll + 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景?

2023-12-05

本文是回答一位知友的提问:

单个 epoll + 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景?

不少教程上都提到线程池适合大量的网络短连接的任务场景。但我总感觉这个优势有点站不住脚(单 epoll + 线程池模型),主要考虑到两点: 1. 线程池的实现机制使得需要引入锁管理线程调度,这个开销在 per thread per epoll 模型中是不需要的。 2. 大量的短连接导致需要经常对 epoll 进行添加和删除操作,线程池在进行这个任务是是需要对唯一的 epoll 加锁的(可能有方法不需要加,我还不知道),而 per thread per epoll 没有这个问题,这个在速度上线程池应该也是有损失的。 关于上面这两点疑问各位前辈怎么看?感觉线程池没什么好的应用场景。

正文

虽然你在线程池的用途上有些混乱,但是这个问题其实蛮不错的,所以详细说一下希望对有需要的朋友提供一点帮助。

我们来详细讨论一下:

不管是 per thread per epoll 还是一个 epoll+线程池,应该抓住关键点。

我们一步步地梳理一下逻辑哈:首先假设您的侦听socket只有一个,这个侦听 socket 必然要绑定且只能绑定到一个 epoll 上(不管是侦听 socket 还是普通与客户端连接的 socket 同时绑定到多个epoll 上不仅处理起来麻烦,也是非常不好的做法),所以这里可以有且只有一个线程来对应这个 epoll,我们暂且把这个线程叫做线程 A,把这个 epoll 叫做 epollA; 接着 epollA 检测到新客户端请求连接,并接受客户端连接产生客户端 socket,这个 socket 我们叫做 B、C、D 等等(可能有许多)。这些与客户端连接对应的 socket 挂到哪里去?有两种思路:

第一种思路:挂到原来的 epollA 上,这样的话,线程A不仅要接受客户端连接(侦听 socket 上的事件)),还要处理客户端的来的数据(普通客户端端 socket B、C、D 等等),这种当连接数量比较多、来往数据比较多的时候,可能一个线程 A 忙不过来,效率不行。这种结构如下图所示:

Redis 就是这种单线程模型。

第二种思路:将 socket B、C、D 等以某种策略挂到新的 epoll 上,这些新的 epoll 我们暂且称为 epollB、epollC、epollD,当然分别对应线程 B、线程 C、线程 D 等等(具体数量根据你的需求来确定,但不能无限多,一般也就几个),比如轮询策略,即新来一个 socket B,挂到 epollB 上,接着来了 socket C 挂到 epollC 上,又来了 socket D 挂到 epollD 上,再来了 socket E 又挂到 epollB 上。因为产生 socket B、C、D 是在线程 A,而需要挂到 epollB、epollC、epollD 所在的线程上(在各个 epoll 上面移除 socket 同理),这里挂接和移除操作可能需要锁。这就是所谓的 per thread per epoll,或者叫 per thread per loop(一个线程一个循环),这里就是一组线程了,其中每个线程都有一个 epoll,只不过第一个 epoll 只绑定侦听 socket,其他的 epoll 绑定客户端 socket(当然,如果你觉得第一个 epoll 比较闲,也可以在上面绑定一些客户端 socket)。这两种结构如下图所示:

这两种结构是现在大多数服务器的结构。

说到这里咱们再深入一点,每个线程循环的结构如下:

while (!m_bQuit)
{
    //步骤一:使用select或者epoll_wait等IO复用技术检测socket上是否有读写或出错事件
    // 对于第一个循环,只检测侦听socket是否有事件
    epoll_or_select_func();

    //步骤二:检测到某些socket上有事件后处理事件,比如收数据,对于第一个循环可能是
    //接受客户端连接,接收完数据解数据包进行业务逻辑处理
    handle_io_events();

    //步骤三:做一些其他事情
    handle_other_things();
}

这是这个结构的最基本逻辑,在这基础上可以延伸出很多变体,例如:不知道你有没有发现,步骤二中如果解数据包或者业务逻辑处理过程比较耗时(计算密集型),那么会导致 thread 在这个步骤停留时间很长,导致很久以后才能走下一次循环,影响网络数据的检测和收发。所以 handle_io_events() 这个步骤中,我们又可以拆出一部分功能出来,比如将数据解包完后,产生的业务数据再交给另外一批线程(又来一个线程池),这批线程我们叫做业务线程(业务线程具体做什么顾名思义根据你的程序业务来决定),这个过程业务数据从网络线程组(生产者,epoll 线程组)流向业务线程组(消费者)的时候,也要加锁,因为业务线程会不断取出业务数据进行处理。

如果你能清晰明白地看到这里,说明你大致明白了一个不错的服务器框架是怎么回事了。

如果你有兴趣,咱们可以再进一步:

由于 CPU 核数有限,当线程数量超过 CPU 核数时,各个线程(网络线程和业务线程)也不是真正地并行执行,那么即使开了一组业务线程也不一定能真正地并发执行,那么我们不如就在网络线程里面处理。

上文也说了不能在步骤二的 handle_io_events(),但是我们可以放到 handle_other_things() 中处理呀,但是这里有个疑问,我产生了一个业务任务需要 handle_other_things()这个函数立即执行,而循环可能还挂在步骤一的 select 或者 epoll_wait 上,怎么办?没关系,我们可以使用一些"技术"手段立即唤醒他们,比如给 epoll 或者 select 额外绑定一些“功能” socket,Linux 还可以绑定 eventfd 或者 socketpair。当我们网络数据解包后产生业务任务后,只要往这些 socket 或者eventfd 上随便写一个数据,epoll_wait 或 select 因为检测到这些“功能” socket 可读事件就会立刻返回了,接下来的流程就走到 handle_other_things(),对我们的业务任务进行处理了。

特别说明一下:

这种所谓的技巧在handle_other_things()里面不会有耗时的任务的才可以替代专门开业务线程,如果有耗时操作还是老老实实开业务线程吧。

这就是目前主流的网络库的设计思想和基本框架原理,如 libevent 和 muduo。当然这些框架可能在上面的结构上稍微再加点东西,比如定时器,这样程序就变成了:

while (!m_bQuit)
{
    //步骤一:检测是否有定时器到期并处理定时器事件
    check_and_handle_timers(); 

    //步骤二:使用select或者epoll_wait等IO复用技术检测socket上是否有读写或出错事件
    // 对于第一个循环,只检测侦听socket是否有事件
    epoll_or_select_func();

    //步骤三:检测到某些socket上有事件后处理事件,比如收数据,对于第一个循环可能是
    //接受客户端连接,接收完数据解数据包进行业务逻辑处理
    handle_io_events();

    //步骤四:做一些其他事情
    handle_other_things();
}

之所以把定时器放在最前面是为了尽量减少定时器的事件的过期时间间隔。

说了这么多,希望你能理解:

  1. per thread per loop 思想

  2. 何时该用线程池

  3. 这个框架的优点与瓶颈所在

更具体的做法,您可以参考这里:

服务器端编程心得(一)-- 主线程与工作线程的分工

服务器端编程心得(二)-- Reactor模式

服务器端编程心得(三)-- 一个服务器程序的架构介绍

当然,如果您对网络编程或者高性能服务器开发感兴趣,可以关注我的微信公众号『高性能服务器开发』与我进一步沟通交流~

可以从哪里系统地学习到上述知识?

有同学私信问我,你这些知识从哪里学习的呢?

如果你是网络编程零基础或者觉得自己网络编程存在夹生饭问题,推荐看看尹圣雨的《TCP/IP 网络编程》,这本书同时兼顾 Windows 和 Linux 两个平台,使用的是 C 语言和操作系统的 Socket API,通过这本书你能学会常用的操作系统 Socket API 和常用的网络模型,认真学完之后,你不会再纠结同步异步、阻塞非阻塞等概念。

TCP/IP 网络编程

链接: https://pan.baidu.com/s/1ho3e1POq5LzEQWp0Gm2Nsg 提取码: sp8p

接着如果你想编写高性能的网络框架或者高效的服务,推荐游双老师的《Linux 高性能服务器编程》一书。

链接: https://pan.baidu.com/s/1f9IErU5JP2sw-5Crha9vzg 提取码: je7g

这两本书的获取方式可以参见这里:

计算机必看经典书籍(含下载方式)

当然,我自己也出版了一本书《 C++ 服务器开发精髓 》,在这本书凝聚了我从客户端到服务器、从 Windows 到 Linux 的经验总结,你还将从本书中系统地学习到 C++ 开发编译调试完整技术链、多线程编程技术、作者精心凝炼的20多个网络编程重难点知识、网络故障排查与定位知识、如何设计可兼容可扩展的通信协议、如何设计高性能网络框架、如何设计高性能服务框架、如何开发服务常用组件等知识。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单个 epoll + 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景? 的相关文章

  • Android通用流行框架大全,零基础入门学习android

    Picasso transformations 一个为Picasso提供多种图片变换的库 Glide transformations 一个为Glide提供多种图片变换的库 Android gpuimage 基于OpenGL的Android过
  • CodeIgniter(CI)4.1.9 安装学习整理ing

    最近一直在看各种php的框架 前面一个是安装的laravel 安装成功并实验了一个小例子 下面开始试着安装 CodeIgniter 我找了一个不是最新的版本 4 1 9版本 这个版本要求的还是比较高的 要求PHP 7 3 我习惯于用wind
  • 关于springmvc的面试经验分享

    1 什么是 Spring MVC Spring MVC 是一个基于 Java 的实现了 MVC 设计模式的请求驱动类型的轻量级 Web 框架 通过把 Model View Controller 分离 将 web 层进行职责解耦 把复杂的 w
  • 信创-大数据平台CPU架构支持

    一 CDH和HDP CDP CDP数据中心类似于CDH和HDP 直接安装在硬件服务器上 目前支持市面上主流的X86服务器 包括国内海光服务器 CDH不支持ARM 以上两种大数据平台都仅支持x86架构 早在几年期RedHat联手clouder
  • MVC三层架构

    1 什么是MVC Model View Controller 模型 视图 控制器 模型就是Java对应数据库的那些字段 实体类 视图 就是JSP页面 控制器 就是Servlet负责跳转页面 Controller作用 Controller其实
  • API架构的选择,RESTful、GraphQL还是gRPC

    文章目录 一 RESTful 1 什么是RESTful 2 RESTful架构的原则 3 RESTful的适用场景 4 RESTful的优点 5 RESTful的缺点 二 GraphQL 1 什么是GraphQL 2 GraphQL的原则
  • ARM架构学习(二)——流水线

    本期主题 ARM流水线 往期地址 ARMv7架构学习 ARM流水线 1 流水线概念 2 指令的分解步骤 1 流水线概念 硬件资源总是有限的 有一个明显的方法能改善硬件资源的利用率 这就是pipeline 流水线 技术 其实就是在当前指令结束
  • 微服务项目之项目简介

    目录 项目模式 技术栈 项目架构图 模块 主模块 项目模式 电商模式 市面上有5种常见的电商模式 B2B B2C C2B C2C O2O 1 B2B模式 B2B Business to Business 是指 商家与商家建立的商业关系 如
  • 英伟达最新开源

    Title FasterViT Fast Vision Transformers with Hierarchical Attention Paper https arxiv org pdf 2306 06189 pdf Code https
  • RabbitMQ集群架构模式

    搭建Mirror镜像集群 4369是erlang的发现端口 5672是rabbitmq的通信端口 15672是rabbitmq的可视化控制台的端口号 25672是erlang底层发送消息和分配消息的底层端口 firewall cmd zon
  • [架构之路-256]:目标系统 - 设计方法 - 软件工程 - 软件设计 - 架构设计 - 软件系统不同层次的复用与软件系统向越来越复杂的方向聚合

    目录 前言 一 CPU寄存器级的复用 CPU寄存器 二 指令级复用 二进制指令 三 过程级复用 汇编语言 四 函数级复用 C语言 五 对象级复用 C Java Python 六 组件级复用 七 服务级复用 八 微服务级复用 前言 物质世界的
  • GoLong的学习之路,进阶,微服务之序列化协议,Protocol Buffers V3

    这章是接上一章 使用 RPC包 序列化中没有详细去讲 因为这一块需要看的和学习的地方很多 并且这一块是RPC中可以说是最重要的一块 也是性能的重要影响因子 今天这篇主要会讲其使用方式 文章目录 Protocol Buffers V3 背景以
  • 每天花2小时复习Java面试指南,高级架构视频,我进了阿里定级P7

    Java进阶架构师必备 基础 容器 并发 JVM Java8 计算机网络 计算机操作系统 Linux 数据结构 算法 mysql 优化思路 系统设计 分布式 线上问题调优 虚拟机 tomcat 面试指南 工具 添加图片注释 不超过 140
  • 双非本科进不了大厂?阿里技术四面+交叉面+HR面,成功拿到offer

    前言 前两天 我收到了阿里巴巴的实习offer 从学长内推开始面试到拿到最后offer经历了4面技术 一面交叉面和一面HR面 经过了漫长的等待和几次几乎折磨的面试之后 终于拿到了实习offer 自我介绍 本人来自西南某双非本科学校 该校学的
  • 阿里P8架构师带你“一窥”大型网站架构的主要技术挑战和解决方案

    写在前面 传统的企业应用系统主要面对的技术挑战是处理复杂凌乱 千变万化的所谓业务逻辑 而大型网站主要面对的技术挑战是处理超大量的用户访问和海量的数据处理 前者的挑战来自功能性需求 后者的挑战来自非功能性需求 功能性需求也许还有 人月神话 聊
  • 什么是微服务

    微服务是一种架构风格 它把一个大型的复杂软件应用划分为一系列小的服务 每个服务都具有单一的功能 运行在其自己的进程中 并通常基于不同的编程语言和框架 这些服务之间通过轻量级通信机制相互通信 这种通信机制基于HTTP协议 微服务架构风格使得系
  • 浅谈小程序开源业务架构建设之路

    一 业务介绍 1 1 小程序开源整体介绍 百度从做智能小程序的第一天开始就打造真正开源开放的生态 我们的愿景是 定义移动时代最佳体验 建设智能小程序行业标准 打破孤岛 共建开源 开放 繁荣的小程序行业生态 百度智能小程序的生态玩家有三类 分
  • 微服务常见的配置中心简介

    微服务架构中 常见的配置中心包括以下几种 Spring Cloud Config Spring Cloud Config是官方推荐的配置中心解决方案 它支持将配置文件存储在Git SVN等版本控制系统中 通过提供RESTful API 各个
  • 【技术科普】什么是达芬奇架构?有什么优势?

    芯片架构是指芯片设计的基本结构和组织方式 用于实现各种计算 存储和通信功能 芯片架构通常包括处理器核心 内存 输入输出接口等组成部分 这些部分的设计对芯片性能和功耗有着直接的影响 世界上主流的芯片架构主要包括x86 ARM PowerPC和
  • 阿里技术官亲笔力作:Kafka限量笔记,一本书助你掌握Kafka的精髓

    前言 分布式 堪称程序员江湖中的一把利器 无论面试还是职场 皆是不可或缺的技能 而Kafka 这款分布式发布订阅消息队列的璀璨明珠 其魅力之强大 无与伦比 对于Kafka的奥秘 我们仍需继续探索 要论对Kafka的熟悉程度 恐怕阿里的大佬们

随机推荐

  • 计算机毕业设计选题推荐-SpringBoot 桂林旅游景点导游平台

    作者主页 疯狂行者 java领域优质创作者 专注于Java技术领域技术交流 文末获取源码 精彩专栏推荐订阅 在 下方专栏 Java精彩实战项目案例 Java精彩新手项目案例 Python精彩新手项目案例 文章目录 Java精彩实战项目案例
  • java高校学生实习管理系统springboot+vue

    高校学生实习管理系统管理员 学生 教师 管理员功能有个人中心 学生管理 教师管理 公告信息管理 实习申请管理 实习信息管理 实习成绩管理 学生可以注册 可以实习申请 查看公告信息 查看实习成绩 教师给学生添加实习成绩 审核学生实习申请 查看
  • C++ 游戏服务器方向需要多少功底?

    这篇文章是回答一位知友的提问 现在大二了马上升大三 就读于一个很垫底的211 专业是计算机相关的 但是对本专业内容不感兴趣 希望能从事c 后端的工作 对游戏比较有兴趣 但又不知道需要哪方面的知识 希望各位能给出一个客观的评价或者批评 帮忙指
  • C/C++ 函数调用是如何实现的?

    一 写在前面的话 C C 函数调用方式与栈原理是 C C 开发必须要掌握的基础知识 也是高级技术岗位面试中高频题 我真的真的真的建议无论是使用 C C 的学生还是广大 C C 开发者 都该掌握此回答中所介绍的知识 如果你看不懂接下来第二部分
  • Nodejs+vue+elementui+mysql酒店宾馆客房预订管理系统479v8

    对一个宾馆而言 一个良好的管理系统就等于优质的服务 赚钱的工具 为宾馆的发展带来光明的前景 模块介绍 1 用户注册与登录模块 员工和管理员注册与登录 个人信息修改等 2 个人中心模块 对个人信息进行修改添加等 3 员工管理模块 添加 修改员
  • 基于java的高校教职工档案管理系统springboot+jsp

    一 拟解决的关键问题 1 登陆模块 该模块对档案管理系统设定登录约束 并在该模块对档案系统登录用户进行权限分配 2 档案收集模块 对各类档案材料进行录入和入库 数据库 主要包括学历档案信息 工作经历档案信息 职称档案信息 职务信息档案 表彰
  • python+django民俗风俗习惯传统文化网站pycharm毕业设计

    1 所有记录信息要保持全面 信息记录内容不可以是空 2 各种数据间相互联系要保持正确 3 相同数据在不同记录中要保持一致 传统文化如果还用之前的只有线下进行黑板报形式的去实行 已经很落伍了 这样会导致了效率低下 而且 时间一长的话 积累下来
  • 计算机毕业设计python+django家庭养老服务管理系统vr18o

    快本居家养老系统管理员和工作人员两个角色 管理员功能有个人中心 老人账号管理 工作人员管理 老人档案管理 订单申请管理 检查检验项目管理 维修服务管理 订单信息管理 转诊信息管理 生活服务管理 服务记录管理 生活用品信息管理 药品信息管理
  • 基于Android的旅游服务APP系统

    收藏关注不迷路 源码文章末 文章目录 前言 一 项目介绍 二 开发环境 三 功能介绍 四 核心代码 五 效果图 六 文章目录 前言 本Android的旅游服务APP是根据当前我国旅游的大环境相关的内容实际情况开发的 在系统语言选择上我们使用
  • nodejs微信小程序+python+PHP健身房信息管理系统的设计与实现-计算机毕业设计推荐

    目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1 1背景及意义 1 1 2 国内外研究概况 1 1 3 研究的内容 1 第2章 相关技术 3 2 1 nodejs简介 4 2 2 express框架介绍 6 2
  • 计算机毕业设计推荐之java网上购物商城系统sringboot+vue_o9m4k

    系统使用过程主要涉及到管理员和用户两种角色 主要包含个人中心 用户管理 商品类别管理 热卖商品管理 投诉建议 系统管理 订单管理等功能 系统开发主要在 Windows 系统下进行 采用支持跨平台的 Java语言开发完成 因此可以运行在任意开
  • 大一大二的计算机专业同学应该学习什么?如何学习?

    本文是回答一位知友的提问 已经大一下了 现在在学 C 感觉书上很多术语都不懂 编程自己也得花很多时间才能做出来 但感觉自己身边的同学却什么都会 有什么好的建议吗 我一定努力改正 正文 一 可能的原因 调整心态 克服恐惧和畏难情绪 建议反思一
  • 前后端分离vscode+mysql校园报修维修管理系统nodejs+vue

    本基于nodejs的学校智能网上报修管理系统是根据当前高校网上报修相关的内容实际情况开发的 在系统语言选择上我们使用的nodejs语言 数据库是小巧灵活的MySQL数据库 本系统的开发可以极大的提高学校智能网上报修管理系统的管理效率 开发语
  • nodejs+vue+elementui电子数码产品商城推荐系统vscode毕业设计

    基于vue的电子产品推荐系统分为前台和后台两部 前台部分主要是让用户购买和查看商品使用的 后台主要是让管理员人员发布商品相关信息和管理订单使用的 前台部分包括用户注册登录 查看商品相关信息 查看公告信息 查看热卖产品 查看精品产品 将商品加
  • 基于springboot洗衣店管理系统

    收藏关注不迷路 源码文章末 文章目录 一 项目介绍 二 开发环境 三 功能介绍 四 核心代码 五 效果图 六 文章目录 一 项目介绍 本基于springboot洗衣店管理系统是根据当前洗衣店和用户的实际情况开发的 在系统语言选择上我们使用的
  • css设置渐变色

    css如何设置自定义渐变色 线性渐变篇 CSS渐变可以让你在两个或多个指定颜色之间显示平滑的过渡 CSS定义了三种渐变类型 Linear Gradients goes down up left right diagonally 下降 上升
  • python+django基于hadoop大数据的学习资源推送系统的设计与实现vue

    考虑到实际生活中在学习资源推送管理方面的需要以及对该系统认真的分析 将系统按权限进行划分 管理员登入使用本系统涉到的功能主要有个人中心 用户管理 学习视频管理 学习类型管理 系统管理等功能 管理员用例如图3 1所示 图3 1 管理员用例图
  • springboot+jsp高校大学生心理咨询系统

    1 课题目的及意义 随着全球化的发展 各国对高等素质的人才需求越来越大 培养高素质的人才 顺应世界的需求 就要求高校培养的不单单是德智体美劳德人才 还需要心理健康的人才 加强大学生心理素质教育是时代发展的需要 也是中国高等教育改革的需要 近
  • 基于java的可视化高校学生宿舍公寓管理系统springboot+vue

    实现了用户在线选择试题并完成答题 在线查看考核分数 管理员管理班级管理 每日打卡管理 字典管理 访客管理 宿舍缴费记录管理 离校登记管理 宿舍管理 宿舍管理员管理 物品进出登记管理 学生管理 住宿信息管理 管理员管理等功能 管理员功能 1
  • 单个 epoll + 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景?

    本文是回答一位知友的提问 单个 epoll 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景 不少教程上都提到线程池适合大量的网络短连接的任务场景 但我总感觉这个优势有点站不住脚 单 epoll 线程池模型 主要考虑到