Go语言 几种常见的IO模型用法 和 netpoll与原生GoNet对比

2024-06-04 00:04

本文主要是介绍Go语言 几种常见的IO模型用法 和 netpoll与原生GoNet对比,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【go基础】16.I/O模型与网络轮询器netpoller_go中的多路io复用模型-CSDN博客

字节开源的netPoll多路复用器源码解析-CSDN博客

一、几种常见的IO模型

1. 阻塞I/O

(1) 解释:

    用户调用如accept、read等系统调用,向内核发起I/O请求后,应用程序会从用户态陷入内核态。

    内核会检查文件描述符fd是否就绪,如果没有数据准备就绪,内核就会挂起(阻塞)当前的线程

    当fd中数据就绪后,操作系统内核会将数据从内核空间拷贝到进程空间,并交回控制权。

(2) 缺点:

    一个goroutine同一时刻只能处理一个流,无法解决多个IO请求问题

2. 非阻塞I/O

(1) 解释:

    执行read和write 等I/O操作会立刻返回,然后应用程序不停轮询。读取时如果没有数据,会返回

EAGAIN或EWOULDBLOCK错误码。

(2) 缺点:

    占用cpu资源,不停做无用的轮询操作

3.  I/O多路复用模型

(1) 解释:

    一个进程/线程处理多个I/O,内核同时监视多个文件描述符,一旦某个描述符就绪,通知程序进行相应的读写操作;如果没有文件句柄就绪,就阻塞应用程序,交出CPU。

(2) 缺点:无,基本符合需求。

4. 三种IO模型对比

目前epoll是linux大规模并发网络应用程序的首选。

大部分高性能的网络服务器使用的I/O复用模型均是epoll,比如nginx、redis、memcached等。

二、几种常见的IO模型 使用方法 

     以下模型的 IO 操作都是 使用阻塞的机制。

1、多线程

(1) 解释:

    每accept到一个客户端后,都启动一个新的线程。存在多个线程。

(2) 优点: 简单。

(3) 缺点:

a. 占用内存资源,每个线程需要2M的栈空间;需要的线程很多,且频繁切换。

b. 长连接需要保持连接状态(心跳/健康检查),进一步占用资源。

2、单线程 + 多路IO复用

(1) 解释:

    一个线程 ,处理多个客户端。采用多路I/O复用机制(epoll) 监控多个fd的IO请求

    多个请求是依次执行的,fd1的请求完成了,才去处理fd2的请求。

(2) 优点: 只需要一个线程,节省资源。

(3) 缺点:同一时间只能处理一个客户端操作,会有排队延迟

3、单线程 + 多路IO复用 + 多线程处理业务

(1) 解释:

    把逻辑任务分离到另外的线程池。

    创建专门用于处理逻辑业务的线程池。

    当有客户端消息到达,主线程完成io读操作后,将后续逻辑业务放入线程池的一个线程中执行,主线程继续监控IO请求。当线程执行完逻辑业务之后,将结果消息返回主线程,主线再发送给客户端。

(2) 优点: 将业务放到线程处理,减轻排队延迟。

(3) 缺点:IO 读写数据时的并发能力依然是1

4、单线程(只监听) + 多路IO复用 + 多线程处理业务和IO读写

(1) 解释:

     在3的基础上,让线程池把 IO读写 和 业务 都处理了。

     主线程只负责用来创建fd,每个线程负责监听多个客户端读写操作,以及后续逻辑业务。

     使用例子: GO语言的 原生net 和 netpoll 采用的是这个模式。

(2) 优点: 

a. 可以监听更多的fd,提升io读写的并发能力

b. 充分利用多核CPU

(3) 缺点:同一个线程内的多个客户端,依然是排队的

三、Netpoll与原生GoNet对比

1. 触发方式

Go Net:使用 边缘触发。只有一个Epoll事件循环,高并发时压力大。但消息包很大时,需要内存少。

NetPoll:使用 水平触发。支持多个事件,高并发效果更好。但消息包很大时,需要更多的内存。

2. Goroutine数目

Go Net:一个Goroutine下只有一个连接。

NetPoll:一个Goroutine下有多个连接。

3. 是否支持共用buff池,少拷贝一次数据。

Go Net:不支持。

NetPoll:支持。管理一个Buffer池直接交给用户,少拷贝一次。

四、边缘触发和水平触发的区别

1. 水平触发(LT): 若就绪的事件一次没有处理完,就会将没有处理完的事件继续放回到就绪队列之中,下一次可继续触发事件。

    必须使用非阻塞模式。因为水平触发模式会将文件描述符一直读到返回 errno或EAGAIN,非阻塞模式下才会返回这个。 而阻塞模式下不会返回这个,所以会一直阻塞卡死。

2. 边缘触发(ET):就绪的事件只能处理一次,需要一次过把数据读完。

  若没有处理完,会在下次的其它事件就绪时再进行处理。

  而若以后再也没有就绪的事件,剩余的那部分数据也会丢失。

这篇关于Go语言 几种常见的IO模型用法 和 netpoll与原生GoNet对比的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1028489

相关文章

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

Go Gorm 示例详解

《GoGorm示例详解》Gorm是一款高性能的GolangORM库,便于开发人员提高效率,本文介绍了Gorm的基本概念、数据库连接、基本操作(创建表、新增记录、查询记录、修改记录、删除记录)等,本... 目录1. 概念2. 数据库连接2.1 安装依赖2.2 连接数据库3. 数据库基本操作3.1 创建表(表关

oracle中exists和not exists用法举例详解

《oracle中exists和notexists用法举例详解》:本文主要介绍oracle中exists和notexists用法的相关资料,EXISTS用于检测子查询是否返回任何行,而NOTE... 目录基本概念:举例语法pub_name总结 exists (sql 返回结果集为真)not exists (s

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

Apache Tomcat服务器版本号隐藏的几种方法

《ApacheTomcat服务器版本号隐藏的几种方法》本文主要介绍了ApacheTomcat服务器版本号隐藏的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1. 隐藏HTTP响应头中的Server信息编辑 server.XML 文件2. 修China编程改错误