自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊K8s的 Nginx Ingress 調(diào)優(yōu)

開發(fā) 前端
Nginx Ingress Controller 基于 Nginx 實(shí)現(xiàn)了 Kubernetes Ingress API,Nginx 是公認(rèn)的高性能網(wǎng)關(guān),但如果不對(duì)其進(jìn)行一些參數(shù)調(diào)優(yōu),就不能充分發(fā)揮出高性能的優(yōu)勢(shì)。

概述

Nginx Ingress Controller 基于 Nginx 實(shí)現(xiàn)了 Kubernetes Ingress API,Nginx 是公認(rèn)的高性能網(wǎng)關(guān),但如果不對(duì)其進(jìn)行一些參數(shù)調(diào)優(yōu),就不能充分發(fā)揮出高性能的優(yōu)勢(shì)。Nginx Ingress工作原理:

內(nèi)核參數(shù)調(diào)優(yōu)

我們先看看通過內(nèi)核的哪些參數(shù)能夠提高Ingress的性能。保證在高并發(fā)環(huán)境下,發(fā)揮Ingress的最大性能。

調(diào)大全連接隊(duì)列的大小

TCP 全連接隊(duì)列的最大值取決于 somaxconn 和 backlog 之間的最小值,也就是 min(somaxconn, backlog)。在高并發(fā)環(huán)境下,如果隊(duì)列過小,可能導(dǎo)致隊(duì)列溢出,使得連接部分連接無法建立。要調(diào)大 Nginx Ingress 的連接隊(duì)列,只需要調(diào)整 somaxconn 內(nèi)核參數(shù)的值即可,但我想跟你分享下這背后的相關(guān)原理。Nginx 監(jiān)聽 socket 時(shí)沒有讀取 somaxconn,而是有自己?jiǎn)为?dú)的參數(shù)配置。在 nginx.conf 中 listen 端口的位置,還有個(gè)叫 backlog 參數(shù)可以設(shè)置,它會(huì)決定 nginx listen 的端口的連接隊(duì)列大小。

  1. server { 
  2.     listen  80  backlog=1024; 
  3.     ... 

backlog 是 listen(int sockfd, int backlog) 函數(shù)中的 backlog 大小,Nginx 默認(rèn)值是 511,可以通過修改配置文件設(shè)置其長(zhǎng)度;還有 Go 程序標(biāo)準(zhǔn)庫在 listen 時(shí),默認(rèn)直接讀取 somaxconn 作為隊(duì)列大小。就是說,即便你的 somaxconn 配的很高,nginx 所監(jiān)聽端口的連接隊(duì)列最大卻也只有 511,高并發(fā)場(chǎng)景下可能導(dǎo)致連接隊(duì)列溢出。所以在這個(gè)在 Nginx Ingress 中, Nginx Ingress Controller 會(huì)自動(dòng)讀取 somaxconn 的值作為 backlog 參數(shù)寫到生成的 nginx.conf 中: https://github.com/kubernetes/ingress-nginx/blob/controller-v0.34.1/internal/ingress/controller/nginx.go#L592 也就是說,Nginx Ingress 的連接隊(duì)列大小只取決于 somaxconn 的大小,這個(gè)值在 Nginx Ingress 默認(rèn)為 4096,建議給 Nginx Ingress 設(shè)為 65535:

  1. sysctl -w net.core.somaxconn=65535 

擴(kuò)大源端口范圍

根據(jù)《linux中TCP三次握手與四次揮手介紹及調(diào)優(yōu)》的介紹,我們知道客戶端會(huì)占用端口。在高并發(fā)場(chǎng)景會(huì)導(dǎo)致 Nginx Ingress 使用大量源端口與upstream建立連接。源端口范圍是在內(nèi)核參數(shù) net.ipv4.ip_local_port_range 中調(diào)整的。在高并發(fā)環(huán)境下,端口范圍過小容易導(dǎo)致源端口耗盡,使得部分連接異常。Nginx Ingress 創(chuàng)建的 Pod 源端口范圍默認(rèn)是 32768-60999,建議將其擴(kuò)大,調(diào)整為 1024-65535:

  1. sysctl -w net.ipv4.ip_local_port_range="1024 65535" 

TIME_WAIT

根據(jù)《linux中TCP三次握手與四次揮手介紹及調(diào)優(yōu)》的介紹,我們知道客戶端會(huì)占用端口。當(dāng)在 netns 中 TIME_WAIT 狀態(tài)的連接就比較多的時(shí)候,源端口就會(huì)被長(zhǎng)時(shí)間占用。因?yàn)槎?TIME_WAIT 連接默認(rèn)要等 2MSL 時(shí)長(zhǎng)才釋放,當(dāng)這種狀態(tài)連接數(shù)量累積到超過一定量之后可能會(huì)導(dǎo)致無法新建連接。所以建議給 Nginx Ingress 開啟 TIME_WAIT 復(fù)用,即允許將 TIME_WAIT 連接重新用于新的 TCP 連接:

  1. sysctl -w net.ipv4.tcp_tw_reuse=1 

