【muduo源码学习】one-loop-per-thread核心原理

在 TCP 网络编程中,这里我们特指在单机的环境下,主要关注两件事。第一,如何正确的处理TCP的连接和断开,以及正确处理数据的收发;在错综复杂的网络环境中,这并非易事,涉及很多细节。第二,如何榨干机器的性能,即如何让单台机器在已有的硬件条件下处理尽可能多的连接请求;这需要设计一种高效的网络模型,这是本文讨论的主题,即在 muduo 网络库源码的学习基础上,总结和讨论。

下面进入本文的主题。

在TCP网络编程中,我们关注的核心是,在一个小的时间片段中,如何能够处理更多的并发连接。这主要可以从三个方面展开,而从一个服务端程序的性能指标来看,这三个方面分别为:响应时间、吞吐量和并发连接数。

  • 响应时间。响应时间是指请求发送到收到响应的时间。从程序本身来看,当收到客户端发来的请求时,TCP服务端需要能够立马处理,并将处理结果立马发送回客户端。更具体地,在面对短时间内有大量的请求到来时,TCP服务端要做尽可能地做到不阻塞在某个或某些请求处理上。这表现为,在错综复杂的网络环境中,数据的收发是不确定性,TCP服务端不能阻塞在socket上的读写上,这就要求socket是非阻塞的(nonblocking IO)。
  • 吞吐量。吞吐量是指单位时间内处理的请求数量。我们希望每个单机的TCP服务程序在单位时间内能够处理尽可能多的请求,这对于单核的CPU很容易就达到瓶颈,而对于多核的CPU,我们希望尽可能把每个核都跑满,使其处理充分多的请求,这就要求TCP服务程序具有很好的多线程网络模型,而下文中介绍的 one loop per thread 网络模型就可以很好的和多线程结合。
  • 并发连接数。并发连接数是指服务程序同时能够处理的连接数量。每个连接最少需要一定的内存资源,因此并发连接数会受计算机硬件的影响;此外每个连接至少需要一个socket文件描述符,而操作系统中的文件描述符数量是有限的,因此并发连接数会受到操作系统软件资源的影响。此外,从TCP服务程序本身来看,TCP服务程序可以同时保持很多连接,但在同一时刻处理这些已连接的请求的数量是少于总连接的数量的,同时TCP服务程序要需要处理源源不断带来的新连接,以及因为连接超时等原因关闭的连接,这就要求我们使用IO复用技术(IO multiplexing)。

小结一下,为降低响应时间,需要使用 nonblocking IO;为并发连接数尽可能大,需要使用 IO multiplexing;为了提高吞吐量,在程序上需要设计良好的多线程网络模型。下面就正式介绍 one loop per thread 网络模型,它是基于 nonblocking IO 和 IO multiplexing 的。

one loop per thread 网络模型,也称为 Reactor 模型。loop指事件循环,将文件描述符可读称为一个可读事件,将文件描述符可写称为一个可写事件,在TCP网络编程中,我们重点关注socket文件描述符上的读写事件。事件循环是指监控文件描述符上的读写事件,当有文件描述符变得可读或可写时,理解为发生了一次事件循环,即检测到一次事件发生。事件循环是依赖于 IO multiplexing 的。综上,one loop per thread 指每个线程中只有一个事件循环。

如下图所示,先来看下在单线程下,one loop per thread 网络模型长什么样子。
在这里插入图片描述

单线程下 one loop per thread 网络模型的TCP连接处理流程:

  • 服务端阻塞在 IO multiplexing 函数调用,等待客户端的请求到来。
  • 当客户端发送请求给服务端,IO multiplexing 函数检测到读事件,解除阻塞,然后获取产生读事件的 socket 文件描述符,从socket文件描述符上读取数据进行处理。在 IO multiplexing 函数中监控的 socket 文件描述有两类,一类是已连接的 socekt 文件描述符,一类是监听是否有新连接到来的 socket 文件描述符。
    • 对于监听socket上的读事件,调用 accept() 函数接收一个新的连接请求,并获取新连接的 socket 文件描述符,然后将其注册到 IO multiplexing 函数中。
    • 对于已连接的 socket 上的读事件,进行 read() --> 业务处理 --> write() 的处理流程。

one loop per thread 网络模型通过 nonblocking IO + IO multiplexing 可以很好的同时处理新连接和已连接,但存在的问题也显而易见,因为是单线程,你处理能力受限,且当已连接的处理比较耗时,新连接的响应时间就会受到影响。若已连接的处理比较耗时,比如是CPU密集计算任务,一种解决方案是,另起线程做CPU密集祭祀按任务,不让其影响IO线程,从而影响响应时间。当然这在单线程环境下都无从说起。

