Author: wencoo
Blog:https://wencoo.blog.csdn.net/
Date: 18/04/2023
Details:
项目服务器不够用了,需要弹性伸缩服务器,准备使用火山的弹性伸缩功能,但是在配置的过程中发现,弹性伸缩的指标都是针对于本机的负载等等进行监控,从而实现弹性伸缩。我的项目是使用的GPU服务器,在程序启动的时候,相关GPU资源都已经申请好了,达到了最大值,即使没有任务,也是资源占用掉了,任务的来源是中间件rabbitmq,所以在本机上监控,并不合理。
因为使用的rabbitmq,任务都存储在队列中,先获取队列任务数量,根据队列任务数量,按照策略,决定是否创建弹性伸缩的服务器,创建之后,待任务消费减少,再删除之前创建好的弹性伸缩的服务器。
创建配置mq的相关信息的配置文件configMq.json,创建配置服务器的相关信息的配置文件configECS.json,创建配置数据库的相关信息的配置文件configDB.json,这里内容很简单,也没必要整个数据库啦,所以直接使用配置文件解决
{
"port": 5672,
"hostName": "106.15.0.159",
"passwd": "xxx",
"userName": "admin",
"maxCounts": 3000,
"interval": 3000
}
{
"ImageId": "image-ycct00qocb4qwlkufab4",
"InstanceName": "instance-test",
"InstanceTypeId": "ecs.g1tl.4xlarge",
"Password": "xxx",
"ZoneId": "cn-beijing-b"
}
{
"min":2,
"max":3,
"base":[
"i-yc9mljz3vo2ud9z787ky",
"i-ycbpj0u2pz8rx7cc8n06"
],
"elasticity": [
],
"rule":1
}
读取相关配置信息
//读取configDB.json
jsonFile, err := os.Open("configDB.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
jsonData, err := ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println("error reading json file")
return
}
var dbS DbConfStruct
json.Unmarshal(jsonData, &dbS)
fmt.Println(dbS.Max)
//读取configECS.json
jsonFile, err = os.Open("configECS.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
jsonData, err = ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println("error reading json file")
return
}
var ecsS EcsConfStruct
json.Unmarshal(jsonData, &ecsS)
fmt.Println(ecsS.ImageId)
//读取configMq.json
jsonFile, err = os.Open("configMq.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
jsonData, err = ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println("error reading json file")
return
}
var mqS MqConfStruct
json.Unmarshal(jsonData, &mqS)
fmt.Println(mqS.Port)
获取mq队列里面的任务数量
//获取mq队列任务数量
msgCounts := getQueueMsgCounts("material.analysis.new", "material.exchange",
"material.analysis.new", mqS.HostName, mqS.UserName, mqS.Passwd, mqS.Port)
创建弹性伸缩的机器的规则,并创建新的服务器
baseCounts := len(dbS.Base)
elasticityCounts := len(dbS.Elasticity)
nextMaxCounts := mqS.MaxCounts + (elasticityCounts+1)*mqS.Interval
if (baseCounts + elasticityCounts) >= dbS.Max {
logger.Println("启动服务器数量已达到最大值...不再继续启动新服务器")
goto Sleep
}
if msgCounts >= mqS.MaxCounts && msgCounts < nextMaxCounts {
//资源申请
serverIdList, err := RunInstances()
var serverId *string
if err == nil {
if len(serverIdList) >= 1 {
serverId = serverIdList[0]
logger.Println("创建伸缩服务器成功,serverId:", serverId)
fmt.Println("create server id:", serverId)
}
} else {
logger.Println("创建伸缩服务器失败,err:", err.Error())
goto Sleep
}
...
删除服务器资源
//资源释放
elasticityCount := len(dbS.Elasticity)
if 0 == elasticityCount {
fmt.Println("没有伸缩资源,继续休眠")
goto Sleep
} else {
eServerId := dbS.Elasticity[len(dbS.Elasticity)-1].EServerId
DeleteInstance(eServerId)
fmt.Println("删除伸缩资源:", eServerId)
}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"time"
)
var logger *log.Logger
func init() {
//指定路径的文件,无则创建
logFile, err := os.OpenFile("./log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND|os.O_TRUNC, 0666)
if err != nil {
panic(err)
}
logger = log.New(logFile, "", log.Lshortfile|log.Lmicroseconds)
}
func main() {
logger.Println("application start ...")
//读取configDB.json
jsonFile, err := os.Open("configDB.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
jsonData, err := ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println("error reading json file")
return
}
var dbS DbConfStruct
json.Unmarshal(jsonData, &dbS)
fmt.Println(dbS.Max)
//读取configECS.json
jsonFile, err = os.Open("configECS.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
jsonData, err = ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println("error reading json file")
return
}
var ecsS EcsConfStruct
json.Unmarshal(jsonData, &ecsS)
fmt.Println(ecsS.ImageId)
//读取configMq.json
jsonFile, err = os.Open("configMq.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
jsonData, err = ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println("error reading json file")
return
}
var mqS MqConfStruct
json.Unmarshal(jsonData, &mqS)
fmt.Println(mqS.Port)
for {
//获取mq队列任务数量
msgCounts := getQueueMsgCounts("material.analysis.new", "material.exchange",
"material.analysis.new", mqS.HostName, mqS.UserName, mqS.Passwd, mqS.Port)
fmt.Println("get queue counts is: ", msgCounts)
baseCounts := len(dbS.Base)
elasticityCounts := len(dbS.Elasticity)
nextMaxCounts := mqS.MaxCounts + (elasticityCounts+1)*mqS.Interval
if (baseCounts + elasticityCounts) >= dbS.Max {
logger.Println("启动服务器数量已达到最大值...不再继续启动新服务器")
goto Sleep
}
if msgCounts >= mqS.MaxCounts && msgCounts < nextMaxCounts {
//资源申请
serverIdList, err := RunInstances()
var serverId *string
if err == nil {
if len(serverIdList) >= 1 {
serverId = serverIdList[0]
logger.Println("创建伸缩服务器成功,serverId:", serverId)
fmt.Println("create server id:", serverId)
}
} else {
logger.Println("创建伸缩服务器失败,err:", err.Error())
goto Sleep
}
//写入json
var eesId ElasticityMachine
eesId.EServerId = *serverId
dbS.Elasticity = append(dbS.Elasticity, eesId)
jsonFile, err = os.Open("configDB.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
data, err := json.MarshalIndent(dbS, "", " ") // 第二个表示每行的前缀,这里不用,第三个是缩进符号,这里用tab
if err != nil {
panic(err)
}
err = ioutil.WriteFile("configDB.json", data, 0777)
if err != nil {
panic(err)
}
} else {
fmt.Println("队列任务较少,尝试释放资源")
//查询弹性设备创建时间,不用查,直接删除任意一个,反正值伸缩出来的服务
// for _, serverId := range dbS.Elasticity {
// sid := serverId.EServerId
// }
//资源释放
elasticityCount := len(dbS.Elasticity)
if 0 == elasticityCount {
fmt.Println("没有伸缩资源,继续休眠")
goto Sleep
} else {
eServerId := dbS.Elasticity[len(dbS.Elasticity)-1].EServerId
DeleteInstance(eServerId)
fmt.Println("删除伸缩资源:", eServerId)
}
//删除数据写入json
dbS.Elasticity = dbS.Elasticity[:len(dbS.Elasticity)-1]
jsonFile, err = os.Open("configDB.json")
if err != nil {
fmt.Println("error opening json file")
return
}
defer jsonFile.Close()
data, err := json.MarshalIndent(dbS, "", " ") // 第二个表示每行的前缀,这里不用,第三个是缩进符号,这里用tab
if err != nil {
panic(err)
}
err = ioutil.WriteFile("configDB.json", data, 0777)
if err != nil {
panic(err)
}
}
Sleep:
time.Sleep(time.Second * 300)
}
}
项目代码已上传至gitee,传送门 volcano_ecs_manage