減小FIN_WAIT2狀態(tài)的參數(shù) net.ipv4.tcp_fin_timeout 的時(shí)間和減小TIME_WAIT 狀態(tài)的參數(shù)net.netfilter.nf_conntrack_tcp_timeout_time_wait的時(shí)間 ,讓系統(tǒng)盡快釋放它們所占用的資源。

  1. sysctl -w net.ipv4.tcp_fin_timeout=15 
  2. sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30 

調(diào)大增大處于 TIME_WAIT 狀態(tài)的連接數(shù)

Nginx一定要關(guān)注這個(gè)值,因?yàn)樗鼘?duì)你的系統(tǒng)起到一個(gè)保護(hù)的作用,一旦端口全部被占用,服務(wù)就異常了。tcp_max_tw_buckets 能幫你降低這種情況的發(fā)生概率,爭(zhēng)取補(bǔ)救時(shí)間。在只有 60000 多個(gè)端口可用的情況下,配置為:

  1. sysctl -w net.ipv4.tcp_max_tw_buckets = 55000 

調(diào)大最大文件句柄數(shù)

Nginx 作為反向代理,對(duì)于每個(gè)請(qǐng)求,它會(huì)與 client 和 upstream server 分別建立一個(gè)連接,即占據(jù)兩個(gè)文件句柄,所以理論上來說 Nginx 能同時(shí)處理的連接數(shù)最多是系統(tǒng)最大文件句柄數(shù)限制的一半。系統(tǒng)最大文件句柄數(shù)由 fs.file-max 這個(gè)內(nèi)核參數(shù)來控制,默認(rèn)值為 838860,建議調(diào)大:

  1. sysctl -w fs.file-max=1048576 

配置示例

給 Nginx Ingress Controller 的 Pod 添加 initContainers 來設(shè)置內(nèi)核參數(shù):

  1. initContainers: 
  2.       - name: setsysctl 
  3.         image: busybox 
  4.         securityContext: 
  5.           privileged: true 
  6.         command: 
  7.         - sh 
  8.         - -c 
  9.         - | 
  10.           sysctl -w net.core.somaxconn=65535 
  11.           sysctl -w net.ipv4.ip_local_port_range="1024 65535" 
  12.           sysctl -w net.ipv4.tcp_max_tw_buckets = 55000 
  13.           sysctl -w net.ipv4.tcp_tw_reuse=1 
  14.           sysctl -w fs.file-max=1048576 
  15.           sysctl -w net.ipv4.tcp_fin_timeout=15 
  16.           sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30 

應(yīng)用層配置調(diào)優(yōu)

除了內(nèi)核參數(shù)需要調(diào)優(yōu),Nginx 本身的一些配置也需要進(jìn)行調(diào)優(yōu),下面我們來詳細(xì)看下。

調(diào)高 keepalive 連接最大請(qǐng)求數(shù)

keepalive_requests指令用于設(shè)置一個(gè)keep-alive連接上可以服務(wù)的請(qǐng)求的最大數(shù)量,當(dāng)最大請(qǐng)求數(shù)量達(dá)到時(shí),連接被關(guān)閉。默認(rèn)是100。這個(gè)參數(shù)的真實(shí)含義,是指一個(gè)keep alive建立之后,nginx就會(huì)為這個(gè)連接設(shè)置一個(gè)計(jì)數(shù)器,記錄這個(gè)keep alive的長(zhǎng)連接上已經(jīng)接收并處理的客戶端請(qǐng)求的數(shù)量。如果達(dá)到這個(gè)參數(shù)設(shè)置的最大值時(shí),則nginx會(huì)強(qiáng)行關(guān)閉這個(gè)長(zhǎng)連接,逼迫客戶端不得不重新建立新的長(zhǎng)連接。

