You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Right now we're watching the Go issue to fix this for all go applications in the standard library / runtime. There's recent indication that the Go team plan to make Go aware of this.
Go 程序启动时候会根据 CPU 数量设置 GOMAXPROCS,比如下面的程序中在 8 核处理下输出为 8。
当我们使用 Docker 的时候也是如此,不过当我们使用 docker run 的时候同时限制了 CPU 数量,那么程序中会正常显示吗?
不会,比如
docker run --cpus=2 IMAGE
,输出还是宿主机的数量。这样就带来一个问题,如果宿主机是一个配置特别大的机器,同时限制了运行容器的 CPU ,那么就会造成 GOMAXPROCS 过大,程序运行中也会过多生成线程。
线程越多,但是 CPU 很少,这就造成线程调度负担,从而导致程序运行变慢。
所以需要去提前设置 GOMAXPROCS 为准确的值,uber 开源了 uber-go/automaxprocs 库,就很好的解决了这个问题,使用很简单。
重新构造 Docker 镜像,再运行,可以看到这里适配了准确的 CPU 数量后自动打印了数据。
这样就很OK了,另外还有一个可选项 LXCFS。什么是 LXCFS ?docker 资源控制的原理的是使用了 cgroup,可以参考耗子叔的文章具体了解。
程序不能获取 cpu 限制,问题出在 docker 直接挂载 cgroup 信息到容器的
/sys/fs/cgroup
目录下,而 lxcfs 所做的就是让这些信息重新挂载到/proc
目录下。接下来介绍如何使用 lxcfs,首先在机器上安装 lxcfs
yum install -y fuse fuse-lib fuse-devel libtool git clone --branch=lxcfs-4.0.6 --depth=1 https://github.com/lxc/lxcfs cd lxcfs ./bootstrap.sh ./configure make make install
然后可以根据
which lxcfs
获取到已经安转到/usr/local/bin/lxcfs
,接着配置 systemd 守护进程第一步,创建lxcfs mount 目录
mkdir -p /var/lib/lxcfs
,接着配置 systemd然后就可以启动lxcfs进程,并设置开机启动
最后验证查看启动状态
如果你遇到
Process: 25502 ExecStopPost=/usr/bin/fusermount -u /var/lib/lxcfs (code=exited, status=1/FAILURE)
的错误,目前看这是正常的。这样我们就可以验证结果了,输出的 cpu 数量就是 2。
用上面的 go 程序不能验证结果,这是因为 docker 具体而言使用了 CFS公平调度算法 限制容器的 CPU 使用,虽然 lxcfs 成功挂载了必要信息到
/proc/cpuinfo
里,但是 golang 运行时通过 sched_getaffinity系统调用来获取 cpu 数量,所以 lxcfs 还是不能彻底解决问题。这个问题目前没有解决,可以订阅这个 golang: runtime: make GOMAXPROCS cfs-aware on GOOS=linux 问题进行跟踪。上面介绍的 uber 开源的 automaxprocs 库解决这个问题的思路是读取 cgroup 信息,然后在启动的时候就设置 GOMAXPROCS。
另外你用 lscpu不能验证结果,也是同样的道理,都是系统调用,lxcfs 并不能拦截系统调用。
The text was updated successfully, but these errors were encountered: