client-go的Indexer三部曲之而:性能测试

news2024/11/16 17:29:21

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《client-go的Indexer》系列的第二篇,在前文咱们通过实例掌握了client-go的Indexer的基本功能,本篇咱们尝试对下面这两种接口进行压力测试,用数据验证Indexer的性能优势,看看是否如理论分析那样真的存在
  1. 第一个接口:basic/get_obj_by_obj_key,这个接口会用到Store.GetByKey方法,从本地缓存中取得pod对象返回,如下图红色箭头所示

在这里插入图片描述

  1. 第二个接口:remote/get_obj_by_obj_key_remote_query,此接口会调用client-go库的api,向api-server发起http请求,查找指定pod的信息返回
    在这里插入图片描述

部署情况说明

  • 今天的压测所涉及的服务和应用,它们的部署情况如下图所示,共两台Ubuntu电脑,电脑1用于执行压测,上面部署了k6(或者部署docker,用docker来运行k6),电脑2部署了kubernetes,同时也运行着名为client-go-indexer-tutorials的应用,该应用就是咱们编写的代码:实现了今天要压测的两个接口
    在这里插入图片描述

源码下载

  • 接下来要进入的是编码环节,如果您不想写代码,也可以从GitHub上直接下载,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
名称链接备注
项目主页https://github.com/zq2599/blog_demos该项目在GitHub上的主页
git仓库地址(https)https://github.com/zq2599/blog_demos.git该项目源码的仓库地址,https协议
git仓库地址(ssh)git@github.com:zq2599/blog_demos.git该项目源码的仓库地址,ssh协议
  • 这个git项目中有多个文件夹,本篇的源码在tutorials/client-go-indexer-tutorials文件夹下,如下图红框所示:
    在这里插入图片描述

编码(第一个接口:basic/get_obj_by_obj_key)

  • 第一个接口的源码其实在前文其实已写好,就不重新写了,这里看一下关键代码,如下所示,其实也就一行(调用INDEXER.GetByKey)
// GetObjByObjKey b. 根据对象的key返回(演示Store.Get方法)
func GetObjByObjKey(c *gin.Context) {
	rawObj, exists, err := INDEXER.GetByKey(ObjKey(c))

	if err != nil {
		c.String(500, fmt.Sprintf("b. get pod failed, %v", err))
	} else if !exists {
		c.String(500, fmt.Sprintf("b. get empty pod, %v", err))
	} else {
		if v, ok := rawObj.(*v1.Pod); ok {
			c.JSON(200, v)
		} else {
			c.String(500, "b. convert interface to pod failed")
		}
	}
}
  • 在初始化gin的时候绑定path和handler即可
	// 用于提供基本功能的路由组
	basicGroup := r.Group("/basic")

	// a. 查询指定语言的所有对象的key(演示2. IndexKeys方法)
	basicGroup.GET("get_obj_keys_by_language_name", basic.GetObjKeysByLanguageName)

	// b. 返回对象的key,返回对应的对象(演示Store.GetByKey方法)
	basicGroup.GET("get_obj_by_obj_key", basic.GetObjByObjKey)

编码(第二个接口:remote/get_obj_by_obj_key_remote_query)

  • 要使用client-go库,首先要准备好ClientSet对象,这个在前文也准备好了,放在全局变量中随时可以用,来回顾初始化的代码
var ClientSet *kubernetes.Clientset
var once sync.Once

func initIndexer() {
	log.Println("开始初始化Indexer")

	var kubeconfig *string

	// 试图取到当前账号的家目录
	if home := homedir.HomeDir(); home != "" {
		// 如果能取到,就把家目录下的.kube/config作为默认配置文件
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		// 如果取不到,就没有默认配置文件,必须通过kubeconfig参数来指定
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}

	// 加载配置文件
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}

	// 用clientset类来执行后续的查询操作
	ClientSet, err = kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
	...
  • 再来看如何用ClientSet向api-server发起请求,这也是熟悉的api,在《client-go实战》系列中屡屡用到