簡(jiǎn)單解釋一下:QPS=10000時(shí),客戶端每秒發(fā)送10000個(gè)請(qǐng)求(通常建立有多個(gè)長(zhǎng)連接),每個(gè)連接只能最多跑100次請(qǐng)求,意味著平均每秒鐘就會(huì)有100個(gè)長(zhǎng)連接因此被nginx關(guān)閉。同樣意味著為了保持QPS,客戶端不得不每秒重新新建100個(gè)連接。因此,就會(huì)發(fā)現(xiàn)有大量的TIME_WAIT的socket連接(即使此時(shí)keep alive已經(jīng)在client和nginx之間生效)。因此對(duì)于QPS較高的場(chǎng)景,非常有必要加大這個(gè)參數(shù),以避免出現(xiàn)大量連接被生成再拋棄的情況,減少TIME_WAIT。

如果是內(nèi)網(wǎng) Ingress,單個(gè) client 的 QPS 可能較大,比如達(dá)到 10000 QPS,Nginx 就可能頻繁斷開跟 client 建立的 keepalive 連接,然后就會(huì)產(chǎn)生大量 TIME_WAIT 狀態(tài)連接。我們應(yīng)該盡量避免產(chǎn)生大量 TIME_WAIT 連接,所以,建議這種高并發(fā)場(chǎng)景應(yīng)該增大 Nginx 與 client 的 keepalive 連接的最大請(qǐng)求數(shù)量,在 Nginx Ingress 的配置對(duì)應(yīng) keep-alive-requests,可以設(shè)置為 10000,參考: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#keep-alive-requests 同樣的,Nginx 與 upstream 的 keepalive 連接的請(qǐng)求數(shù)量的配置是 upstream-keepalive-requests,參考: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#upstream-keepalive-requests

但是,一般情況應(yīng)該不必配此參數(shù),如果將其調(diào)高,可能導(dǎo)致負(fù)載不均,因?yàn)?Nginx 與 upstream 保持的 keepalive 連接過久,導(dǎo)致連接發(fā)生調(diào)度的次數(shù)就少了,連接就過于 "固化",使得流量的負(fù)載不均衡。

調(diào)高 keepalive 最大空閑連接數(shù)

Nginx 針對(duì) upstream 有個(gè)叫 keepalive 的配置,它不是 keepalive 超時(shí)時(shí)間,也不是 keepalive 最大連接數(shù),而是 keepalive 最大空閑連接數(shù)。當(dāng)這個(gè)數(shù)量被突破時(shí),最近使用最少的連接將被關(guān)閉。

簡(jiǎn)單解釋一下:有一個(gè)HTTP服務(wù),作為upstream服務(wù)器接收請(qǐng)求,響應(yīng)時(shí)間為100毫秒。如果要達(dá)到10000 QPS的性能,就需要在nginx和upstream服務(wù)器之間建立大約1000條HTTP連接。nginx為此建立連接池,然后請(qǐng)求過來時(shí)為每個(gè)請(qǐng)求分配一個(gè)連接,請(qǐng)求結(jié)束時(shí)回收連接放入連接池中,連接的狀態(tài)也就更改為idle。我們?cè)偌僭O(shè)這個(gè)upstream服務(wù)器的keepalive參數(shù)設(shè)置比較小,比如常見的10. A、假設(shè)請(qǐng)求和響應(yīng)是均勻而平穩(wěn)的,那么這1000條連接應(yīng)該都是一放回連接池就立即被后續(xù)請(qǐng)求申請(qǐng)使用,線程池中的idle線程會(huì)非常的少,趨近于零,不會(huì)造成連接數(shù)量反復(fù)震蕩。B、顯示中請(qǐng)求和響應(yīng)不可能平穩(wěn),我們以10毫秒為一個(gè)單位,來看連接的情況(注意場(chǎng)景是1000個(gè)線程+100毫秒響應(yīng)時(shí)間,每秒有10000個(gè)請(qǐng)求完成),我們假設(shè)應(yīng)答始終都是平穩(wěn)的,只是請(qǐng)求不平穩(wěn),第一個(gè)10毫秒只有50,第二個(gè)10毫秒有150:

  1. 下一個(gè)10毫秒,有100個(gè)連接結(jié)束請(qǐng)求回收連接到連接池,但是假設(shè)此時(shí)請(qǐng)求不均勻10毫秒內(nèi)沒有預(yù)計(jì)的100個(gè)請(qǐng)求進(jìn)來,而是只有50個(gè)請(qǐng)求。注意此時(shí)連接池回收了100個(gè)連接又分配出去50個(gè)連接,因此連接池內(nèi)有50個(gè)空閑連接。
  2. 然后注意看keepalive=10的設(shè)置,這意味著連接池中最多容許保留有10個(gè)空閑連接。因此nginx不得不將這50個(gè)空閑連接中的40個(gè)關(guān)閉,只留下10個(gè)。
  3. 再下一個(gè)10個(gè)毫秒,有150個(gè)請(qǐng)求進(jìn)來,有100個(gè)請(qǐng)求結(jié)束任務(wù)釋放連接。150 - 100 = 50,空缺了50個(gè)連接,減掉前面連接池保留的10個(gè)空閑連接,nginx不得不新建40個(gè)新連接來滿足要求。

