![ee41f58730714a28597210f09e27cc61.png](https://img-blog.csdnimg.cn/img_convert/ee41f58730714a28597210f09e27cc61.png)
上一章中对于golang的常用关键字说明如下:
- 1 for 和 range
- 2 select
- 3 defer
- 4 panic 和 recover
- 5 make 和 new
接下来我们来对golang的并发编程进行说明,主要内容有:
- 1 上下文 Context
- 2 同步原语与锁
- 3 定时器
- 4 Channel
- 5 调度器
- 6 网络轮询器
- 7 系统监控
— — — — — — — — — — — — — — — — — — — — — — — — — — — —
很多系统中都有守护进程,它们能够在后台监控系统的运行状态,在出现意外情况时及时响应。系统监控是 Go 语言运行时的重要组成部分,它会每隔一段时间检查 Go 语言运行时,确保程序没有进入异常状态。本节会介绍 Go 语言系统监控的设计与实现原理,包括它的启动、执行过程以及主要职责。
7.1 设计原理
在支持多任务的操作系统中,守护进程(Daemon)是在后台运行的计算机程序。守护进程不会由用户直接操作,它一般会在操作系统启动时自动运行。Kubernetes 的 DaemonSet 和 Go 语言的系统监控都使用类似设计提供一些通用的功能:
![503e9a02bf349f2e54e168800fc5c382.png](https://img-blog.csdnimg.cn/img_convert/503e9a02bf349f2e54e168800fc5c382.png)
守护进程是很有效的设计,它在整个系统的生命周期中都会存在,会随着系统的启动而启动,系统的结束而结束。在操作系统和 Kubernetes 中,我们经常会将数据库服务、日志服务以及监控服务等进程作为守护进程运行。
Go 语言的系统监控也起到了很重要的作用,它在内部启动了一个不会中止的循环,在循环的内部会轮询网络、抢占长期运行或者处于系统调用的 Goroutine 以及触发垃圾回收,通过这些行为,它能够让系统的运行状态变得更健康。
7.2 监控循环
当 Go 语言程序启动时,运行时会在第一个 Goroutine 中调用 runtime.main
启动主程序,该函数会在系统栈中创建新的线程:
func main() {
...
if GOARCH != "wasm" {
systemstack(func() {
newm(sysmon, nil)
})
}
...
}
runtime.newm
会创建一个存储待执行函数和处理器的新结构体 runtime.m
。运行时执行系统监控不需要处理器,系统监控的 Goroutine 会直接在创建的线程上运行:
func newm(fn func(), _p_ *p) {
mp := allocm(_p_, fn)
mp.nextp.set(_p_)
mp.sigmask = initSigmask
...
newm1(mp)
}
runtime.newm1
会调用特定平台的 runtime.newsproc
通过系统调用 clone
创建一个新的线程并在新的线程中执行 runtime.mstart
:
func newosproc(mp *m) {
stk := unsaf