发挥 one loop per thread 网络模型能力的场合时多线程环境,通过将新连接的处理和已连接的处理分发到不同线程,来提高吞吐量。其本质是让已连接的处理不会影响新连接的处理。多线程下的 one loop per thread 网络模型如下图所示。
在这里插入图片描述

多线程 one loop per thread 网络模型下,每个线程中运行一个 loop,且每个线程最多运行一个 loop。在这个网络模型下,有一个主线程,有的博客中也称为主Reactor(Main Reactor)。主线程主要干两件事,第一,管理监听socket,当有新连接到来,即监听socket可读,调用 accept() 建立一个新连接;第二,获取新连接的 socket 后,将其分发到一个子线程中的 IO multiplexing 函数中,之后这个已连接 socket 上的读写事件主线程就不再负责,被分发到的子线程始终管理着这个已连接socket上的读写事件,直到这个连接关闭。

多线程的 one loop per thread 网络模型的优点:

  • 将新连接处理和已连接处理分离在不同的线程处理,兼顾服务程序的响应事件和吞吐量。
  • 监控 socket 上读写事件的线程是固定的,即不存在A线程监控读事件B线程监控写事件的情况,事件处理的流程简单。
  • 任务在线程之间的调配安全简单。在A线程调用B线程管理的socket上的回调函数,最终会转入B线程执行调用。(将在《muduo源码分析之Channel、EventLoop和Selector》的文章中详细介绍)

总结: 上述描述的 one loop per thread 网络模型主要涉及网络的IO,也即主要关心 socket 的读写事件,这是网络库关心的核心问题之一。因此,有时又将具有事件循环的线程称为IO线程。一个高效的网络库的核心工作是要能够处理足够大的并发量,即IO事件,当请求中涉及CPU密集计算任务时,不能让其在IO线程中占用过多的CPU资源,这样会影响到IO线程上的其他连接,一种解决办法是,为CPU密集计算任务开辟单独的线程或线程池,通过例如消息队列的形式将密集计算任务分发给这些线程, one loop per thread 模型可能很轻松进行这样的结合。

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

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

相关文章

【JAVA基础篇教学】第十七篇:Java单元测试