C、同樣,如果假設(shè)相應(yīng)不均衡也會(huì)出現(xiàn)上面的連接數(shù)波動(dòng)情況。

它的默認(rèn)值為 32,在高并發(fā)下場(chǎng)景下會(huì)產(chǎn)生大量請(qǐng)求和連接,而現(xiàn)實(shí)世界中請(qǐng)求并不是完全均勻的,有些建立的連接可能會(huì)短暫空閑,而空閑連接數(shù)多了之后關(guān)閉空閑連接,就可能導(dǎo)致 Nginx 與 upstream 頻繁斷連和建連,引發(fā) TIME_WAIT 飆升。在高并發(fā)場(chǎng)景下可以調(diào)到 1000,參考: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#upstream-keepalive-connections

網(wǎng)關(guān)超時(shí)

ingress nginx 與 upstream pod 建立 TCP 連接并進(jìn)行通信,其中涉及 3 個(gè)超時(shí)配置,我們也相應(yīng)進(jìn)行調(diào)優(yōu)。proxy-connect-timeout 選項(xiàng) 設(shè)置 nginx 與 upstream pod 連接建立的超時(shí)時(shí)間,ingress nginx 默認(rèn)設(shè)置為 5s,由于在nginx 和業(yè)務(wù)均在內(nèi)網(wǎng)同機(jī)房通信,我們將此超時(shí)時(shí)間縮短一些,比如3秒。參考:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#proxy-connect-timeout

proxy-read-timeout 選項(xiàng)設(shè)置 nginx 與 upstream pod 之間讀操作的超時(shí)時(shí)間,ingress nginx 默認(rèn)設(shè)置為 60s,當(dāng)業(yè)務(wù)方服務(wù)異常導(dǎo)致響應(yīng)耗時(shí)飆漲時(shí),異常請(qǐng)求會(huì)長(zhǎng)時(shí)間夯住 ingress 網(wǎng)關(guān),我們?cè)诶∷蟹?wù)正常請(qǐng)求的 P99.99 耗時(shí)之后,將網(wǎng)關(guān)與 upstream pod 之間讀寫超時(shí)均縮短到 3s,使得 nginx 可以及時(shí)掐斷異常請(qǐng)求,避免長(zhǎng)時(shí)間被夯住。參考:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#proxy-read-timeout

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#proxy-send-timeout

調(diào)高單個(gè) worker 最大連接數(shù)

max-worker-connections 控制每個(gè) worker 進(jìn)程可以打開的最大連接數(shù),默認(rèn)配置是 16384。在高并發(fā)環(huán)境建議調(diào)高,比如設(shè)置到 65536,這樣可以讓 nginx 擁有處理更多連接的能力,參考: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#max-worker-connections

優(yōu)化重試機(jī)制

nginx 提供了默認(rèn)的 upstream 請(qǐng)求重試機(jī)制,默認(rèn)情況下,當(dāng) upstream 服務(wù)返回 error 或者超時(shí),nginx 會(huì)自動(dòng)重試異常請(qǐng)求,并且沒有重試次數(shù)限制。由于接入層 nginx 和 ingress nginx 本質(zhì)都是 nginx,兩層 nginx 都啟用了默認(rèn)的重試機(jī)制,異常請(qǐng)求時(shí)會(huì)出現(xiàn)大量重試,最差情況下會(huì)導(dǎo)致集群網(wǎng)關(guān)雪崩。接入層 nginx 一起解決了這個(gè)問題:接入層 nginx 必須使用 proxy_next_upstream_tries 嚴(yán)格限制重試次數(shù),ingress nginx 則使用 proxy-next-upstream="off"直接關(guān)閉默認(rèn)的重試機(jī)制。參考:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#proxy-next-upstream

