k8s API限流——server级别整体限流和客户端限流
1. 背景
为了防止突发流量影响apiserver可用性,k8s支持多种限流配置,包括:
- MaxInFlightLimit,server级别整体限流
- Client限流
- EventRateLimit, 限制event
- APF,更细力度的限制配置
1.1 MaxInFlightLimit限流
- apiserver默认可设置最大并发量(集群级别,区分只读与修改操作)
- 通过参数–max-requests-inflight代表只读请求
- –max-mutating-requests-inflight代表修改请求
- 可以简单实现限流。
1.1.1 源码解读
-
入口 GenericAPIServer.New中的添加hook
// FlowControl为nil ,代表未启用 APF,API 服务器中的整体并发量将受到 kube-apiserver 的参数 --max-requests-inflight 和 --max-mutating-requests-inflight 的限制。if c.FlowControl != nil {const priorityAndFairnessFilterHookName = "priority-and-fairness-filter"if !s.isPostStartHookRegistered(priorityAndFairnessFilterHookName) {err := s.AddPostStartHook(priorityAndFairnessFilterHookName, func(context PostStartHookContext) error {genericfilters.StartPriorityAndFairnessWatermarkMaintenance(context.StopCh)return nil})if err != nil {return nil, err}}} else {const maxInFlightFilterHookName = "max-in-flight-filter"if !s.isPostStartHookRegistered(maxInFlightFilterHookName) {err := s.AddPostStartHook(maxInFlightFilterHookName, func(context PostStartHookContext) error {genericfilters.StartMaxInFlightWatermarkMaintenance(context.StopCh)return nil})if err != nil {return nil, err}}}// StartMaxInFlightWatermarkMaintenance starts the goroutines to observe and maintain watermarks for max-in-flight // requests. func StartMaxInFlightWatermarkMaintenance(stopCh <-chan struct{}) {startWatermarkMaintenance(watermark, stopCh) }// startWatermarkMaintenance starts the goroutines to observe and maintain the specified watermark. func startWatermarkMaintenance(watermark *requestWatermark, stopCh <-chan struct{}) {// 定期更新inflight使用指标go wait.Until(func() {watermark.lock.Lock()readOnlyWatermark := watermark.readOnlyWatermarkmutatingWatermark := watermark.mutatingWatermarkwatermark.readOnlyWatermark = 0watermark.mutatingWatermark = 0watermark.lock.Unlock()metrics.UpdateInflightRequestMetrics(watermark.phase, readOnlyWatermark, mutatingWatermark)}, inflightUsageMetricUpdatePeriod, stopCh)// 定期观察watermarks。这样做是为了确保他们不会落后太多。当他们//落后太多时,在响应接收到的下一个请求时会有很长的延迟,而观察者//会赶上来。go wait.Until(func() {watermark.readOnlyObserver.Add(0)watermark.mutatingObserver.Add(0)}, observationMaintenancePeriod, stopCh) }
-
WithMaxInFlightLimit代表限流处理函数
调用入口: staging\src\k8s.io\apiserver\pkg\server\config.go
DefaultBuildHandlerChain中,判断FlowControl为nil就开启WithMaxInFlightLimit,
if c.FlowControl != nil {requestWorkEstimator := flowcontrolrequest.NewWorkEstimator(c.StorageObjectCountTracker.Get)handler = filterlatency.TrackCompleted(handler)handler = genericfilters.WithPriorityAndFairness(handler, c.LongRunningFunc, c.FlowControl, requestWorkEstimator)handler = filterlatency.TrackStarted(handler, "priorityandfairness")} else {handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.LongRunningFunc)}func WithMaxInFlightLimit(handler http.Handler,nonMutatingLimit int,mutatingLimit int,longRunningRequestCheck apirequest.LongRunningRequestCheck,
) http.Handler {// 如果limit num为0就不开启限流了if nonMutatingLimit == 0 && mutatingLimit == 0 {return handler}var nonMutatingChan chan boolvar mutatingChan chan bool// 构造限流的chan,类型为长度=limit的 bool chanif nonMutatingLimit != 0 {nonMutatingChan = make(chan bool, nonMutatingLimit)klog.V(2).InfoS("Initialized nonMutatingChan", "len", nonMutatingLimit)} else {klog.V(2).InfoS("Running with nil nonMutatingChan")}if mutatingLimit != 0 {mutatingChan = make(chan bool, mutatingLimit)klog.V(2).InfoS("Initialized mutatingChan", "len", mutatingLimit)} else {klog.V(2).InfoS("Running with nil mutatingChan")}initMaxInFlight(nonMutatingLimit, mutatingLimit)// 发起请求return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {ctx := r.Context()requestInfo, ok := apirequest.RequestInfoFrom(ctx)if !ok {handleError(w, r, fmt.Errorf("no RequestInfo found in context, handler chain must be wrong"))return}// 检查是否是长时间运行的请求if longRunningRequestCheck != nil && longRunningRequestCheck(r, requestInfo) {handler.ServeHTTP(w, r)return}。。。。。。。。
}// LongRunningRequestCheck is a predicate which is true for long-running http requests.
type LongRunningRequestCheck func(r *http.Request, requestInfo *RequestInfo) bool
使用BasicLongRunningRequestCheck检查是否是watch或者pprof debug等长时间运行的请求,因为这些请求不受限制,位置
func BasicLongRunningRequestCheck(longRunningVerbs, longRunningSubresources sets.String) apirequest.LongRunningRequestCheck {return func(r *http.Request, requestInfo *apirequest.RequestInfo) bool {if longRunningVerbs.Has(requestInfo.Verb) {return true}if requestInfo.IsResourceRequest && longRunningSubresources.Has(requestInfo.Subresource) {return true}if !requestInfo.IsResourceRequest && strings.HasPrefix(requestInfo.Path, "/debug/pprof/") {return true}return false}
}
检查是只读操作还是修改操作,决定使用哪个chan限制
var c chan boolisMutatingRequest := !nonMutatingRequestVerbs.Has(requestInfo.Verb)if isMutatingRequest {c = mutatingChan} else {c = nonMutatingChan}
如果队列未满,有空位置,则更新排队数字
- 使用select 向c中写入true,如果能写入到说明队列未满
- 记录下对应的指标
select {case c <- true:// We note the concurrency level both while the// request is being served and after it is done being// served, because both states contribute to the// sampled stats on concurrency.if isMutatingRequest {watermark.recordMutating(len(c))} else {watermark.recordReadOnly(len(c))}// default代表队列已满defer func() {<-cif isMutatingRequest {watermark.recordMutating(len(c))} else {watermark.recordReadOnly(len(c))}}()handler.ServeHTTP(w, r)
但是如果请求的group中含有 system:masters,则放行, 因为apiserver认为这个组是很重要的请求,不能被限流.
- group=system:masters 对应的clusterRole 为cluster-admin, 队列已满,如果请求的group中没有 system:masters,则返回http 429错误,并且丢弃请求
// at this point we're about to return a 429, BUT not all actors should be rate limited. A system:master is so powerful// that they should always get an answer. It's a super-admin or a loopback connection.if currUser, ok := apirequest.UserFrom(ctx); ok {for _, group := range currUser.GetGroups() {if group == user.SystemPrivilegedGroup {handler.ServeHTTP(w, r)return}}}
- http 429 代表当前有太多请求了,请重试,并设置 response 的header Retry-After =1
// We need to split this data between buckets used for throttling.metrics.RecordDroppedRequest(r, requestInfo, metrics.APIServerComponent, isMutatingRequest)metrics.RecordRequestTermination(r, requestInfo, metrics.APIServerComponent, http.StatusTooManyRequests)tooManyRequests(r, w)func tooManyRequests(req *http.Request, w http.ResponseWriter) {// Return a 429 status indicating "Too Many Requests"w.Header().Set("Retry-After", retryAfter)http.Error(w, "Too many requests, please try again later.", http.StatusTooManyRequests)
}
1.2 Client限流
client-go默认的qps为5,但是只支持客户端限流,只能由各个发起端限制
- 集群管理员无法控制用户行为。
相关文章:
k8s API限流——server级别整体限流和客户端限流
1. 背景 为了防止突发流量影响apiserver可用性,k8s支持多种限流配置,包括: MaxInFlightLimit,server级别整体限流Client限流EventRateLimit, 限制eventAPF,更细力度的限制配置 1.1 MaxInFlightLimit限流 apiserver…...

