Go、容器以及Linux调度器

在容器中运行Go应用程序时,需要设置合理的GOMAXPROCS,从而避免调度中因为资源不足而造成STW。原文: Go, Containers, and the Linux Scheduler

alt

Go开发的应用程序通常部署在容器中。在容器中运行时,重要的一点是要设置CPU限制以确保容器不会耗光主机上的所有CPU。但Go运行时不知道容器上设置的CPU限制,因此有可能会把所有可用的CPU都用光,从而造成应用延迟很高。这个问题曾经困扰过我,在这篇文章中,我将解释发生了什么以及如何修复。

Go垃圾收集器是如何工作的

这是对Go垃圾收集器(GC)的概要介绍,想要更深入了解,建议阅读Go文档以及Will Kennedy的系列文章[1]

绝大多数情况下,Go运行时在执行程序的同时执行垃圾收集,这意味着GC会与程序同时运行。然而,在GC过程中有两个点需要Go运行时暂停所有Goroutine,从而确保数据完整性。在GC标记阶段(Mark Phase)之前,运行时将暂停所有Goroutine,用以启用写屏障(write barrier),确保在此之后创建的任何对象都不会被GC,这个阶段称为扫描终止(Sweep Termination)。在标记阶段完成后,还有一个STW(stop the world)阶段,被称为标记终止(Mark Termination),并且也是删除写屏障的过程。整个流程通常需要几十微秒。

我创建了一个简单的web应用,分配了大量内存,并使用以下命令在一个限制为4个CPU核的容器中运行,源代码在Github[2]上。

docker run --cpus=4 -p 8080:8080 $(ko build -L main.go)

值得注意的是,docker CPU限制是硬性限制。可以设置--CPU-shares,表示只在主机CPU受限时强制执行。这意味着如果主机有空闲容量,容器可以使用超出分配的CPU核。但是如果主机资源受限,那么应用程序也将受到限制。

可以使用runtime/trace[3]包收集trace,然后用go tool trace对其进行分析。下面的trace显示了在我的机器上捕获的一个GC周期,可以看到在Proc 5中STW阶段的扫描终止和标记终止。

alt

这个GC周期只花了不到2.5ms,但我们在STW阶段花费了近10%的时间。这是相当长的一段时间,特别是对于延迟敏感应用来说。

Linux调度器

完全公平调度程序(Complete Fair Scheduler, CFS)是在Linux 2.6.23中引入的,在2023年10月份发布的Linux 6.6之前一直是默认调度程序,很可能你正在使用CFS。

CFS是一个比例共享调度器[4],意味着进程权重与允许使用的CPU内核数量成正比。例如,如果允许一个进程使用4个CPU核,那么它的权重将为4。如果一个进程被允许使用2个CPU核心,它的权重将为2。

CFS通过分配一小部分CPU时间来实现,一个4核系统每秒钟有4秒的CPU时间可以分配。当我们为容器分配多个CPU内核时,实际上是要求Linux调度器给它n个CPU的时间。

在上面的docker run命令中,指定了4个CPU,意味着容器每秒将获得4秒的CPU时间。

问题

当Go运行时启动时,为每个CPU内核创建一个操作系统线程。这意味着如果有一个16核的机器,Go运行时将创建16个操作系统线程,不管任何CGroup CPU限制。然后Go运行时使用这些操作系统线程来调度程序。

问题是Go运行时不知道CGroup的CPU限制,而是在所有16个操作系统线程上调度goroutine,意味着Go运行时预计每秒能够使用16秒的CPU时间。

由于Go运行时需要在等待Linux调度器调度的线程上停止gooutine,因此将面临长时间的STW时间,因为一旦容器使用超过了CPU配额,线程就不会被调度。

解决方案

Go通过设置GOMAXPROCS环境变量限制运行时将创建的CPU线程数量。这一次,使用以下命令来启动容器:

docker run --cpus=4 -e GOMAXPROCS=4 -p 8080:8080 $(ko build -L main.go)