開啟 brotli 壓縮

參考: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#enable-brotli

壓縮是時(shí)間換空間的通用方法。用cpu時(shí)間來換取大量的網(wǎng)絡(luò)帶寬,增大吞吐量。Brotli是Google開發(fā)的一種壓縮方法,于2015年發(fā)布。我們常用的壓縮算法是 gzip(Ingress-nginx也是默認(rèn)使用gzip),據(jù)說brotli要比gzip高出20%至30%的壓縮率。默認(rèn)的壓縮算法是gzip,壓縮級(jí)別為1,如需要啟用brotli,需要配置以下三個(gè)參數(shù):

  • enable-brotli: true 或 false,是否啟用brotli壓縮算法
  • brotli-level: 壓縮級(jí)別,范圍1~11,默認(rèn)為4,級(jí)別越高,越消耗CPU性能。
  • brotli-types: 由brotli即時(shí)壓縮的MIME類型

配置示例

Nginx 全局配置通過 configmap 配置(Nginx Ingress Controller 會(huì) watch 并自動(dòng) reload 配置):

  1. apiVersion: v1 
  2. kind: ConfigMap 
  3. metadata: 
  4.   name: nginx-ingress-controller 
  5. data: 
  6.   keep-alive-requests: "10000" 
  7.   upstream-keepalive-connections: "200" 
  8.   max-worker-connections: "65536" 
  9.   proxy-connect-timeout: "3" 
  10.   proxy-read-timeout: "3" 
  11.   proxy-send-timeout: "3" 
  12.   proxy-next-upstream: "off" 
  13.   enable-brotli: "true" 
  14.   brotli-level"6" 
  15.   brotli-types: "text/xml image/svg+xml application/x-font-ttf image/vnd.microsoft.icon application/x-font-opentype application/json font/eot application/vnd.ms-fontobject application/javascript font/otf application/xml application/xhtml+xml text/javascript application/x-javascript text/plain application/x-font-truetype application/xml+rss image/x-icon font/opentype text/css image/x-win-bitmap" 

參考資料

優(yōu)化nginx-ingress-controller并發(fā)性能:

https://cloud.tencent.com/developer/article/1537695

Nginx Ingress 配置參考:

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/

Tuning NGINX for Performance:

https://www.nginx.com/blog/tuning-nginx/

ngx_http_upstream_module 官方文檔:

http://nginx.org/en/docs/http/ngx_http_upstream_module.html

本文轉(zhuǎn)載自微信公眾號(hào)「運(yùn)維開發(fā)故事」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系運(yùn)維開發(fā)故事公眾號(hào)。

 

責(zé)任編輯:姜華 來源: 運(yùn)維開發(fā)故事
相關(guān)推薦

2023-09-15 08:00:20

Ingress網(wǎng)關(guān)Istio

2025-03-05 08:33:56

2022-04-22 13:32:01

K8s容器引擎架構(gòu)

2023-11-06 07:16:22

WasmK8s模塊

2020-11-30 11:40:35

NginxLinux性能調(diào)優(yōu)

2023-04-24 14:54:09

JVM性能調(diào)優(yōu)

2023-09-06 08:12:04

k8s云原生

2021-09-26 07:43:08

KongKongaK8s

2024-01-26 14:35:03

鑒權(quán)K8sNode

2025-03-10 08:00:05

2020-05-12 10:20:39

K8s kubernetes中間件

2022-09-05 08:26:29

Kubernetes標(biāo)簽

2021-12-06 11:03:57

JVM性能調(diào)優(yōu)

2022-04-29 10:40:38

技術(shù)服務(wù)端K8s

2023-08-03 08:36:30

Service服務(wù)架構(gòu)

2023-05-25 21:38:30

2023-08-04 08:19:02

2022-01-07 08:23:38

k8s AnnotationNginx

2024-10-15 08:37:08

2024-07-22 13:43:31

Kubernetes容器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)