GaussDB(DWS)的CPU管控实现原理与演示
一、技术原理
想要搞清楚cgroup问题怎么处理,首先要理解清楚cgroup基本原理以及GaussDB(DWS)如何使用的cgroup以及使用cgroup解决了什么问题。
1.1 cgroup基本原理
cgroup全称control group,是linux内核提供的用于对进程/线程使用的资源进行隔离、管控以及记录的组件,主要包含cpu、IO、内存相关子系统。
GaussDB(DWS)应用cgroup实现了CPU管控,因此GaussDB(DWS)应用中只涉及以下CPU子系统:
- cpu子系统:限制任务的cpu使用率;
- cpuacct 子系统:统计cgroup中所有任务使用cpu的累积信息,单位ns;
- cpuset子系统:限制任务能够使用的cpu核。
cgroup的接口操作也是基于VFS实现的,可以通过mount命令查看cgroup挂载信息,每个目录对应cgroup的一个子系统。
cgroup详细原理参见GaussDB(DWS)的CPU资源隔离管控能力。
1.2 CPU管控实现
GaussDB(DWS)使用二进制文件保存cgroup配置,文件位于$GAUSSHOME/etc下面。可以通过“gs_cgroup -p”命令解析二进制文件,并显示cgroup配置信息。
1.2.1 初始化cgroup
使用gs_cgroup工具初始化cgroup配置文件,参考步骤如下:
1. echo $GAUSSHOME
2. echo $LD_LIBRARY_PATH
3. 切换至root用户
4. export LD_LIBRARY_PATH
5. $GAUSSHOME/bin/gs_cgroup -d -U user_name
6. $GAUSSHOME/bin/gs_cgroup -c -U user_name -H $GAUSSHOME
7. 此时就会生成一个cgroup配置文件:$GAUSSHOME/etc/gscgroup_[user_name].cfg
因为cgroup文件系统默认属主都是root,且普通用户没有读写权限,因此需要使用root用户在cgroup子系统文件夹下为指定用户user_name创建一个文件夹,并将属主修改为user_name。
注:集群安装时,会默认挂载cgroup,不需要用户单独初始化cgroup文件,此处只是说明步骤和原理,有兴趣的同学可以找环境验证。
1.2.2 CPU管控原理
这里我们想实现的是按业务分类管控,不同业务使用不同cpuset或不同业务间按配额比例争抢CPU资源。而只要将进程/线程关联到cgroup上,cgroup就可以自动实现CPU的隔离与调度。因此我们要做的就是识别业务类型,并按照分类将作业所属线程attach到对应cgroup即可。
GaussDB(DWS)设计实现了资源池用于资源隔离与管控,支持依据“用户-资源池”的映射关系将作业路由至对应资源池,同时提供了“键值对-资源池”的路由方式将作业路由至资源池。
这里我们主要关注CPU管控的实现,具体资源池管控实现可参考以下博客:
1. GaussDB(DWS)的query_band负载识别与应用;
2. https://bbs.huaweicloud.com/blogs/386595。
依据“用户-资源池”的映射关系或“键值对-资源池”的路由方式,可以将不同类型作业按业务需要路由至特定资源池。因此我们可以借助资源池实现CPU管控,为不同资源池创建不同的cgroup,并将cgroup与资源池关联起来。在作业路由至资源池后,将作业attach到资源池绑定的cgroup上,即可实现对业务的CPU隔离与管控。
1.2.3 gs_cgroup常用命令
1. 更新GaussDB(DWS)进程可以使用的cpu范围
gs_cgroup -u -f 0-47 -T Gaussdb
2. 创建控制组
gs_cgroup -c -N ngname //为逻辑集群ngname创建cgroup
gs_cgroup -c -N ngname -S class1 -G wg1 // 为逻辑集群ngname创建两层cgroup:class1:wg1
注:非逻辑模式下,不需要指定-N ngname,也不需要创建为逻辑集群创建cgroup。
3. 删除控制组
gs_cgroup -d -N ngname -S class1 // 删除ngname逻辑集群下class1控制组
gs_cgroup -d -N ngname -S class1 -G wg1 //// 删除ngname逻辑集群下class1:wg1控制组,说明:并不会删除class1控制组
4. 修改控制组cpuset
gs_cgroup -u -N ngname --fixed -S class1 -s 40 // 修改class1使用GaussDB(DWS)进程40%的cpu core
gs_cgroup -u -N ngname --fixed -S class1 -G wg1 -g 40 //修改wg1使用class1控制组40%的cpu core
5. 修改控制组配额权重
gs_cgroup -u -N ngname -S class1 -s 40 //修改class1的CPU配额为40%
gs_cgroup -u -N ngname -S class1 -G wg1 -g 40 //修改wg1的CPU配额为40%
6. 刷新cgroup挂载信息
gs_cgroup --refresh
7. 显示cgroup配置文件信息
gs_cgroup -p
注:打印指定逻辑集群的cgroup配置信息时需指定-N ngname。
8. 显示cgroup挂载信息
gs_cgroup -P
二、应用示例
下面设计一个小案例,探索GaussDB(DWS)如何实现的CPU管控。
1. 首先,按照1.2.1步骤初始化cgroup。
2. 创建控制组
gs_cgroup -c -S class1 -G wg1
3. 更新控制组cpuset
gs_cgroup -u -S class1 -G wg1 -g 40 --fixed
4. 创建资源池,绑定cgroup
CREATE RESOURCE POOL p1_class WITH(control_group='class1'); -- 创建父资源池
CREATE RESOURCE POOL rp1 WITH(control_group='class1:wg1',short_acc=false); --创建业务资源池
5. 创建父租户
CREATE ROLE role_p1 RESOURCE POOL 'p1_class' PASSWORD DISABLE; --父租户是没有登陆权限的,仅用于资源隔离
6. 创建用户,关联资源池
CREATE USER user_1 RESOURCE POOL 'rp1' PASSWORD 'Huawei@123' USER GROUP 'role_p1';
7. 使用用户user_1运行作业,实现CPU管控
因为资源池rp1关闭了短查询加速,因此其所有作业均受CPU管控,使用user_1运行作业过程中,查询以下SQL确认作业所属线程号:
postgres=# select a.usename,s.node_name,s.query_id,s.lwtid from gs_query_monitor a left join pgxc_thread_wait_status s on a.query_id=s.query_id where a.usename='user_1';
usename | node_name | query_id | lwtid
---------+--------------+-------------------+-------
user_1 | datanode1 | 72902018968066828 | 60673
user_1 | datanode2 | 72902018968066828 | 60674
user_1 | coordinator1 | 72902018968066828 | 61423
(3 rows)
使用“gs_cgroup -P”命令确认作业是否受cgroup管控。
- class1 (shares: 2048, cpus: 0-95)
- RemainWD:1 (shares: 1000, cpus: 0-95)
- RemainWD:2 (shares: 8000, cpus: 0-95)
- Timeshare (shares: 1024, cpus: 0-95)
- Rush (shares: 8192, cpus: 0-95)
- High (shares: 4096, cpus: 0-95)
- Medium (shares: 2048, cpus: 0-95)
- Low (shares: 1024, cpus: 0-95)
- wg1:2 (shares: 2000, cpus: 0-18,48-66)
60673 60674 61423
- TopWD:1 (shares: 9000, cpus: 0-95)
从上述命令结果可以看出,class1:wg1控制组仅能使用40%的CPU,即:0-18,48-66。因为超线程和物理核隔离,因此此处cpu编号不连续。
从上述视图结果可以看出作业在CN和DN上线程号分为为:60673、60674、61423。而在cgroup挂载信息中我们可以看到这三个线程号都attach在class1:wg1上。而class1:wg1被限制使用40%的cpu core,因此user_1的作业也只能使用这40%的cpu。
至此,我们实现了对user_1作业的CPU管控。
- 点赞
- 收藏
- 关注作者
评论(0)