go的netpoll学习

go的运行时调度框架简介

在这里插入图片描述

Go的运行时(runtime)中,由调度器管理:goroutine(G)、操作系统线程(M)和逻辑处理器(P)之间的关系
以实现高效的并发执行
当一个goroutine(G)发起一个系统调用(system call)并且需要等待其完成时,会导致该goroutine暂停执行

G的阻塞:
当一个goroutine执行系统调用并因此阻塞时(例如文件I/O、网络请求等),这个goroutine会进入阻塞状态
此时,它不会占用CPU资源,也不会继续执行

M与P的关系调整:
关键在于执行该goroutine的用户级线程(M)的行为
实际上,并不是M会被解绑P并一起进入sleep状态 。根据Go的调度策略,当M上的goroutine因为系统调用而阻塞时,调度器可能会采取以下行动之一:
(1) 如果可能,调度器会尝试将其他可运行的goroutine(即处于就绪状态的G)分配给这个M来执行,这样M不会空闲,继续利用CPU资源。这种情况下,M保持与P的绑定,只是切换了执行的goroutine。
(2) 如果没有其他goroutine可以调度(或者出于效率考虑,比如系统调用预计很快返回),M可能会选择进入休眠状态(但不直接与G一起sleep),这时它会释放对P的绑定,让P可以被其他M使用,以避免P资源闲置。M此时会进入一个等待状态,直到被唤醒(可能是由于系统调用完成/有新的任务需要处理)。

sysmon(监控线程)的作用:
sysmon是Go运行时中的一个特殊后台线程,负责监控和维护整个运行时的状态
包括发现并解决某些阻塞情况、管理空闲的M和P等
如果一个M因为等待系统调用长时间未被唤醒,sysmon可能会介入检查并采取措施
比如创建新的M来保证CPU的充分利用,但这并不意味着sysmon直接抢走P

当一个goroutine因系统调用而阻塞时,主要影响是该goroutine本身暂停执行
而执行它的M和关联的P则根据Go运行时的具体策略灵活调整,以优化整体的执行效率和资源利用率,而不是一起进入sleep状态

Go netpoll 核心

