南大通用GBase 8a通过taskset绑定CPU的内核来部分限制CPU使用率

GBase 8a数据库可以通过cgroup功能,对CPU使用率实现相对精确的控制,本文介绍一种通过linux自带的taskset功能,绑定CPU的具体内核,来实现部分的CPU使用率。该功能在V9.5.3的多实例版本里,已经内置实现了对一个实例绑定哪些CPU的功能,如果V8和V952等版本,可以考虑本文介绍的方法实现粗粒度的CPU使用率控制。

由于限制粒度在核心数量一级,所以无法做到cgroup那样的精确控制,只能成比例的部分控制使用率。

taskset 介绍

有关taskset的详细,可以从搜索引擎查找,如下是我参考的一个文章。

https://blog.csdn.net/guotianqing/article/details/80958281

查看CPU内核信息

如下是1个4核的CPU输出信息。可用核心编号是0-3. 注意从0开始。

[root@rh6-1 ~]# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 142
model name      : Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
stepping        : 9
cpu MHz         : 2712.000
cache size      : 3072 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 4
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good xtopology nonstop_tsc unfair_spinlock pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase avx2 invpcid
bogomips        : 5424.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 142
model name      : Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
stepping        : 9
cpu MHz         : 2712.000
cache size      : 3072 KB
physical id     : 0
siblings        : 4
core id         : 1
cpu cores       : 4
apicid          : 1
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good xtopology nonstop_tsc unfair_spinlock pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase avx2 invpcid
bogomips        : 5424.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

processor       : 2
vendor_id       : GenuineIntel
cpu family      : 6
model           : 142
model name      : Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
stepping        : 9
cpu MHz         : 2712.000
cache size      : 3072 KB
physical id     : 0
siblings        : 4
core id         : 2
cpu cores       : 4
apicid          : 2
initial apicid  : 2
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good xtopology nonstop_tsc unfair_spinlock pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase avx2 invpcid
bogomips        : 5424.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

processor       : 3
vendor_id       : GenuineIntel
cpu family      : 6
model           : 142
model name      : Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
stepping        : 9
cpu MHz         : 2712.000
cache size      : 3072 KB
physical id     : 0
siblings        : 4
core id         : 3
cpu cores       : 4
apicid          : 3
initial apicid  : 3
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good xtopology nonstop_tsc unfair_spinlock pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase avx2 invpcid
bogomips        : 5424.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

查看绑定的CPU内核

不带c参数的是显示掩码mask, 带c参数的是具体的核数。如下例子中,绑定的是0号。

[root@rh6-1 ~]# taskset -p `pidof gbased`
pid 9381's current affinity mask: 1

[root@rh6-1 ~]# taskset -pc `pidof gbased`
pid 9381's current affinity list: 0

动态设置单个进程、线程绑定的CPU内核

如下是修改某个进程或线程的方法

[root@rh6-1 ~]# taskset -pc 0-1 `pidof gbased`
pid 9381's current affinity list: 0
pid 9381's new affinity list: 0,1
[root@rh6-1 ~]# taskset -pc `pidof gbased`
pid 9381's current affinity list: 0,1
[root@rh6-1 ~]#

绑定进程和其子线程

因为某个进程可能打开了多个线程,如果要整体限制,需要每个子线程都限制。

ps -T -p `pidof gbased` | cut -d' ' -f 4|while read line; do echo --$line--;taskset -pc 0,1 $line;done;

启动进程时指定

在进程启动命令前,增加taskset命令,来指定进程绑定的CPU内核

taskset -c 0 gbased

GBase 8a的修改

动态修改

GBase 8a的内核绑定,可以通过如上的【绑定进程和其子线程】方法,对每个需要限制的进程做【动态设置】,主要是gcware/corosync, gclusterd,gbased, 几个。其它的gcrecover,sync_server等一般是系统同步等时候才会用到。

修改启动程序

修改gcluster_services服务启停程序,增加taskset参数,实现对所有服务的CPU内核绑定

该程序位于如下2个位置,都需要修改

/opt/gcluster/server/bin/gcluster_services
/opt/gnode/server/bin/gcluster_services

修改内容,是查找如下代码部分,一般位于function __start()函数部分

 $2 > /dev/null 2>&1 &