博主打算从0-1讲解下java基础教学,今天教学第十七篇:Java单元测试。 单元测试和集成测试是软件开发过程中至关重要的一部分,它们可以帮助确保代码的质量和稳定性。下面我将为您提供详细说明和代码案例。 一、单元测试(Unit Test…

27、Lua 学习笔记之五(Lua中的数学库)

Lua中的数学库 Lua5.1中数学库的所有函数如下表: math.pi 为圆周率常量 3.14159265358979323846 数学库说明例子方法abs取绝对值math.abs(-15)15acos反余弦函数math.acos(0.5)1.04719755asin反正弦函数math.asin(0.5)0.52359877atan2x / y的反正切值math.atan2(9…

JAVA学习-并发.并发的定义

并发是指多个任务在同一时间段内执行。在计算机领域,特指多个线程或进程同时执行的情况。Java提供了多种并发编程的机制,包括线程、锁、信号量、并发集合等。下面将对Java并发编程的一些常见概念、特点以及使用方法进行概述,并与其他比较和高…

Optional类用法

简介 空指针异常是Java应用程序失败的最常见原因。Google公司在著名的Guava项目中引入了Optional类,通过使用检查空值的方式来防止代码污染,来解决臭名昭著的空指针异常问题。受此启发,Optional类已成为Java 8 类库的一部分。 使用 Optional类…

Leetcode 221. 最大正方形

心路历程: 这道题是一个动态规划题,但是其实递推关系很难想到,如下图所示: MDP建模: 状态:以i,j为右下角的正方形 动作候选集:这道题的动作候选集其实是是否选择其左上角邻接的三个位置&#x…

11.范式与反范式设计

范式 1.问题 MySQL的库表设计,在很多时候我们都是率性而为,往往在前期的设计中考虑不全面,同时对于库表结构的划分也并不明确,所以很多时候在开发过程中,代码敲着敲着会去重构某张表结构,甚至大面积重构多…

linux常用基本命令

# 文本与文本查找 ## 1.grep 常用参数: -A n --after-context显示匹配字符后n行 -B n --before-context显示匹配字符前n行 -C n --context 显示匹配字符前后n行 -c --count 计算符合样式的行数 -i 忽略大小写 -v反转 -a处理二进制文件 -l 只列出文件内容符…

深圳比创达电子EMC|EMC电磁兼容性:电子设备稳定运行的保障

随着科技的飞速发展,电子设备在人们的日常生活中发挥着越来越重要的作用。然而,随之而来的电磁干扰问题也日益突出。电磁兼容性(EMC)作为衡量电子设备在电磁环境中正常工作能力的关键指标,其重要性不言而喻。 一、EMC…

IP地址是随着网络变化的吗?

IP地址,即互联网协议地址,是分配给每个联网设备或网络接口的数字标签。它在网络通信中起着至关重要的作用,是设备之间互相识别和通信的基础。然而,关于IP地址是否随着网络变化,这是一个值得深入探讨的问题,…

每日新闻掌握【2024年4月16日 星期二】

2024年4月16日 星期二 农历三月初八 大公司/大事件 丁雄军:茅台集团2023年出口额超43亿元,占中国白酒出口额的77% 36氪获悉,据贵州茅台微信公众号消息,4月13日,茅台集团党委书记、董事长丁雄军出席全球消费创新系列活…

深度残差收缩网络中,使用 Sigmoid 函数的用意在哪?

在深度残差收缩网络中,使用 Sigmoid 函数将输出归一化到 0 和 1 之间的目的是为了限制输出值的范围,并且使得输出可以被解释为概率。这个 Sigmoid 函数的输出可以被看作是一个置信度或者概率的度量,表示某个事件发生的可能性。 在设置阈值时…

对外观模式的理解

目录 一、场景【[案例来源](https://kamacoder.com/problempage.php?pid1089)】1 题目描述2 输入描述3 输出描述4 输入示例5 输出示例 二、如果不采用外观模式1、实现2、问题 三、采用外观模式1、实现2、优点 四、个人思考 一、场景【案例来源】 1 题目描述 小明家的电源总开…

微信小程序的反编译

参考: 微信小程序的反编译_magic number is not correct!-CSDN博客 如何从在安卓Android手机获取微信小程序源代码 - 知乎 (zhihu.com) 资源: wechar.apk RE管理器.apk Node.js”安装包 反编译GIT:hs610/wxappUnpacker (github.com)

Linux没有显示IP地址,报错mtu 1500 qdisc noop state DOWN group default qlen 1000

问题 复制虚拟机后, 打开,发现没有IP地址. ip addr 1:1o:<LOOPBACK,UP,LOWER_UP>mtu 65536 gdisc noqueue state UNKNOWN group default glen 1000 1ink/1 popback88:80:80:88:88:80brd00:0g:80:80:80:80 inet 127.0.0.1/8 scope host lo valid_lft forever preferre…

详解playwright 官方Javascript demo(适合小白)

如果大家刚上手playwright&#xff0c;并看到了Javascript脚本的官方demo&#xff0c;代码如下&#xff1a; const { webkit } require(playwright);(async () > {const browser await webkit.launch();const page await browser.newPage();await page.goto(http://what…

开放式耳机怎么选?五大市场热卖爆款推荐!

近年来&#xff0c;开放式耳机风潮席卷市场&#xff0c;各大知名品牌纷纷推出新品&#xff0c;以满足消费者的需求。相较于传统的入耳式耳机&#xff0c;开放式耳机凭借其独特的佩戴方式&#xff0c;受到了广大消费者的热烈追捧。它不仅有效避免了长时间佩戴带来的耳道不透气、…

【数据结构】栈的实现

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《数据结构》 &#x1f389;前路漫漫亦灿灿 前言 栈是一种特殊的线性表&#xff0c;我们在有了顺序表和链表的知识的基础上&#xff0c;再来学习栈&#xff0c;掌握起来就更轻松了…

所有可能的真二叉树(Lc894)——记忆化搜索

给你一个整数 n &#xff0c;请你找出所有可能含 n 个节点的 真二叉树 &#xff0c;并以列表形式返回。答案中每棵树的每个节点都必须符合 Node.val 0 。 答案的每个元素都是一棵真二叉树的根节点。你可以按 任意顺序 返回最终的真二叉树列表。 真二叉树 是一类二叉树&#…

【24年物联网华为杯】赛题分析与初步计划

赛事介绍 官网链接&#xff1a;2024 年全国大学生物联网设计竞赛 (sjtu.edu.cn) 含金量&#xff1a;属于A类赛事 &#xff08;注意&#xff1a;很多搜索结果的序号是按照选入时间排列的&#xff0c;与含金量无关&#xff0c;华为杯是23年选入的&#xff09; Kimi Chat: 全国…

开源模型应用落地-LangChain试炼-CPU调用QWen1.5(一)

一、前言 尽管现在的大语言模型已经非常强大&#xff0c;可以解决许多问题&#xff0c;但在处理复杂情况时&#xff0c;仍然需要进行多个步骤或整合不同的流程才能达到最终的目标。然而&#xff0c;现在可以利用langchain来使得模型的应用变得更加直接和简单。 通过langchain框…