云原生项目用于验证负载感知调度的go-web-demo

原创 吴就业 172 0 2024-01-22

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/240832469b8b47cdbbf752b6569ae7a9

作者:吴就业
链接:https://wujiuye.com/article/240832469b8b47cdbbf752b6569ae7a9
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

我们在做云原生调度技术调研的时候,为了做实验获取一些数据,需要编写一个demo, 支持动态模拟cup使用率和内存使用,所以用go开发了这么一个web程序。

package main

import (
	"fmt"
	"net/http"
	"runtime"
	"strconv"
	"sync/atomic"
	"time"
)

// 单个cpu利用率,[0~100]
var cpuUsage atomic.Int64

// 内存占用,单位Mb
var memoryUsage atomic.Int64

var memoryUsageBuf []byte

func init() {
	cpuUsage.Store(0)
	memoryUsage.Store(0)
	cpuUsageTask()
}

func main() {
	http.HandleFunc("/cpu", handleCpuUsgApi)
	http.HandleFunc("/memory", handleMemoryUsgApi)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Println("Error starting server:", err)
	}
}

func handleCpuUsgApi(w http.ResponseWriter, r *http.Request) {
	usage := r.URL.Query().Get("usage")
	v, err := strconv.ParseInt(usage, 10, 64)
	if err != nil || v < 0 || v > 100 {
		w.WriteHeader(500)
		w.Write([]byte("invalid step value"))
		return
	}
	cpuUsage.Store(v)
	w.WriteHeader(200)
	w.Write([]byte("ok"))
}

// 不生效多调几次
func handleMemoryUsgApi(w http.ResponseWriter, r *http.Request) {
	usage := r.URL.Query().Get("usage")
	v, err := strconv.ParseInt(usage, 10, 64)
	if err != nil || v < 0 {
		w.WriteHeader(500)
		w.Write([]byte("invalid step value"))
		return
	}
	updateMemoryUsage(int(v))
	w.WriteHeader(200)
	w.Write([]byte("ok"))
}

func updateMemoryUsage(usageMb int) {
	mb := usageMb * 1024 * 1024
	memoryUsageBuf = nil
	runtime.GC()
	time.Sleep(200 * time.Millisecond)
	memoryUsageBuf = make([]byte, mb)
}

func cpuUsageTask() {
	go func() {
		for {
			usage := float64(cpuUsage.Load()) / float64(100)
			Compute(usage)
		}
	}()
}

// Compute 使用cpu占用率达到目标值
// usage [0, 1], CPU利用率百分比
func Compute(usage float64) {
	// 一个总的CPU利用率的统计周期为1000毫秒
	var t = 1000.0
	// 总时间转换为纳秒
	var r int64 = 1000 * 1000
	totalNanoTime := t * (float64)(r)
	// 计算时间,纳秒
	runTime := totalNanoTime * usage
	// 休眠时间,纳秒
	sleepTime := totalNanoTime - runTime
	startTime := time.Now().UnixNano()
	// 运行
	for float64(time.Now().UnixNano())-float64(startTime) < runTime {
	}
	// 休眠
	time.Sleep(time.Duration(sleepTime) * time.Nanosecond)
}

其中Compute方法就是模拟消耗cpu,参数usage是模拟的目标使用率,取值为0~1,例如0.1表示10%。可以通过top命令验证。 这个值不会很准确,但非常接近。例如想要模拟10%的cpu使用率,可能实际在9.8%左右。

handleMemoryUsgApi方法则是模拟消耗内存,有个问题就是可能需要重复调用两次才会生效。 先给memoryUsageBuf赋值为空,然后gc,再new新的对象,是考虑了,假如先前占用了500m, 现在想更新到800m,如果不先释放500m内存,短时间内就会占用1300m的内容,可能会触达limits。

#云原生

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

极致成本优化背景下,如何通过优化k8s调度器实现计算资源的按需付费(三)

本篇介绍的内容是scheduler-plugins框架的TargetLoadPacking插件,这是一个k8s调度框架的评分插件。TargetLoadPacking即目标负载调度器,用于控制节点的CPU利用率不超过目标值x%(例如65%),通过打分让所有cpu利用率超过x%的都不被选中。目标负载调度器只支持CPU。

极致成本优化背景下,如何通过优化k8s调度器实现计算资源的按需付费(二)

本篇介绍的内容是scheduler-plugins框架的LoadVariationRiskBalancing插件,这是一个k8s调度框架的评分插件,基于request、均值和标准差的K8s负载感知调度器。 我们通过实验去理解和验证该插件实现的负载感知均衡调度算法。

极致成本优化背景下,如何通过优化k8s调度器实现计算资源的按需付费(一)

在降低增笑的大背景下,如何在保证稳定性的前提下,做到极致压缩k8s资源的使用,实现基础设施真正的按需付费,是我们云原生项目的目标之一。要实现如Railway这种产品的基础设施按实际使用付费,不能简单的使用云Serverless产品,因为这些产品都有最低限额的要求,例如阿里云最低限制要求Pod至少0.25cpu+0.5g内存,但其实大多数应用这个配额都用不到,大量的时间cpu负载几乎为0,内存消耗可能也就几十M(Java应用除外),大量的低使用率的Pod会造成资源的浪费。

KubeVela完结篇:我为Terraform Controller贡献了3个PR

KubeVela于2020年年底开源,距离现在还未满三年时间,是一个非常年轻的产物。KubeVela是非常创新的产物,如OAM模型的抽象设计。所以也并未成熟,除了官方文档,找不到更多资料,在使用过程中,我们也遇到各种大大小小的问题。

KubeVela篇14:如何实现存量业务的基础设施导入Kubevela+Terraform

由于我们的使用场景是将基础设施资源定义成KubeVela的组件,一个terraform “module”对应的就是一个kubevela的组件,对应terraform-controller的一个Configuration资源。因此导入的最小粒度是组件,即一个terraform “module”。

KubeVela篇13:跨地域的多集群管理方案

随着公司全球化战略的布局,业务呈点状分布在亚太、美东、欧洲等多个地域,云原生kubevela在跨地域多集群管控方面也遇到网络上的互通问题。