在华为做了三年软件测试被裁了,我该怎么办
近年来,随着经济环境的变化和企业战略的调整,员工被裁员的情况变得越来越普遍。无论是因为企业经营困难还是因为业务调整,员工们都可能面临被裁员的风险。如果你也遇到了这样的情况,那么你应该怎么办呢? 首先…...
Spring cloud 限流的多种方式
在频繁的网络请求时,服务有时候也会受到很大的压力,尤其是那种网络攻击,非法的。这样的情形有时候需要作一些限制。本文主要介绍了两种限流方法,感兴趣的可以了解一下 目录 一、实战基于 Spring cloud Gateway 的限流 二、基于阿…...

Linux命令·top
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。下面详细介绍它的使用方法。top是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止…...

springmvc之系列文章
springmvc之编程步骤 springmvc初始化过程 用WebServlet和WebFilter干掉web.xml 没有web.xml怎么写web程序 一次GET请求在springmvc中是的处理流程 springMVC的handler都有哪些类型 springmvc主要组件简单介绍 springmvc 的Servlet WebApplicationContext springmvc 的…...
Matlab实现深度学习(附上完整仿真源码)
文章目录简单案例完整仿真代码下载简单案例 深度学习是一种能够自动学习和提取数据特征的机器学习方法,它已经在图像识别、语音识别、自然语言处理等领域取得了显著的成果。而Matlab作为一个强大的数学计算工具,也提供了丰富的深度学习工具箱࿰…...
我的谷歌书签
Form 表单 | Element Plusa Vue 3 based component library for designers and developershttps://element-plus.gitee.io/zh-CN/component/form.html#%E5%AF%B9%E9%BD%90%E6%96%B9%E5%BC%8F three.js exampleshttp://www.yanhuangxueyuan.com/threejs/examples/#software_geo…...