// GetObjByObjKey 远程请求,根据指定key查询pod对象
func GetObjByObjKey(c *gin.Context) {
	rawObj, err := basic.ClientSet.
		CoreV1().
		Pods(basic.NAMESPACE).
		Get(c, c.DefaultQuery("pod_name", ""), metav1.GetOptions{})

	if err != nil {
		c.String(500, fmt.Sprintf("g. get pod failed, %v", err))
	} else {
		c.JSON(200, rawObj)
	}
}
  • 最后是绑定path和方法
	remoteGroup := r.Group("/remote")
	// g. 使用clientset远程查询
	remoteGroup.GET("get_obj_by_obj_key_remote_query", remote.GetObjByObjKey)
  • 请将程序运行起来,稍后压测会用到
  • 至此,用于性能对比测试的两个接口代码都已经写好,接下来开始准备性能测试

用k6压测第二个接口(远程访问api-server的方式)

  • 这里用到k6作为压测工具,您也可以选择自己熟悉的工具来用,选择k6是因为足够简单省事儿,如果您已经装好了docker,执行压测只要一行命令就行了
  • 首先编写第二个接口的压测脚本,也就是压测client-go远程访问api-server查询对象的性能,新建文件remote.js,内容如下,可见非常简单,就是发请求检查返回码和返回body
import http from 'k6/http';
import { check } from 'k6';

export default function () {
  const res = http.get(`http://${__ENV.MY_HOSTNAME}/remote/get_obj_by_obj_key_remote_query?pod_name=${__ENV.POD_NAME}`);
  check(res, {
    'is status 200': (res) => res.status === 200,
    'body size is > 0': (r) => r.body.length > 0,
  });
}
  • 如果您的电脑上部署了docker,那么执行以下命令即可完成压力测试,命令中的参数稍后会详细说明
docker run \
--rm \
-i \
loadimpact/k6 \
run \
--duration 60s \
--vus 10 \
-e MY_HOSTNAME=192.168.50.76:18080 \
-e POD_NAME=nginx-deployment-696cc4bc86-2rqcg \
- < remote.js
  • 这里解释清楚上述命令用到的每个参数,
docker run \    	// docker运行容器
--rm \				// 等当前控制台结束时删除该容器(相当于一次性任务)
-i \				// 保持STDIN打开
loadimpact/k6 \		// 镜像名
run \				// 容器中执行的命令,即启动k6的命令
--duration 60s \	// k6的参数:压测时长60秒
--vus 10 \			// k6的参数:并发数为10
-e MY_HOSTNAME=192.168.50.76:18080 \				// remote.js脚本中用到的参数,压测服务的IP和端口
-e POD_NAME=nginx-deployment-696cc4bc86-2rqcg \		// remote.js脚本中用到的参数,pod名称
- < remote.js										// k6压测脚本名称
  • 压测结束,详细数据如下,没有报错,整体QPS为5,虽然我的电脑很烂,但是这么低的QPS还是让人看了直摇头…
     ✓ is status 200
     ✓ body size is > 0

     checks.........................: 100.00% ✓ 6380
     data_received..................: 1.5 MB  25 kB/s
     data_sent......................: 53 kB   857 B/s
     http_req_blocked...............: avg=119.67µs min=927ns   med=2.63µs   max=4.2ms    p(90)=4.96µs   p(95)=7.16µs
     http_req_connecting............: avg=115.35µs min=0s      med=0s       max=4.13ms   p(90)=0s       p(95)=0s
     http_req_duration..............: avg=1.9s     min=15.62ms med=1.99s    max=2.11s    p(90)=2.01s    p(95)=2.03s
       { expected_response:true }...: avg=1.9s     min=15.62ms med=1.99s    max=2.11s    p(90)=2.01s    p(95)=2.03s
     http_req_failed................: 0.00%   ✓ 0319
     http_req_receiving.............: avg=244.4µs  min=23.86µs med=115.38µs max=8.72ms   p(90)=343.48µs p(95)=674.31µs
     http_req_sending...............: avg=18.34µs  min=4.59µs  med=12.75µs  max=209.44µs p(90)=25.43µs  p(95)=35.07µs
     http_req_tls_handshaking.......: avg=0s       min=0s      med=0s       max=0s       p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=1.9s     min=15.51ms med=1.99s    max=2.11s    p(90)=2.01s    p(95)=2.03s
     http_reqs......................: 319     5.159646/s
     iteration_duration.............: avg=1.9s     min=19.58ms med=1.99s    max=2.11s    p(90)=2.01s    p(95)=2.03s
     iterations.....................: 319     5.159646/s
     vus............................: 5       min=5      max=10
     vus_max........................: 10      min=10     max=10

