Files
cpukeep/cpu_scheduler.sh
2017-08-16 14:16:37 +08:00

184 lines
6.4 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#! /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
##############################################################################################
##############################################################################################
##############################################################################################