下面是从与上面相同的应用程序捕获的trace,现在使用与CPU配额匹配的GOMAXPROCS环境变量。

alt

在这个trace中,尽管负载完全相同,但垃圾收集时间要短得多。GC周期小于1ms,STW时间为26μs,约为无限制时的1/10。

GOMAXPROCS应该设置为容器允许使用的CPU核数,通常情况应该向下取整,如果分配的CPU内核少于1个,则向上取整。可以用GOMAXPROCS=max(1, floor(cpu))来计算。Uber开源了一个库automaxprocs来自动从容器的cgroups中计算这个值。

有一个Github问题支持将这个特性添加到Go运行时中,使其开箱即用,希望最终会被Go运行时接受!

结论

在容器化应用程序中运行Go时,设置CPU限制非常重要。通过设置合理的GOMAXPROCS值或使用像automaxprocs这样的库,确保Go运行时意识到这些限制也很重要。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

参考资料
[1]

Garbage Collection In Go: https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html

[2]

示例代码: https://github.com/RiverPhillips/go-cfs-blog

[3]

runtime/trace package: https://golang.org/pkg/runtime/trace

[4]

Proportional share scheduling: https://en.wikipedia.org/wiki/Proportional_share_scheduling

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/247354.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MacOS X 中 OpenGL 环境搭建 Makefile的方式

1,预备环境 安装 brew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 安装glfw: brew install glfw 安装glew: brew install glew 2.编译 下载源代码…

喜报|「云原生数据库PolarDB」、「阿里云瑶池一站式数据管理平台」揽获“2023技术卓越奖”

日前,国内知名IT垂直媒体&技术社区IT168公布2023年“技术卓越奖”评选结果,经由行业CIO/CTO大咖、技术专家及IT媒体三方的联合严格评审,阿里云瑶池数据库揽获两项大奖:云原生数据库PolarDB荣获“2023年度技术卓越奖”&#xf…

【双目】双目精度评估完整方案,可以直接使用(内涵数据,代码和评估报告)

【双目】基于findChessboardCorners的双目精度评估,可以直接使用 数据和代码见 运行结果: 结论与分析: 在使用鱼眼相机进行双目精度上限评估时,出现1米距离的误差大于2米距离的误差可能有几个原因: 畸变影响&#x…

网络协议与攻击模拟_09部署DHCP服务器

一、部署DHCP服务器 Windows server部署DHCP服务器 1、虚拟机网络架构理解 Vmware里面不同的虚拟机可以设置相同的Vmnet网络,也可以设置不同的Vmnet网络。两台虚拟机设置相同的Vmnet1网卡,可以看作为使用虚拟交换机将两台Vmnet1的虚拟机连接起来的。 …

深入理解HarmonyOS UIAbility:生命周期、WindowStage与启动模式探析

UIAbility组件概述 UIAbility组件是HarmonyOS中一种包含UI界面的应用组件,主要用于与用户进行交互。每个UIAbility组件实例对应最近任务列表中的一个任务,可以包含多个页面来实现不同功能模块。 声明配置 为了使用UIAbility,首先需要在mod…

【C/C++】C/C++编程——变量和常量

文章目录 变量变量的声明变量命名规则变量的类型 常量常量的定义与初始化字面量常量整型常量浮点型常量字符常量常量表达式(constexpr) 大家好,我是 shopeeai,也可以叫我虾皮,中科大菜鸟研究生。今天我们来一起来学习C…

2.【Vue3】Vue 基本使用——局部使用Vue

1. 快速入门 现在需要将 “hello vue3” 这样一个字符串渲染到页面上进行展示。 这个需求并不陌生,可以使用原生 JS 代码完成: let msg"hello vue3"; document.getElementById("元素的id属性值").innerHTMLmsg;接下来学习如何使用…

麒麟系统—— openKylin 安装 mongodb