用k6压测第一个接口(获取本地缓存的数据)

  • 远程访问api-server的方式,QPS只有5,接下来该测试第一个接口了,看走本地缓存在性能上是否能比远程访问更强,这要是翻车了该咋办,博客都写不下去了…,Indexer成了全村的希望
    在这里插入图片描述
  • 先编写k6脚本,名为indexer.js
import http from 'k6/http';
import { check } from 'k6';

export default function () {
  const res = http.get(`http://${__ENV.MY_HOSTNAME}/basic/get_obj_by_obj_key?obj_key=${__ENV.OBJ_KEY}`);
  check(res, {
    'is status 200': (res) => res.status === 200,
    'body size is > 0': (r) => r.body.length > 0,
  });
}
  • 完整的压测命令如下
docker run \
--rm \
-i \
loadimpact/k6 \
run \
--duration 60s \
--vus 10 \
-e MY_HOSTNAME=192.168.50.76:18080 \
-e OBJ_KEY=indexer-tutorials/nginx-deployment-696cc4bc86-2rqcg \
- < indexer.js
  • 压测结束,详细数据如下,没有报错,整体QPS为993,嘿嘿,稳了,没翻车…
     ✓ is status 200
     ✓ body size is > 0

     checks.........................: 100.00% ✓ 1192360
     data_received..................: 288 MB  4.8 MB/s
     data_sent......................: 10 MB   168 kB/s
     http_req_blocked...............: avg=4.67µs   min=343ns  med=3.13µs  max=4.81ms   p(90)=5.55µs   p(95)=6.56µs
     http_req_connecting............: avg=633ns    min=0s     med=0s      max=4.4ms    p(90)=0s       p(95)=0s
     http_req_duration..............: avg=9.87ms   min=3.15ms med=9.03ms  max=238.05ms p(90)=13.56ms  p(95)=15.55ms
       { expected_response:true }...: avg=9.87ms   min=3.15ms med=9.03ms  max=238.05ms p(90)=13.56ms  p(95)=15.55ms
     http_req_failed................: 0.00%   ✓ 059618
     http_req_receiving.............: avg=321.15µs min=8.16µs med=70.93µs max=62.14ms  p(90)=478.85µs p(95)=2.07ms
     http_req_sending...............: avg=19.72µs  min=2.29µs med=14.48µs max=2.82ms   p(90)=25.42µs  p(95)=37.31µs
     http_req_tls_handshaking.......: avg=0s       min=0s     med=0s      max=0s       p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=9.53ms   min=3.07ms med=8.69ms  max=237.72ms p(90)=13.13ms  p(95)=15.04ms
     http_reqs......................: 59618   993.440775/s
     iteration_duration.............: avg=10.05ms  min=3.24ms med=9.21ms  max=238.67ms p(90)=13.75ms  p(95)=15.73ms
     iterations.....................: 59618   993.440775/s
     vus............................: 10      min=10       max=10
     vus_max........................: 10      min=10       max=10
  • 至此,压测完成,同样是获取pod的信息,Indexer由于不涉及网络请求,在性能优势上表现的很明显,当然了Indexer也不是万能了,前文编码中,它的局限性也体现出来了
  1. 要和api-server保持长连接,以获取数据最新的变化
  2. 本地内存中长期存放资源数据,相比之下client-go的一次请求响应就搞定了
  3. 灵活性,下图是client-go远程请求api-server的代码,可以按需求随时改变条件,namespace、label-selector等等自由变化,而Indexer则一开始就要把范围确定好,然后只能本地获取这些资源的内容
    在这里插入图片描述
  • 综上所述,两种方式各有优劣,就算混合着用也没问题,一切还是为业务服务吧
  • 至此,性能篇就完成了,接下来就是《client-go的Indexer三部曲》的终篇:源码篇,相信经历了前两篇的实战,您对Indexer已经有了很深入的了解,所以接下来阅读源码也就是件很轻松愉快的事情了

