Go 服务开发高手课
15
15
1.0x
00:00/00:00
登录|注册

09|网络编程:如何进行网络IO编程降消耗,提吞吐?

你好,我是徐逸。
前面,我们花了不少篇幅一同深入学习了 Go 服务高性能编码技巧,来全力保障线上服务的性能。不过呢,除了我们写的业务逻辑代码,服务框架本身对于性能也有着举足轻重的影响。而影响框架性能的一个很重要的因素,就是框架所使用的网络 IO 模型。
今天我们就来聊聊网络 IO 模型、epoll 技术和 Golang 底层网络 IO 的原理。掌握网络 IO 模型、epoll 技术和 Golang 底层网络 IO 原理,不仅有助于你更好地做框架选型,而且还能提升你使用 Go 开发更底层网络程序的能力。

网络 IO 模型

在介绍具体的网络 IO 模型之前,先让我们来想一想,一次网络 IO 的过程大概是什么样的呢?
就像下面的图一样,以读 IO 为例,网络数据要被咱们的应用程序接收到,可以划分为下面两个阶段。
数据准备阶段,驱动程序和操作系统内核从网卡读取数据到 socket 的接收缓冲区。
数据复制阶段,由应用程序将内核空间 socket 缓冲区的数据复制到用户空间。
图1 网络数据传输
应用程序对这两个阶段的不同处理方式,就形成了不同的网络 IO 模型。那么应用程序对这两个阶段有哪几种处理方式呢?

阻塞 IO

我们先来看看数据准备阶段的处理方式。就像下面的图一样,当我们的应用程序进行网络 IO 调用时,如果 socket 缓冲区还没有准备好,我们可以让应用线程阻塞在 IO 调用方法里,而不直接返回,这就是阻塞 IO 模型
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
  • 解释
  • 总结

1. 网络IO模型包括阻塞IO、非阻塞IO、IO多路复用和异步IO,每种模型都有其优缺点和适用场景。 2. IO多路复用通过epoll技术可以在一个线程里阻塞监听多个连接的网络IO事件,避免线程不断轮询消耗CPU资源,同时确保应用线程能及时感知网络IO就绪事件,避免处理请求不及时。 3. epoll技术是Linux内核提供的I/O多路复用技术,包括epoll_create、epoll_ctl和epoll_wait三个系统调用,能够提供更好的性能和扩展性,特别适用于高并发的网络服务器程序。 4. Golang底层巧妙运用网络IO模型和epoll技术,实现高性能网络通信,通过netpollinit、netpollopen、netpollblock等方法实现网络IO就绪事件的感知和协程唤醒。 5. Golang的net库实现了一个简单的TCP服务器,核心方法包括Listen、Accept、Read和Write,底层调用隐藏了I/O多路复用和epoll技术的细节。 6. Golang运行时通过sysmon监控任务、协程调度流程和GC流程,调用操作系统的epoll_wait方法完成网络IO就绪事件的感知和协程唤醒操作。 7. 网络IO模型有阻塞IO、非阻塞IO、IO多路复用和异步IO多种类型,实践中比较常用的是IO多路复用模型。 8. Linux底层的多路复用技术——epoll,操作系统提供了epoll_create、epoll_ctl和epoll_wait三个方法给我们使用,在使用时需要注意触发模式的选择。 9. Golang底层巧妙运用网络IO模型和epoll技术,实现高性能网络通信,通过netpollinit、netpollopen、netpollblock等方法实现网络IO就绪事件的感知和协程唤醒。 10. Golang的net库实现了一个简单的TCP服务器,核心方法包括Listen、Accept、Read和Write,底层调用隐藏了I/O多路复用和epoll技术的细节。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 服务开发高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(2)

  • 最新
  • 精选
  • lJ
    1. 老师能讲一讲io_uring吗,有哪些知名的应用,大厂的态度,Golang的支持情况等 2. epoll ET模式存在数据丢失的风险,如果接收缓冲区足够大的情况下,还存在丢失吗,后续新的数据到达重新触发通知,应用程序应该可以读取到之前未读完的数据吧 3. golang net是如何解决数据丢失的风险的,在使用epoll ET编程时有哪些开发规范或最佳实践应对这个问题 4. 思考题 golang net设计了 BIO模式的 API,为每个连接都分配一个 goroutine。 这在高并发下,会产生大量的 goroutine,需要频繁的上下文切换,增大Goroutine 调度器的开销。 a. evio,使用事件驱动模型,采用单线程或多线程事件循环,比协程并发模型更轻量。 b. netpoll,使用gopool池、高效的内存复用、支持检查连接是否存活,可以及时清理池中失效的连接,降低资源占用。 c. gnet,也是使用ants池,高效、可重用而且自动伸缩的内存 buffer。 以上三个库没有看过源码,简单看了官方文档。个人觉得,evio与netpoll,gnet的不同之处是抛开了协程并发模型,完全基于epoll事件循环模型。而后两者还是采用协程模型,主要使用了协程池,内存池优化达到资源复用,减轻了调度器和GC开销。
    2024-12-27归属地:江苏
  • CodeFish-Xiao
    感觉这篇的质量跟之前比下降了,Golang运行时的网络实现和Linux本身的IO复用优化,但是实际上我们用Golang进行网络编程该进行哪些优化没有讲到
    2024-12-27归属地:广东
收起评论
显示
设置
留言
2
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部