package main
import ("fmt""net"
)func main() {listen, err := net.Listen("tcp", ":8888")if err != nil {fmt.Println("listen error: ", err)return}for {conn, err := listen.Accept()if err != nil {fmt.Println("accept error: ", err)break}// start a new goroutine to handle the new connectiongo HandleConn(conn)}
}
func HandleConn(conn net.Conn) {defer conn.Close()packet := make([]byte, 1024)for {// 如果没有可读数据,也就是读 buffer 为空,则阻塞_, _ = conn.Read(packet)// 同理,不可写则阻塞_, _ = conn.Write(packet)}
}

Go netpoll 通过在底层对 epoll/kqueue/iocp 的封装(利用runtime 的 Go scheduler,让它来负责调度 goroutines)
从而实现了使用同步编程模式达到异步执行的效果,对于开发者来说 I/O 是否阻塞是无感知的。

所有的网络操作都以网络描述符 netFD 为中心实现。
netFD 与底层 PollDesc 结构绑定,当在一个 netFD 上读写遇到 EAGAIN 错误时,就将当前 goroutine 存储到这个 netFD 对应的 PollDesc 中,同时调用 gopark 把当前 goroutine 给 park 住,直到这个 netFD 上再次发生读写事件,才将此 goroutine 给 ready 激活重新运行。
显然,在底层通知 goroutine 再次发生读写等事件的方式就是 epoll/kqueue/iocp 等事件驱动机制。

Go netpoll 问题

没有任何一种设计和架构是完美的,goroutine-per-connection这种模式虽然简单高效,但是在某些极端的场景下也会暴露出问题:
goroutine 虽然非常轻量,它的自定义栈内存初始值仅为 2KB,后面按需扩容
海量连接的业务场景下,goroutine-per-connection,此时 goroutine 数量以及消耗的资源就会呈线性趋势暴涨
首先给 Go runtime scheduler 造成极大的压力和侵占系统资源,然后资源被侵占又反过来影响 runtime 的调度,导致性能大幅下降

Reactor 模式

在 Linux 平台下构建的高性能网络程序中,大都使用 Reactor 模式,比如 netty、libevent、libev、ACE,POE(Perl)、Twisted(Python)等
Reactor 模式本质上指的是使用I/O 多路复用(I/O multiplexing) + 非阻塞 I/O(non-blocking I/O)的模式

通常设置一个主线程负责做 event-loop 事件循环和 I/O 读写,通过 select/poll/epoll_wait 等系统调用监听 I/O 事件
业务逻辑提交给其他工作线程去做

『非阻塞 I/O』的核心思想是指避免阻塞在 read() 或者 write() 或者其他的 I/O 系统调用上
这样可以最大限度的复用 event-loop 线程,让一个线程能服务于多个 sockets
在 Reactor 模式中,I/O 线程只能阻塞在 I/O multiplexing 函数上(select/poll/epoll_wait)

Reactor 模式通常的工作流程如下:
(1) Server 端完成在bind&listen之后,将 listenfd 注册到 epollfd 中,最后进入 event-loop 事件循环。循环过程中会调用select/poll/epoll_wait阻塞等待,若有在 listenfd 上的新连接事件则解除阻塞返回,并调用socket.accept接收新连接 connfd,并将 connfd 加入到 epollfd 的 I/O 复用(监听)队列。
(2) 当 connfd 上发生可读/可写事件也会解除select/poll/epoll_wait的阻塞等待,然后进行 I/O 读写操作,这里读写 I/O 都是非阻塞 I/O,这样才不会阻塞 event-loop 的下一个循环。然而,这样容易割裂业务逻辑,不易理解和维护。
(3) 调用read读取数据之后进行解码并放入队列中,等待工作线程处理。
(4) 工作线程处理完数据之后,返回到 event-loop 线程,由这个线程负责调用write把数据写回 client。
(5) accept 连接以及 conn 上的读写操作若是在主线程完成,则要求是非阻塞 I/O

Reactor 模式一条最重要的原则就是:
I/O 操作不能阻塞 event-loop 事件循环。
实际上 event loop 可能也可以是多线程的,只是一个线程里只有一个 select/poll/epoll_wait

参考文档

https://cloud.tencent.com/developer/article/2064645

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

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

相关文章

统计完全子字符串

很不错的计数问题&#xff0c;用到了分组循环技巧和滑动窗口 代码的实现方式也非常值得多看 class Solution { public:int f(string s,int k){int res 0;for(int m1;m<26&&k*m<s.size();m){int cnt[27]{};auto check[&](){for(int i0;i<26;i){if(cnt[i]…

跟着刘二大人学pytorch(第---10---节课之卷积神经网络)

文章目录 0 前言0.1 课程链接&#xff1a;0.2 课件下载地址&#xff1a; 回忆卷积卷积过程&#xff08;以输入为单通道、1个卷积核为例&#xff09;卷积过程&#xff08;以输入为3通道、1个卷积核为例&#xff09;卷积过程&#xff08;以输入为N通道、1个卷积核为例&#xff09…

计算机组成原理之定点除法

文章目录 定点除法运算原码恢复余数法原码不恢复余数法&#xff08;加减交替法&#xff09;运算规则 习题 定点除法运算 注意 &#xff08;1&#xff09;被除数小于除数的时候&#xff0c;商0 &#xff08;2&#xff09;接下来&#xff0c;有一个除数再原来的基础上&#xff0c…

springboot + Vue前后端项目(第十六记)

项目实战第十六记 写在前面1 第一个bug1.1 完整的Role.vue 2 第二个bug2.1 修改路由router下面的index.js 总结写在最后 写在前面 发现bug&#xff0c;修复bug 1 第一个bug 分配菜单时未加入父id&#xff0c;导致分配菜单失效 <!-- :check-strictly"true" 默…

图的应用之最小生成树

大纲 生成树介绍 特点 但n个 种类 最小生成树 应用 构造算法 MST性质 Prim算法 依次选择与顶点相邻的不会构成回路的最小边对应的顶点 Kruskal算法 依次选不会构成环的最小边 区别 Prim算法有n个顶点进行选择&#xff0c;每个顶点有n个选择&#xff0c;复杂度为O(n*n) K…

C51学习归纳13 --- AD/DA转换

AD/DA转换实现了计算机和模拟信号的连接&#xff0c;扩展了计算机的应用场景&#xff0c;为模拟信号数字化提供了底层支持。 AD转换通常是多个输入通道&#xff0c;使用多路选择器连接到AD开关&#xff0c;实现AD多路复用的目的&#xff0c;提高利用率。 AD/DA转换可以使用串口…

我的创作纪念日(1825天)

Ⅰ、机缘 1. 记得是大一、大二的时候就听学校的大牛说&#xff0c;可以通过写 CSDN 博客&#xff0c;来提升自己的代码和逻辑能力&#xff0c;虽然即将到了写作的第六个年头&#xff0c;但感觉这句话依旧受用; 2、今年一整年的创作都没有停止&#xff0c;本年度几乎是每周都来…

UniApp或微信小程序中scroll-view组件使用show-scrollbar在真机Android或IOS中隐藏不了滚动条的解决办法

show-scrollbar 属性 不论是使用 变量 还是直接使用 布尔值或者直接使用 css 都是在 ios、Android 上是都没有效果。。 真机中还是出现滚动条 解决办法 添加下面CSS ::-webkit-scrollbar {display: none;width: 0 !important;height: 0 !important;-webkit-appearance: no…

盛世古董乱世金-数据库稳定到底好不好?

是不是觉得这个还用问&#xff1f; 是的要问。因为这个还是一个有争议的问题。但是争议双方都没有错。这就像辩论&#xff0c;有正反双方。大家都说的有道理&#xff0c;但是很难说谁对谁错。 正方观点&#xff1a;数据库稳定好 其实这个是用户的观点&#xff0c;应用开发人…

17个关键方法指南,保护您的web站点安全!

了解如何让您的web应用程序或网站安全&#xff0c;对于网站所有者来说至关重要。以下是一些关键步骤&#xff0c;可以帮助您保护网站免受攻击和数据泄露。 1.使用公钥加密技术 当数据以明文形式传输时&#xff0c;它容易受到中间人 &#xff08;MitM&#xff09; 攻击。这意味…

北航第六次数据结构与程序设计作业(查找与排序)选填题

一、 顺序查找的平均查找长度ASL&#xff08;1 2 …… n&#xff09;/ n (n 1&#xff09;/ 2 二、 这半查找法的平均查找次数和判定树的深度有关系。若查找一个不存在的元素&#xff0c;说明进行了深度次比较。 注意&#xff0c;判定树不是满二叉树&#xff0c;因此深…

安卓网络通信(多线程、HTTP访问、图片加载、即时通信)

本章介绍App开发常用的以下网络通信技术&#xff0c;主要包括&#xff1a;如何以官方推荐的方式使用多线程技术&#xff0c;如何通过okhttp实现常见的HTTP接口访问操作&#xff0c;如何使用Dlide框架加载网络图片&#xff0c;如何分别运用SocketIO和WebSocket实现及时通信功能等…

HTTP协议 快速入门

http概述 无状态性&#xff1a;HTTP是一个无状态协议&#xff0c;这意味着服务器不会在请求之间保存任何会话信息。每个请求都是独立的&#xff0c;服务器不会记住之前的请求。 请求-响应模型&#xff1a;HTTP通信是基于客户端发送请求和服务器返回响应的模型。客户端&#xf…

Spark常见的可以优化的点

Shuffle 复用 # 1.以下操作会复用的shuffle结果&#xff0c;只会读一遍数据源 val rdd1 sc.textFile("hdfs://zjyprc-hadoop/tmp/hive-site.xml").flatMap(_.split(" ")).map(x > (x,1)).reduceByKey(_ _).filter(_._2 > 1) rdd1.count() rdd1.fil…

华为od-C卷200分题目2 - 找城市

华为od-C卷200分题目2 - 找城市 题目描述 一个城市规划问题&#xff0c;一个地图有很多城市&#xff0c;两个城市之间只有一种路径&#xff0c;切断通往一 个城市i的所有路径之后&#xff0c;其他的城市形成了独立的城市群&#xff0c;这些城市群里最大的城 市数量&#xff0…

会声会影色彩校正在哪里 会声会影色彩素材栏在哪 会声会影中文免费版下载

会声会影是一款功能强大的视频编辑软件&#xff0c;它可以帮助用户轻松地编辑和制作视频。在进行视频编辑时&#xff0c;色彩校正是一个重要的步骤&#xff0c;它可以调整视频的色调、亮度和对比度等参数&#xff0c;使视频更加生动和鲜明。在会声会影中&#xff0c;色彩校正功…

【Python/Pytorch - 网络模型】-- TV Loss损失函数

文章目录 文章目录 00 写在前面01 基于Pytorch版本的TV Loss代码02 论文下载 00 写在前面 在医学图像重建过程中&#xff0c;经常在代价方程中加入TV 正则项&#xff0c;该正则项作为去噪项&#xff0c;对于重建可以起到很大帮助作用。但是对于一些纹理细节要求较高的任务&am…

MongoDB~分片数据存储Chunk;其迁移原理、影响,以及避免手段

分片数据存储&#xff1a;Chunk存储 Chunk&#xff08;块&#xff09; 是 MongoDB 分片集群的一个核心概念&#xff0c;其本质上就是由一组 Document 组成的逻辑数据单元。每个 Chunk 包含一定范围片键的数据&#xff0c;互不相交且并集为全部数据。 分片集群不会记录每条数据…

Python 基础:类

目录 一、类的概念二、定义类三、创建对象并进行访问四、修改属性的值方法一&#xff1a;句点表示法直接访问并修改方法二&#xff1a;通过方法进行修改 五、继承继承父类属性和方法重写父类方法 六、将实例用作属性七、导入类导入单个类从一个模块中导入多个类导入整个模块导入…

C语言的基本输入输出函数+构造类型数据——数组

C语言的基本输入输出函数 1. 字符输入输出函数 getchar()、putchar() getchar()&#xff1a;从标准输入&#xff08;通常是键盘&#xff09;读取一个字符&#xff0c;并返回其ASCII值。putchar()&#xff1a;将指定的字符&#xff08;由其ASCII值表示&#xff09;写入标准输出…