Go基于I/O多路复用的TCP协议流解析实践

本文永久链接 – https://tonybai.com/2021/07/31/io-multiplexing-model-tcp-stream-protocol-parsing-practice-in-go 在《Go经典阻塞式TCP协议流解析的实践》一文中,我们基于Go经典的阻塞I/O模型实现了一个基于TCP流的自定义协议的解析。这种one-connection-per-goroutine模型的优点就是简单、好写以及好理解,降低开发者心智负担。但一旦连接数上来,goroutine的数量就会线性增加。当面对海量连接的场景,这种模型将力不从心:系统中将存在大量goroutine,goroutine调度和切换的开销过多。 那么面对海量连接场景,应该如何解决呢?业界成熟方案:使用I/O多路复用模型。了解Go net包实现的朋友想必都知晓Go在运行时底层使用的也是I/O多路复用,其实现为runtime中的netpoll。goroutine层面获得的net.Conn(无论是Accept的,还是Dial得到的)都展现出“阻塞”的特征,但这些net.Conn底层实现的fd(文件描述符)在netpoll中都是non-blocking(非阻塞)的,Go运行时负责调用epoll等多路复用机制监视这些fd是否可读或可写,并适时唤醒goroutine继续网络I/O操作,这种方式减少了系统调用,也减少了运行Goroutine的M(操作系统线程)因系统调用陷入内核态等待的频率以及因阻塞失去M而不得不去创建新线程的数量。 ...

July 31, 2021 · 11 min · Tony Bai

Go语言对ARM架构的支持与未来[译]

本文翻译自Go官方博客文章《Go on ARM and Beyond》(https://blog.golang.org/ports)。 最近业界关于非x86处理器的讨论沸沸扬扬,所以我们认为值得简单的写一篇关于Go语言对这些非x86处理器的支持情况的文章。 ...

December 18, 2020 · 6 min · Tony Bai

图解Go运行时调度器

本文翻译自《Illustrated Tales of Go Runtime Scheduler》。 译注:原文章结构有些乱,笔者自行在译文中增加了一些分级标题,让结构显得更清晰一些:)。 多goroutines形式的Go并发是编写现代并发软件的一种非常方便的方法,但是您的Go程序是如何高效地运行这些goroutines的呢? 在这篇文章中,我们将深入Go运行时底层,从设计角度了解Go运行时调度程序是如何实现其魔法的,并运用这些原理去解释在Go性能调试过程中产生的Go调度程序跟踪信息。 ...

March 21, 2020 · 16 min · Tony Bai

可视化Go内存管理

本文翻译自《Visualizing memory management in Golang》。 “内存管理”系列的一部分 在这个由多部分组成的系列文章中,我旨在揭示内存管理背后的概念,并对某些现代编程语言的内存管理机制做更深入的探究。我希望该系列文章可以使您对这些语言在内存管理方面正在发生的事情能有所了解。 ...

March 10, 2020 · 11 min · Tony Bai

图解Go内存分配器

本文翻译自《A visual guide to Go Memory Allocator from scratch (Golang)》。 当我刚开始尝试了解Go的内存分配器时,我发现这真是一件可以令人发疯的事情,因为所有事情似乎都像一个神秘的黑盒(让我无从下手)。由于几乎所有技术魔法都隐藏在抽象之下,因此您需要逐一剥离这些抽象层才能理解它们。 在这篇文章中,我们就来这么做(剥离抽象层去了解隐藏在其下面的技术魔法)。如果您想了解有关Go内存分配器的知识,那么本篇文章正适合您。 ...

February 20, 2020 · 12 min · Tony Bai

也谈Go的可移植性

Go有很多优点,比如:简单、原生支持并发等,而不错的可移植性也是Go被广大程序员接纳的重要因素之一。但你知道为什么Go语言拥有很好的平台可移植性吗?本着“知其然,亦要知其所以然”的精神,本文我们就来探究一下Go良好可移植性背后的原理。 一、Go的可移植性 说到一门编程语言可移植性,我们一般从下面两个方面考量: 语言自身被移植到不同平台的容易程度; 通过这种语言编译出来的应用程序对平台的适应性。 在Go 1.7及以后版本中,我们可以通过下面命令查看Go支持OS和平台列表: ...

