1. 什么是 QPS 和 Burst ?
在 kubernetes client-go 中,QPS 和 Burst 是用于控制客戶端與 Kubernetes API 交互速率的兩個關鍵參數:
QPS (Queries Per Second)
定義:表示每秒允許發送的請求數量,即限速器的平滑速率。
用途:用來控制客戶端與 API Server 的持續請求速率。
場景:適用于需要長時間維持均勻的 API 調用的情況。
Burst
定義:表示瞬時允許發送的最大請求數量,即限速器的突發容量。
用途:允許在短時間內發送的請求數量上限,適用于突發性調用場景。
場景:例如,客戶端初始化時,需要快速獲取大量資源。
2. 實驗驗證
可以通過編寫代碼,發送大量 API 請求來驗證 QPS 和 Burst 的行為。以下是一個實驗示例:
package mainimport ("context""flag""fmt""log""sync""time"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {// 加載 kubeconfigkubeconfig := flag.String("kubeconfig", "~/.kube/config", "Path to kubeconfig file")flag.Parse()config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {log.Fatalf("Failed to load kubeconfig: %v", err)}// 設置 QPS 和 Burstconfig.QPS = 5.0 // 每秒 5 個請求,也是默認設置config.Burst = 10 // 突發允許 10 個請求,也是默認設置// 創建客戶端clientset, err := kubernetes.NewForConfig(config)if err != nil {log.Fatalf("Failed to create clientset: %v", err)}// 統計開始時間startTime := time.Now()// 使用 WaitGroup 追蹤請求完成var wg sync.WaitGrouptotalRequests := 50wg.Add(totalRequests)// 發送大量請求for i := 0; i < totalRequests; i++ {go func(i int) {defer wg.Done()_, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})if err != nil {log.Printf("Request %d failed: %v", i, err)} else {log.Printf("Request %d succeeded", i)}}(i)}wg.Wait()fmt.Printf("Total time taken: %v\n", time.Since(startTime))
}
配置 QPS 和 Burst:
設置 QPS = 5,表示每秒最多發送 5 個請求。
設置 Burst = 10,允許在瞬時突發時最多發送 10 個請求。
當發生客戶端限流時,會出現類似如下輸出:
2025/01/10 15:01:50 Request 32 succeeded
I0110 15:01:50.468917 3083 request.go:729] Waited for 1.19372275s due to client-side throttling, not priority and fairness, request: GET:https://127.0.0.1:63092/api/v1/pods
2025/01/10 15:01:50 Request 33 succeeded
當發生客戶端限流時,請求排隊,實際完成時間會被延長。
實驗結果:
當設置 QPS = 5,Burst = 10 時,請求全部成功,完成耗時 8s
當設置 QPS = 1,Burst = 2 時,請求全部成功,完成耗時 48s
調整建議
如果需要高頻請求,可適當增大 QPS 和 Burst,避免客戶端過度限流。
同時,合理設置參數,可以避免客戶端過高的并發負載影響集群穩定性。
源碼機制
client-go 使用令牌桶進行速率限制,桶容量為 burst 大小,按照每秒生成 QPS 個令牌的速率產生令牌(不會實際啟動協程生成令牌,而是根據時鐘計算),只有拿到令牌才能請求 kube-apiserver,如下圖所示:
reference: client-go QPS、Burst和令牌桶