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.rhkb.cn/news/351457.html

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

相关文章

独辟蹊径:我是如何用Java自创一套工作流引擎的(上)

作者:后端小肥肠 创作不易,未经允许严谨转载。 目录 1. 前言 2. 我为什么要自创一套工作流引擎 3. 表结构设计及关系讲解 3.1. 流程类别business_approval_workflow 3.1.1. 表结构 3.1.2. 表关系说明 3.2. 流程定义business_approval_workflow_de…

LVS+Keepalived NGINX+Keepalived 高可用群集实战部署

Keepalived及其工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题。 VRRP协议(虚拟路由冗余协议) 是针对路由器的一种备份解决方案由多台路由器组成一个热备组,通过共用的…

Linux:基础IO(二.缓冲区、模拟一下缓冲区、详细讲解文件系统)

上次介绍了:Linux:基础IO(一.C语言文件接口与系统调用、默认打开的文件流、详解文件描述符与dup2系统调用) 文章目录 1.缓冲区1.1概念1.2作用与意义 2.语言级别的缓冲区2.1刷新策略2.2具体在哪里2.3支持格式化 3.自己来模拟一下缓…

简单谈谈云服务器私网IP的存在意义及优势

云服务器是基于虚拟化技术的计算资源,可以在云平台上灵活创建和管理。为了满足不同用户的需求,云服务提供商在云服务器上分配了两种类型的IP地址:公网IP和私网IP。其中,私网IP是指在局域网内使用的内部IP地址,无法通过…

计算机图形学入门11:图形管线与着色器

1.什么是图形管线 把场景中的物体经过一系列的处理,最后一张图像的形式在屏幕上显示出来,这一系列过程就是图形管线(Graphics Pipeline),也叫实时渲染管线(Real-time Rendering Pipeline)。如下图所示,为整个渲染管线的过程。 渲染…

《幻影大师:透视缠中说禅的虚像与真相》

而且他从不犯错,至少在他的叙述中是这样,所有的文章和言论都被粉饰得完美无瑕,即便有误,他也绝不公开承认,更别提什么真诚的道歉和改正了。那些对他推崇备至的人,多是盲目追随,将他神化为无所不…

Win11 问题集

文章目录 一、Win11 选择其他应用打开无反应1、新建 1.reg 文件2、新建 2.reg 文件3、运行 reg 文件 二、Win11 账户怎么改名 一、Win11 选择其他应用打开无反应 Win11选择打开方式卡死怎么办? 选择打开方式没有反应的解决办法 1、新建 1.reg 文件 1.reg Windows Registry…

代理IP协议有何区别?深入了解 SOCKS5、HTTP 代理

在数字通信领域,数据安全和匿名性都是非常重要的指标。互联网的不断发展催生了几种协议,每种协议都有独特的优势和挑战。其中,SOCKS5 代理、HTTP代理最为广泛使用,下面给大家一起讨论,HTTP代理与 SOCKS5代理&#xff0…

华为OD机试 - 多段线数据压缩(Java 2024 D卷 100分)

华为OD机试 2024D卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(D卷C卷A卷B卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测…

探索 Docker:容器化技术的未来

1. 引言 在传统的软件开发和部署过程中,经常会遇到诸如“开发环境和生产环境不一致”、“依赖环境冲突”、“部署困难”等问题。为了解决这些问题,容器化技术应运而生。Docker 作为最受欢迎的容器平台之一,已经在业界得到广泛应用。它不仅简化…

【chatbot-api开源项目】开发文档

chatbot-api 1. 需求分析1-1. 需求分析1-2. 系统流程图 2. 技术选型3. 项目开发3-1. 项目初始化3-2. 爬取接口获取问题接口回答问题接口创建对应对象 3-3. 调用AI3-4. 定时自动化回答 4. Docker部署5. 扩展5-1. 如果cookie失效了怎么处理5-2. 如何更好的对接多个回答系统 Gitee…

Unity 3D 物体的Inspector面板

1、Transform:位置、旋转、大小 2、Mesh Filter:物体的形状 3、Mesh Renderer:物体渲染(物体的衣服) 4、Collider:碰撞体

北京多商入驻app开发项目的主要优势及功能

多商入驻app开发项目的定义 随着电子支付技术的不断成熟,全国各地的消费者通过网络在线上购物的频率越来越高,为此,多商入驻app开发项目应用而生。各商家也纷纷开始申请入驻商城平台,开设自己的店铺。 图片来源:unspl…

【iOS】自定义cell及其复用机制

文章目录 cell的复用注册非注册两者的区别 自定义cell cell的复用 当用户滚动 UITableView 或 UICollectionView 时,只有少量可见的 cell 会被实际创建和显示。对于那些暂时不可见的 cell,系统会将它们缓存起来以备将来复用。这就是所谓的 cell 复用机制。 为什么需要cell的复…

【论文阅读】AttnDreamBooth | 面向文本对齐的个性化图片生成

文章目录 1 动机2 方法3 实验 1 动机 使用灵活的文本控制可以实现一些特定的概念的注入从而实现个性化的图片生成。 最经典的比如一些好玩的动漫人物的概念,SD大模型本身是不知道这些概念的,但是通过概念注入是可以实现的从而生成对应的动漫人物 两个…

Vue笔记(三)

上一篇:Vue二)-CSDN博客 目录 1.自定义指令 v-loading的封装 2.插槽 文本插槽 文本插槽(有默认值) 具名插槽 作用域插槽 详细做一个练习 实现如下效果 目录结构 准备数据 父传子数据 使用文本插槽自定义按钮文本 实…

PyTorch计算机视觉入门:测试模型与评估,对单帧图片进行推理

在完成模型的训练之后,对模型进行测试与评估是至关重要的一步,它能帮助我们理解模型在未知数据上的泛化能力。本篇指南将带您了解如何使用PyTorch进行模型测试,并对测试结果进行分析。我们将基于之前训练好的模型,演示如何加载数据…

msvcp120.dll丢失原因分析与解决方法分享

msvcp120.dll 是一个动态链接库(Dynamic Link Library, DLL),属于 Microsoft Visual C 2013 再发行组件包的一部分。它提供了 C 标准库的实现,使得使用 C 编写的应用程序能够在运行时动态链接到该库,从而访问其提供的函…

element-plus表单组件之自动补全组件el-autocomplete和级联选择器组件el-cascader

el-autocomplete 自动补全组件 自补全组件的功能和可以根据输入过滤的el-select组件有些类似。 fetch-suggestions 根据输入框的输入获取建议的内容,其接受值是一个函数,有2个参数,querystring:输入的内容,callback内置函数&…

Django DetailView视图

Django的DetailView是一个用于显示单个对象详情的视图。下面是一个使用DetailView来显示单个书籍详情的例子。 1,添加视图 Test/app3/views.py from django.shortcuts import render# Create your views here. from django.views.generic import ListView from .m…