参考

  • k6官方资料:https://k6.io/docs

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/656844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6.pixi.js编写的塔防游戏(类似保卫萝卜)-游戏资源打包逻辑

游戏说明 一个用pixi.js编写的h5塔防游戏&#xff0c;可以用electron打包为exe&#xff0c;支持移动端&#xff0c;也可以用webview控件打包为app在移动端使用 环境说明 cnpm6.2.0 npm6.14.13 node12.22.7 npminstall3.28.0 yarn1.22.10 npm config list electron_mirr…

配置legacyUnhandledExceptionPolicy属性防止处理异常后程序崩溃退出(C#)

这是这篇文章后面遗留的问题&#xff1a; winform中的全局异常信息_winform全局异常捕获_zxy2847225301的博客-CSDN博客 就是线程抛出异常后&#xff0c;被AppDomain.CurrentDomain.UnhandledException注册的事件捕获后&#xff0c;程序依旧崩溃退出。 解决方案&#xff1a;在…

架构-嵌入式模块

章节架构 约三分&#xff0c;主要为选择题 #mermaid-svg-z6RGCDSEQT5AhE1p {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-z6RGCDSEQT5AhE1p .error-icon{fill:#552222;}#mermaid-svg-z6RGCDSEQT5AhE1p .error-text…

【产品经理】从用户体验五要素出发,谈如何设计与体验一款产品

用户体验五要素是产品人必备的知识技能&#xff0c;由于网络碎片化的了解&#xff0c;往往容易造成其高深莫测&#xff0c;晦涩难懂的形象&#xff0c;进而对其束之高阁。但实质不过是一种产品分析与设计的方法论&#xff0c;正确姿势去了解它能帮助我们更好地理解一款产品和从…

移动端小于12px的字体处理方法

今天在按设计稿坐页面时&#xff0c;遇到了下图的情况 ​​​​​ 由于浏览器对字体最小为12px的限制&#xff0c;所以我查阅资料后尝试使用transform:scale来处理 代码如下&#xff1a; <div class"icon"><span class"iconfont icon-a-xuexi3 icon-…

ZYNQ——PL端流水灯的实现

文章目录 一、介绍二、代码编写三、引脚分配四、仿真分析五、添加 ILA IP六、板上验证 一、介绍 本文介绍的是在ZYNQ 7020黑金开发板上实现PL端流水灯的例子&#xff0c;开发板上PL端的LED灯总共有4个&#xff0c;在原理图中找到 PL LED 如下图所示&#xff0c;通过看图可知&a…

【MarkDown】CSDN Markdown之四象限图quadrantChart详解

四象限图 四象限图是一种将数据分为四个象限的可视化方法。它用于在二维网格上绘制数据点&#xff0c;其中一个变量表示x轴&#xff0c;另一个变量表示y轴。根据针对正在分析的数据集的一组标准&#xff0c;将图表分成四个相等的部分来确定四个象限。经常使用四象限图来识别数…

父亲节|祝天下所有父亲节日快乐,长寿安康!

父亲节&#xff0c;是一个感谢父亲的节日。普遍认为的日期是每年6月的第三个星期日&#xff0c;在这一天世界上有52个国家和地区在过父亲节。同时注重孝道也是我们中华民族的传统文化。 在这个感恩的节日里 把最真诚美好的祝福 送给天下所有的父亲们 祝福他们 节日快乐&…

OpenAI 大模型生态

目录标题 1. 语言类大模型2. 图像多模态大模型3. 语音识别模型4. 文本向量化模型5. 审查模型6. 编程大模型1. 语言类大模型 包括GPT-3、GPT-3.5、GPT-4系列模型。并且,OpenAl在训练GPT-3的同时,训练了参数不同、复杂度各不相同的A、B、C、D四项大模型(基座模型),用于不同场景…

mysql 集群 MGR

mysql安装&#xff08;3台服务&#xff09; 1下载 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.11-linux-glibc2.12-x86_64.tar.gz 2解压mysql wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.11-linux-glibc2.12-x86_64.tar.gz tar -zxvf…

键盘按键事件 通过键盘上下左右按键移动界面上图标

#main.c文件 #include “keyevent.h” #include int main(int argc, char *argv[]) { QApplication a(argc, argv); KeyEvent w; w.show(); return a.exec();} #include “keyevent.h”//头文件 #ifndef KEYEVENT_H #define KEYEVENT_H #include #include #include cl…

Windows安装Make工具(make.exe和mingw)

1、make.exe 官网介绍&#xff1a;Make是一个工具&#xff0c;它控制从程序的源文件生成程序的可执行文件和其他非源文件。Make从一个名为Makefile的文件中获取如何构建程序的知识&#xff0c;该文件列出了每个非源文件以及如何从其他文件中计算它。当你编写一个程序时&#x…

[性能测试工具]——Loadrunner的使用及安装指南

目录 一、基本概念 1.1 什么是性能测试&#xff1f; 1.2 性能测试和功能测试的区别&#xff1f; 1.3 什么样的软件属于性能好&#xff0c;什么样的软件属于性能不好&#xff1f; 1.4 哪些因素会影响到软件性能&#xff1f; 二、为什么对软件进行性能测试&#xff1f; 三、性…

压测工具Jmeter学习

压测工具Jmeter Jmeter介绍 Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试&#xff0c;它最初被设计用于Web应用测试&#xff0c;但后来扩展到其他测试领域。 它可以用于测试静态和动态资源&#xff0c;例如静态文件、Java 小服务程序、CGI …

Django基础入门④:数据表显示和Django模板详讲

Django基础入门④&#xff1a;数据表显示和Django模板详讲 数据表显示字段显示表单显示分块内联显示列表显示搜索栏目创建筛选排序分页导入导出 Django模板什么是模板模板使用render方法详解 &#x1f3d8;️&#x1f3d8;️个人简介&#xff1a;以山河作礼。 &#x1f396;️&…

CVPR | 时尚领域视觉语言预训练模型Kaleido-BERT

来源&#xff1a;投稿 作者&#xff1a;小灰灰 编辑&#xff1a;学姐 这是一篇在时尚领域、往细粒度方向做视觉-语言预训练的工作。 论文标题&#xff1a;Kaleido-BERT: Vision-Language Pre-training on Fashion Domain 论文链接&#xff1a;https://arxiv.org/abs/2103.1611…

深度刨析指针Advanced 2

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《系统解析C语言》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白…

使用omp并行技术加速最短路径算法-迪杰斯特拉(Dijkstra)算法(记录最短路径和距离)

原理&#xff1a; Dijkstra算法是解决**单源最短路径**问题的**贪心算法** 它先求出长度最短的一条路径&#xff0c;再参照该最短路径求出长度次短的一条路径 直到求出从源点到其他各个顶点的最短路径。 首先假定源点为u&#xff0c;顶点集合V被划分为两部分&#xff1a;集合…

stable-diffusion-webui的介绍与使用——Controlnet1.1

源码地址&#xff1a;https://github.com/lllyasviel/ControlNet | 最新版本 controlnet-v1.1 论文地址&#xff1a;2302.Adding Conditional Control to Text-to-Image Diffusion Models 扩展UI地址&#xff08;需先安装sd-webui&#xff09;&#xff1a;https://github.com/M…

基于对Element UI的表单验证

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1fa80;从以下源码中介绍&#xff1a;&#x1f380;这里是官网源码 &#x1f412;个人主页 &#x1f3c5;JavaEE系列专栏 &#x1f4d6;前言&#xff1a; 本篇博客主要以介绍基…