此部分是用于启动服务进程,在前面增加需要绑定的CPU内核

taskset -c 0-1 $2 > /dev/null 2>&1 &

然后对所有服务重启即可。

注意

该种方法,直接修改数据库核心文件,会导致checksum报错,所以要关闭文件检查功能(skip_file_check=1), 详情请参考 GBase 8a集群打补丁时需要关闭文件检查功能的参数skip_file_check

V8版本

V8数据库版本,在通过service gcware 服务启动时,并没有调用gcluster_services, 所以需要在修改服务脚本,V9不需要这个。

注意,V8版本的服务,在意外停止后被gcmonit拉起时,同样通过gcluster_services实现的,所以前面章节的修改同样要做。

脚本

均保存在/etc/init.d下(redhat)如果其它操作系统,请找一下对应版本,服务自启动的位置。

-rwxr-xr-x  1 root root  3343 Oct 25 12:31 corosync
-rwxr-xr-x  1 root root  1246 Oct 25 12:31 monit
-rwxr-x---  1 root root  3011 Oct 25 12:31 gcrecover
-rwxr-x---  1 root root  2969 Oct 25 12:31 gclusterd
-rwxr-x---  1 root root  3996 Oct 25 12:31 gcware
-rwxr-x---  1 root root  2926 Oct 25 12:31 gcsync
-rwxr-x---  1 root root  3259 Oct 26 11:46 gbased
[root@rh6-1 init.d]# pwd
/etc/init.d

修改样例

由于gbased是最核心的组件,如下以gbased的启动服务修改为例,如下是启动部分

        if [ -x "$daemon_path" ];then
            start_daemon -u $GCLUSTER_USER -g $GCLUSTER_GROUP -p $PID_FILE $exec > /dev/null 2>&1 &
        else
            if [ -d /etc/sysconfig ]; then # SuSE
                daemon --user $GCLUSTER_USER  --pidfile $PID_FILE $exec > /dev/null 2>&1 &
            else #debian
                start-stop-daemon --start --oknodo --user $GCLUSTER_USER --name gbased --pidfile $PID_FILE --startas $exec --chuid $GCLUSTER_USER > /dev/null 2>&1 &

增加taskset的设定

        if [ -x "$daemon_path" ];then
            start_daemon -u $GCLUSTER_USER -g $GCLUSTER_GROUP -p $PID_FILE taskset -c 0-1 $exec > /dev/null 2>&1 &
        else
            if [ -d /etc/sysconfig ]; then # SuSE
                daemon --user $GCLUSTER_USER  --pidfile $PID_FILE taskset -c 0-1 $exec > /dev/null 2>&1 &
            else #debian
                start-stop-daemon --start --oknodo --user $GCLUSTER_USER --name gbased --pidfile $PID_FILE --startas taskset -c 0-1 $exec --chuid $GCLUSTER_USER > /dev/null 2>&1 &

建议再对gclusted和corosync共三个组件做修改即可,和故障修复有关的进程,个人不建议调整,还是尽快恢复优先。

numactl 的方案

硬件情况

CPU核心数量,node数量。

[gbase@rh6-1 ~]$ numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 4095 MB
node 0 free: 3265 MB
node distances:
node   0
  0:  10

绑定CPU

通过numactl也可以实现进程的CPU绑定,样子类似

numactl -C 1,3 gbased

在启动脚本里,改动成如下样子,绑定核心1和3

numactl -C 1,3 $2 > /dev/null 2>&1 &

重启后查看效果

[gbase@rh6-1 ~]$ vi /opt/gcluster/server/bin/gcluster_services
[gbase@rh6-1 ~]$ gcluster_services gbase restart
Stopping gbase :                                           [  OK  ]
Starting gbase :                                           [  OK  ]
[gbase@rh6-1 ~]$ taskset -c -p `pidof gbased`
pid 3379's current affinity list: 1,3

没有看到动态调整的方案

同时绑定内存

如下绑定了CPU的核心0和1,已经内存的0-1。

numactl --cpunodebind=0,1 --membind=0 $2 > /dev/null 2>&1 &
--membind=nodes, -m nodes 
  Only allocate memory from nodes. Allocation will fail when there is not enough 
  memory available on these nodes.