June 27, 2017 · 10 min · Tony Bai

也谈goroutine调度器

Go语言在2016年再次拿下TIBOE年度编程语言称号,这充分证明了Go语言这几年在全世界范围内的受欢迎程度。如果要对世界范围内的gopher发起一次“你究竟喜欢Go的哪一点”的调查,我相信很多Gopher会提到:goroutine。 Goroutine是Go语言原生支持并发的具体实现,你的Go代码都无一例外地跑在goroutine中。你可以启动许多甚至成千上万的goroutine,Go的runtime负责对goroutine进行管理。所谓的管理就是**“调度”,粗糙地说调度**就是决定何时哪个goroutine将获得资源开始执行、哪个goroutine应该停止执行让出资源、哪个goroutine应该被唤醒恢复执行等。goroutine的调度是Go team care的事情,大多数gopher们无需关心。但个人觉得适当了解一下Goroutine的调度模型和原理,对于编写出更好的go代码是大有裨益的。因此,在这篇文章中,我将和大家一起来探究一下goroutine调度器的演化以及模型/原理。 ...

June 23, 2017 · 14 min · Tony Bai

理解Unikernels

当Docker, Inc在今年年初宣布收购Unikernel Systems公司时,Unikernel对大多数技术人员来说还是很陌生的。直到今天,知名问答类网站知乎上也没有以Unikernel为名字的子话题。国内搜索引擎中关于Unikernel的内容很少,实践相关的内容就更少了。Docker收购Unikernel Systems,显然不是为了将这个其未来潜在的竞争对手干掉,而是嗅到了Unikernel身上的某些技术潜质。和关注Docker一样,本博客后续将持续关注Unikernel的最新发展和优秀实践,并将一些国外的优秀资料搬(翻)移(译)过来供国内Unikernel爱好者和研究人员参考。 ...

May 16, 2016 · 10 min · Tony Bai

Ubuntu 12.04修复记

今天一早发现Ubuntu 12.04坏掉了,于是用了大半天对其做了修复,修复过程十分坎坷,但结果还不错,遂记之以备忘。 * 毁掉Ubuntu Ubuntu坏掉完全是由于我的错误决策。昨天一天Ubuntu桌面右上方的状态拦一直有一个红色的错误提示符,提示系统包冲突,建议执行sudo apt-get install -f解决。apt-get也提示索引冲突,无法卸载和安装任何包。于是执行了sudo apt-get install -f,虽然我不知道这个命令对系统做了哪些更改。但结果是那个错误提示符的确不见了。 ...

August 7, 2013 · 4 min · Tony Bai

一种基于内存映射文件的系统运行数据提取方法

这是我无意中想到的一个方法,估计这个方法已经不是什么新鲜的东西了,很可能在类似的问题场景中早已经被使用了。不过这里还是要说说我的思维过程。 近期在学习一些Linux性能查看和分析方面的工具,比如top、iostat、vmstat以及sar等。在学习过程中我发现这些工具有个共同的特点,那就是她们采集的Linux运行数据都是从/proc下的文件中实时获取并计算而得出的。众所周知,/proc是Linux内核维护的一个虚拟文件系统,他允许用户在Linux运行时查看内核运行数据(用户可以像查看普通文件一样查看/proc下的目录和文件),甚至是运行时实时改变内核设置。Linux实现/proc的细节不是这里要关注的,吸引我的是Linux的这种提取运行数据的设计。这个设计将Linux运行数据的产生实现细节与第三方性能采集工具间的耦合最大化地解开,这样一来/proc就像是一种Linux的基础服务,为用户提供一种实时的运行数据信息。而用户侧的运行数据查看工具也可以根据用户的需求自由定制,因此有了top、iostat、vmstat、iotop、sar等关注点不同的工具。 ...

March 18, 2013 · 6 min · Tony Bai