麒麟系统—— openKylin 安装 mongodb 一、准备工作1. 确保麒麟系统 openKylin 已经安装完毕。 二、下载解压 MongoDB二、增加环境变量三、配置MongoDB创建数据目录创建日志文件运行 四、加入到服务中 MongoDB是一款高性能、开源的NoSQL数据库,因其灵活的数据结构、…

机器学习:梯度下降法(Python)

LinearRegression_GD.py import numpy as np import matplotlib.pyplot as pltclass LinearRegression_GradDesc:"""线性回归,梯度下降法求解模型系数1、数据的预处理:是否训练偏置项fit_intercept(默认True)&…

【面试】测试开发面试题

帝王之气,定是你和万里江山,我都护得周全 文章目录 前言1. 网络原理get与post的区别TCP/IP各层是如何传输数据的IP头部包含哪些内容TCP头部为什么有浮动网络层协议1. 路由协议2. 路由信息3. OSPF与RIP的区别Cookie与Session,Token的区别http与…

解决Linux部署报错No main manifest attribute, in XXX.jar

这是我近期遇到的一个问题,报错原因就是没找到主类,首先你在你本地运行,本地运行ok的话,解压生成的jar包,里面有个META-INF文件,打开MANIFEST.MF文件,该文件是一个清单文件。该文件包含有关JAR文…

11. 双目视觉之立体视觉基础

目录 1. 深度恢复1.1 单目相机缺少深度信息1.2 如何恢复场景深度?1.3 深度恢复的思路 2. 对极几何约束2.1 直观感受2.2 数学上的描述 1. 深度恢复 1.1 单目相机缺少深度信息 之前学习过相机模型,最经典的就是小孔成像模型。我们知道相机通过小孔成像模…

汽车网络安全dos, someip

汽车Cyber Security入门之DoS 攻防 - 知乎 3、SOME/IP-TP 近年来火热地谈论下一代EE架构和SOA的时候,总离不开SOME/IP这个进程间通讯协议。在许多应用场景中,需要通过UDP传输大型的SOME/IP有效载荷。鉴于在以太网上传输数据包的大小限制,SO…

Linux文件管理(下)

上上篇介绍了Linux文件管理的上部分内容,这次继续将 Linux文件管理的剩余部分说完。内容如下。 一、查看文件内容 1、cat 命令 1.1 输出文件内容 基本语法: cat 文件名称主要功能:正序输出文件的内容。 eg:输出 readme.txt文…

剧本杀小程序的诞生:重塑线下娱乐的数字化未来

随着科技的不断发展,人们对于娱乐方式的需求也在不断升级。近年来,剧本杀作为一种新型的线下社交娱乐方式,以其独特的魅力和深度的人际互动性,受到了广大年轻人的喜爱。然而,传统的剧本杀模式存在一些问题,…

中间件安全

中间件安全 vulhub漏洞复现:https://vulhub.org/操作教程:https://www.freebuf.com/sectool/226207.html 一、Apache Apache(音译为阿帕奇)是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和…

录屏软件哪个好?为您提供最佳选择(最新)

随着科技的进步,录屏软件已成为我们日常生活和工作中不可或缺的工具。无论是为了制作教程、会议记录还是游戏录像,一款优秀的录屏软件都是必不可少的。可是录屏软件哪个好呢?在本文中,我们将介绍两款常用的录屏软件,并…

uniapp 实现路由拦截,权限或者登录控制

背景: 项目需要判断token,即是否登录,登录之后权限 参考uni-app官方: 为了兼容其他端的跳转权限控制,uni-app并没有用vue router路由,而是内部实现一个类似此功能的钩子:拦截器,由…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之CheckboxGroup组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之CheckboxGroup组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、CheckboxGroup组件 提供多选框组件,通常用于某选项的打开或关…

Apollo Cyber RT:引领实时操作系统在自动驾驶领域的创新

🎬 鸽芷咕:个人主页 🔥 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! ⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…