day3 数据库技术考点汇总
一、重点知识点 基本概念:三级模式-两级映像、数据库设计数据库模型:E-R模型、关系模型、关系代数(结合SQL语言)规范化:函数依赖、健与约束、范式、模式分解事务并发:并发三种问题、三级封锁协议数据库新技…...

学剪辑难吗 如何使用会声会影2023做剪辑视频
很多剪辑初学者都问过一个问题,学剪辑难吗?其实不论学什么,只要用心学都不难,今天我们就来讲讲如何学做剪辑视频,感兴趣的小伙伴们不要走开!一、学剪辑难吗 其实学剪辑并不是件难事,但是需要掌握…...
django学习日记
1、虚拟环境 virtualenv "加虚拟环境名字" 在当前目录下创建一个虚拟环境 进入虚拟环境执行activate进入该虚拟环境,再执行deactivate退出虚拟环境 安装一个包来管理虚拟环境,每次创建虚拟环境都放到同一位置,以及在任意位置都可…...

在线教学视频课程如何防止学员挂机?
阿酷TONY / 2023-3-31 / 长沙 / 原创 / 要不?交个朋友吧? 在线教学视频课程如何防止学员挂机?siri:这是个有意思的问题哈~~~在线教育、在线企业培训机构通常是如何处理的呢? 答:在视频播放过程中,弹出问题…...

【Redis】安装配置
文章目录Redis简介Redis版本迭代Redis安装配置官网地址操作系统环境基础查看本地redis版本修改配置文件docker容器安装redis测试linux版Redis简介 简介 与传统数据库关系(mysql),Redis是key-value数据库(NoSQL一种),mysql是关系数据库。Redis数据操作主要…...

ChatGPT批量生成文章-ChatGPT文章生成器
ChatGPT:一键批量生成高质量文章,提高生产效率! 随着信息爆炸的时代,文本生产成为了各个行业必不可少的一部分。但面对高强度的生产需求,人力资源却难以跟上步伐。现在,我们有一款基于人工智能和自然语言处…...
Linux命令 ——sed
介绍 sed 是一种流式文本编辑器,常用于在 Unix 和类 Unix 系统中对文本进行处理。它可以将文本从标准输入或文件中读取,对其进行修改,然后将修改后的文本输出到标准输出或文件中。sed 是 “stream editor” 的缩写。 语法 sed 的基本语法为…...
C++常用字符串string方法
文章目录字符串string操作方法1. 类方法使用示例2. 头文件cstring方法使用示例字符串string操作方法 1. 类方法 在C中,引入string.h头文件可以使用C语言中的字符串操作函数。然而,C提供了一个更加方便的字符串类string,不需要引入string.h头…...

XML树结构和语法
文章目录一、XML 树结构二、XML 语法规则总结一、XML 树结构 XML 树结构 XML 文档形成了一种树结构,它从"根部"开始,然后扩展到"枝叶"。 一个 XML 文档实例 XML 文档使用简单的具有自我描述性的语法: <?xml vers…...
【Qt】Qt单元测试详解(四):Google Test 断言
1、创建测试工程 【Qt】Qt单元测试详解(一):通过QtCreator创建测试工程 2、添加测试代码 2.1 默认生成的代码 1)项目工程pro include(gtest_dependency.pri)TEMPLATE = app CONFIG += console c++14 CONFIG -= app_bundle CONFIG += thread CONFIG -= qtHEADERS += \t…...
句柄和指针的区别
句柄和指针都是一种数据结构,都常用于访问内存,下面介绍他们的一些不同点。 1 数据结构类型不同 指针的数据类型是无符号整数,占用4或8个字节(在32位和64位系统中),它就像一个变量一样,这个变量…...
Linux 网络编程学习笔记——十四、多线程编程
目录 早期 Linux 不支持线程,直到 1996 年,Xavier Leroy 等人才开发出第一个基本符合 POSIX 标准的线程库 LinuxThreads 。但 LinuxThreads 效率低而且问题很多。自内核 2.6 开始,Linux 才真正提供内核级的线程支持,并有两个组织…...
JS 获取时区
JS 获取时区 啥是时区? 时区是地球上的区域使用同一个时间定义。以前,人们通过观察太阳的外置(时角)决定时间,这就使得不同经度的地方的时间各有不同,为了统一使用同一个时间,就引入了时区的概…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...