commit cda745b19c3596e890d11f80d2d2a861e8c6797a Author: Davidze Date: Wed Aug 16 14:16:37 2017 +0800 实现对多核Linux CPU% 的期望占用 diff --git a/cpu_scheduler.sh b/cpu_scheduler.sh new file mode 100755 index 0000000..9c1a361 --- /dev/null +++ b/cpu_scheduler.sh @@ -0,0 +1,183 @@ +#! /bin/bash +#! -*- coding=utf-8 -*- +# Author:zhouze03 +# Date: 2017-08-15 + +###### +# 期望当正经的CPU%使用率 < 期望值时 ; 可以启动额外的任务来提升CPU的使用率; +# 备注: +# 1. 当前程序作为附加程序,要做到”不得已而用之“; +# 2. 本程序会调用一个非常消耗CPU的脚本程序:这个进程暂且称之为”greedy(贪婪的)进程“(死循环脚本) +# 3. 服务器其它的进程都认为是online的进程; +###### + +# 1. 当前CPU总使用率(排除/kill贪婪进程);(CURR_CPU_RATE) +# 2. 某进程CPU总使用率:(greedy_process_cpu_rate)(舍弃) +# 3. 期望的CPU% 使用百分值;(EXPECT_CPU_RATE) +# 4. 逻辑CPU的个数 CPU_LOGI_NUM + +############ +# 算法: +# 无限循环语句: +# 0. 每5分钟检查一次; +# 1. 由于当前的进程CPU使用率不好获取,因此,使用直接kill贪婪进程的方式(如果有进程),然后获取此刻的CPU使用率(该使用率 = 正经CPU使用率) +# 2. 获取当前的CPU% 使用率; +# 3. 获取贪婪值:GREEDY_VALUE=(EXPECT_CPU_RATE - CURR_CPU_RATE) +# Case1: GREEDY_VALUE > 0; then +# 本次贪婪占用核数目 =(CPU核数目 * 贪婪值(0.0-1))向下取整 && 启动与贪婪核数目相同的进程数目;(通过cpulimit 限制贪婪进程最高占用95%CPU) +# 备注: +# 使用cpulimit 只运行单进程对单核的使用上限为95% 是为了避免超过100%不可预期的异常。(不确定超过100% 是否会造成问题,因此保险起见进行了限制) +# 其次,线程可控,该程序脚本的线程上限为CPU的核数目,不会为了打满CPU而创建过的线程的情况,(Linux 用户线程有上限,避免影响线上(正经)的服务) +# 备注(重点): +# 单个贪婪进程所占用的CPU% : +# 1. 如果当前机器总CPU% < 50%; then: 可以使得单贪婪进程CPU% > 80%; (如果一半的CPU逻辑单元被占满不会影响其它服务可以这样设置,否则按下面的方式) +# 2. 如果当前服务器上正经的服务对CPU逻辑单元需求很大,则设置单个贪婪进程CPU% <= 50% , 同时贪婪进程个数增加, +# 这样虽在表面上看起来两个50% 的进程占用了100%,但是在CPU的并发度上是不同的,其它的进程有机会去获取CPU时间片去执行它们的程序; +# 简而言之: +# CPU_LIMIT_FOR_GREEDY_PROCESS 确定了贪婪进程的个数与进程所占的比例 +############ + + +# 设定期望值(改为main参数确定) +# EXPECT_CPU_RATE=50 +# 贪婪进程比例的设定 (改为main参数确定) +# CPU_LIMIT_FOR_GREEDY_PROCESS=50 + +# 当前CPU% +function get_curr_cpu_rate(){ + local curr_cpu_rate=`env LC_ALL=en_US.UTF8 sar 1 1 | grep ^Average | awk '{print $8}' ` + curr_cpu_rate=${curr_cpu_rate%.*} + CURR_CPU_RATE=`expr 100 - $curr_cpu_rate` + echo "CURRENT CPU USAGE RATE="$CURR_CPU_RATE +} + +# 当前机器 逻辑CPU数目 +function get_cpu_logi_num(){ + CPU_LOGI_NUM=`cat /proc/cpuinfo| grep "processor"| wc -l` + echo "CPU LOGI NUM="$CPU_LOGI_NUM +} + +# kill 贪婪进程 +function kill_greedy_pid(){ + ps -ef | grep ./dead_circle.sh | grep -v grep | awk '{print $2}' | xargs kill -9 > /dev/null +} + +# 贪婪start +function fire_greedy_process(){ + echo "GREEDY NUM= "$1 + for i in `seq 1 $1` + do + { + ./cpulimit -l $CPU_LIMIT_FOR_GREEDY_PROCESS bash ./dead_circle.sh > /dev/null & + } + done +} + +############################################################################################## +##################################### 贪婪引擎 ############################################## +############################################################################################## + +function greedy_machine(){ + # 确定CPU核数目: + get_cpu_logi_num + + # 贪婪调度器 + while true + do + # 1.kill 贪婪进程 + kill_greedy_pid + # 2.获取当前CPU% + get_curr_cpu_rate + # 3.获取贪婪值 + GREEDY_VALUE=`expr $EXPECT_CPU_RATE - $CURR_CPU_RATE` + echo "GREEDY_VALUE="$GREEDY_VALUE + # 4.是否执行贪婪计划 + if [ $GREEDY_VALUE -gt 0 ]; then + # 确定贪婪进程数 + # greedy_process_num=`expr $CPU_LOGI_NUM \* $GREEDY_VALUE / 100` + greedy_process_num=`expr $CPU_LOGI_NUM \* $GREEDY_VALUE / $CPU_LIMIT_FOR_GREEDY_PROCESS` + GREEDY_PROCESS_NUM=${greedy_process_num%.*} + echo "GREEDY_PROCESS_NUM= "$GREEDY_PROCESS_NUM + # 大于0则调度 + if [ $GREEDY_PROCESS_NUM -gt 0 ]; then + fire_greedy_process $GREEDY_PROCESS_NUM + fi + fi + # 休眠1min + sleep 60 + done +} + +############################################################################################## +############################################################################################## +############################################################################################## + + + + +############################################################################################## +########################################## main ############################################# +############################################################################################## + + +function check_parameters(){ + + if [ "x$EXPECT_CPU_RATE" == "x" ] + then + echo "PARAM ERROR: EXPECT_CPU_RATE IS NULL (-e)" >&2 + exit -1 + fi + + if [ $EXPECT_CPU_RATE -lt 0 -o $EXPECT_CPU_RATE -gt 100 ] + then + echo "PARAM ERROR: EXPECT_CPU_RATE value expect [1-100] (-e)" >&2 + exit -1 + fi + + if [ "x$CPU_LIMIT_FOR_GREEDY_PROCESS" == "x" ] + then + echo "PARAM ERROR: CPU_LIMIT_FOR_GREEDY_PROCESS IS NULL (-l)" + exit -1 + fi + + if [ $CPU_LIMIT_FOR_GREEDY_PROCESS -lt 0 -o $CPU_LIMIT_FOR_GREEDY_PROCESS -gt 100 ] + then + echo "PARAM ERROR: CPU_LIMIT_FOR_GREEDY_PROCESS value expect [1-100] (-e)" >&2 + exit -1 + fi + + +} + + + + +while getopts "e:l:h" opt +do + case $opt in + e) + EXPECT_CPU_RATE=$OPTARG + echo "EXPECT_CPU_RATE= "$EXPECT_CPU_RATE + ;; + l) + CPU_LIMIT_FOR_GREEDY_PROCESS=$OPTARG + echo "CPU_LIMIT_FOR_GREEDY_PROCESS= "$CPU_LIMIT_FOR_GREEDY_PROCESS + ;; + *) + echo "ERROR don't support this parameter" >&2 + usage + exit -1 + ;; + esac +done + +check_parameters +greedy_machine + + +############################################################################################## +############################################################################################## +############################################################################################## + + + diff --git a/cpulimit b/cpulimit new file mode 100755 index 0000000..09cbc60 Binary files /dev/null and b/cpulimit differ diff --git a/cpulimit.zip b/cpulimit.zip new file mode 100644 index 0000000..196abc1 Binary files /dev/null and b/cpulimit.zip differ diff --git a/dead_circle.sh b/dead_circle.sh new file mode 100755 index 0000000..09adca3 --- /dev/null +++ b/dead_circle.sh @@ -0,0 +1,14 @@ +#! /usr/bin/bash +#! -*- coding=utf-8 -*- +# Author:zhouze03 +# Date: 2017-08-15 + +####### +# 死循环脚本,贪婪程序即该脚本 +####### + + +while true +do + echo "-----do---" +done \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..e351b1d --- /dev/null +++ b/readme.txt @@ -0,0 +1,32 @@ +#! -*- coding=utf-8 -*- +# Author:zhouze03 +# Date: 2017-08-16 + + +当前应用的目的: +该应用脚本是为了提高机器的CPU使用率,它会根据当前机器CPU (会自动排除本程序进程所占用CPU%) 决定是否需要”协助“已提高当前机器的CPU的使用率; +1. 当前脚本会自动的去判断当前机器的CPU逻辑单元数目; +2. 脚本的检查周期为 1min; +3. 具备自动调节能力,会自动计算以达到用户指定的总CPU% 占有率;(当前脚本CPU%(自动调节,调节周期1min) + 其它进程CPU% 约等于= 用户目标总CPU%) +备注: +1. 不要去更改脚本的相对路径,所有脚本都得按照我提供的路径(平级)存放,因为脚本中使用的时相对路径进行脚本间的调用; +2. 提供了test 脚本,已测试是cpu_scheduler 程序能否自适应,使用者可以自行学习验证; +3. cpulimit 只能在Linux CenOS上使用,如果需要在其它平台使用,则需要根据(c++源文件重新编译); + 3.1 unzip cpulimit.zip + 3.2 cd cpulimit-master + 3.3 make + 3.4 copy src/cpulimit 到当前应用目录 + + +启动命令(推荐): + cd ${cpu_greeedy目录} + ./start_kg_cpu_control.sh -e 50 + 或者 + ./start_kg_cpu_control.sh -e 50 -l 50 + +备注: +-e: 表示希望机器达到的总CPU% 占用率; +-l:表示我提供的脚本进程中,”贪婪进程“对单个CPU逻辑单元的占用率,推荐60。避免过高独占一个完整的CPU逻辑单元而降低CPU的并发度。 + + + diff --git a/start_kg_cpu_control.sh b/start_kg_cpu_control.sh new file mode 100755 index 0000000..80ef003 --- /dev/null +++ b/start_kg_cpu_control.sh @@ -0,0 +1,75 @@ +#! /bin/bash +#! -*- coding=utf-8 -*- +# Author:zhouze03 +# Date: 2017-08-16 + + +############################################################################################## +########################################## main ############################################# +############################################################################################## + + +function start() { + + # 设置贪婪脚本的执行进程不会独占一个CPU逻辑单元,因为贪婪脚本中有无限循环(不设置则独占一个逻辑单元) + nohup ./cpulimit -l 50 ./cpu_scheduler.sh -e $EXPECT_CPU_RATE -l $CPU_LIMIT_FOR_GREEDY_PROCESS >/dev/null & +} + + +function check_parameters(){ + + if [ "x$EXPECT_CPU_RATE" == "x" ] + then + echo "PARAM ERROR: EXPECT_CPU_RATE IS NULL (-e)" >&2 + exit -1 + fi + + if [ $EXPECT_CPU_RATE -lt 0 -o $EXPECT_CPU_RATE -gt 100 ] + then + echo "PARAM ERROR: EXPECT_CPU_RATE value expect [1-100] (-e)" >&2 + exit -1 + fi + + if [ "x$CPU_LIMIT_FOR_GREEDY_PROCESS" == "x" ] + then + # 用户没有输入,则提供默认值 + CPU_LIMIT_FOR_GREEDY_PROCESS=60 + fi + + if [ $CPU_LIMIT_FOR_GREEDY_PROCESS -lt 0 -o $CPU_LIMIT_FOR_GREEDY_PROCESS -gt 100 ] + then + echo "PARAM ERROR: CPU_LIMIT_FOR_GREEDY_PROCESS value expect [1-100] (-e)" >&2 + exit -1 + fi + + +} + + + + +while getopts "e:l:" opt +do + case $opt in + e) + EXPECT_CPU_RATE=$OPTARG + echo "EXPECT_CPU_RATE= "$EXPECT_CPU_RATE + ;; + l) + CPU_LIMIT_FOR_GREEDY_PROCESS=$OPTARG + echo "CPU_LIMIT_FOR_GREEDY_PROCESS= "$CPU_LIMIT_FOR_GREEDY_PROCESS + ;; + *) + echo "ERROR don't support this parameter" >&2 + usage + exit -1 + ;; + esac +done + +check_parameters +start + +############################################################################################## +############################################################################################## +############################################################################################## diff --git a/stop_kg_cpu_control.sh b/stop_kg_cpu_control.sh new file mode 100755 index 0000000..fc38454 --- /dev/null +++ b/stop_kg_cpu_control.sh @@ -0,0 +1,15 @@ +#! /bin/bash +#! -*- coding=utf-8 -*- +# Author:zhouze03 +# Date: 2017-08-16 + + +# kill 主线程 +ps -ef | grep ./cpu_scheduler.sh | grep -v grep | awk '{print $2}' | xargs kill -9 + +# 为了安全起见kill 贪婪进程(正常情况kill 主线程,子线程即退出) +ps -ef | grep ./dead_circle.sh | grep -v grep | awk '{print $2}' | xargs kill -9 + + +# 测试脚本相关 +# ps -ef | grep ./test_dead_circle.sh | grep -v grep | awk '{print $2}' | xargs kill -9 \ No newline at end of file diff --git a/test_cpu_release.sh b/test_cpu_release.sh new file mode 100755 index 0000000..f658162 --- /dev/null +++ b/test_cpu_release.sh @@ -0,0 +1,44 @@ +#! /bin/bash +#! -*- coding=utf-8 -*- +# Author:zhouze03 +# Date: 2017-08-15 + + +############# +# 该脚本用于测试的目的,测试当有CPU% 已经超过期望的值时(这里由自己决定,比如KG机器希望CPU超50%,那么此值即50) +# cpu_schedule.sh 的脚本逻辑是否会判断当前检测时刻CPU负载达标,从而不会去启动贪婪进程。 +# 操作&&简而言之: +# 确定该脚本需要启用多少个贪婪进程,这个需要使用者自己根据CPU的逻辑核数目去计算, +# 比如48核,在没有任何其它CPU消耗的情况下,需要启用大概 48 * 50% = 24 个贪婪进程(下面脚本固定控制为单CPU逻辑单元使用为 95%) +# 备注: +# 视当前测试机器CPU 现有占用百分值去计算。 +# 测试目标: +# 上述进程确定并启动后,使用htop进行观察,cpu_scheduler 应该判断出当前CPU已经达到指标值,从而它不会启动它要调用的贪婪进程。 +# 目标符合预期则: +# cpu_scheduler.sh 程序能根据机器CPU自适应的调节贪婪进程的启动数目。 +############ + + + +function fire_greedy_process(){ + for i in `seq 1 22` + do + { + echo "start greedy process "$i + # 贪婪进程 + ./cpulimit -l 95 bash ./test_dead_circle.sh >/dev/null & + } + done +} + +FLAG=0 + +while true +do + if [ $FLAG -eq 0 ]; then + echo "FLAG="$FLAG + fire_greedy_process + FLAG=1 + fi + +done \ No newline at end of file diff --git a/test_dead_circle.sh b/test_dead_circle.sh new file mode 100755 index 0000000..7417bc9 --- /dev/null +++ b/test_dead_circle.sh @@ -0,0 +1,15 @@ +#! /bin/bash +#! -*- coding=utf-8 -*- +# Author:zhouze03 +# Date: 2017-08-15 + + +####### +# 死循环脚本,贪婪程序即该脚本 +####### + + +while true +do + echo "-----do---" +done \ No newline at end of file