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

Kubernetes用了,延遲高了10倍,問題在哪?

新聞 前端
當(dāng)我們團隊將業(yè)務(wù)遷移至 Kubernetes 之后,一旦出現(xiàn)問題,總有人覺得“這是遷移之后的陣痛”,并把矛頭指向 Kubernetes,但最終事實證明犯錯的并不是 Kubernetes。

當(dāng)我們團隊將業(yè)務(wù)遷移至 Kubernetes 之后,一旦出現(xiàn)問題,總有人覺得“這是遷移之后的陣痛”,并把矛頭指向 Kubernetes,但最終事實證明犯錯的并不是 Kubernetes。雖然文章并不涉及關(guān)于 Kubernetes 的突破性啟示,但我認(rèn)為內(nèi)容仍值得各位管理復(fù)雜系統(tǒng)的朋友借鑒。

近期,我所在的團隊將一項微服務(wù)遷移到中央平臺。這套中央平臺捆綁有 CI/CD,基于 Kubernetes 的運行時以及其他功能。這項演習(xí)也將作為先頭試點,用于指導(dǎo)未來幾個月內(nèi)另外 150 多項微服務(wù)的進一步遷移。而這一切,都是為了給西班牙的多個主要在線平臺(包括 Infojobs、Fotocasa 等)提供支持。

在將應(yīng)用程序部署到 Kubernetes 并路由一部分生產(chǎn)流量過去后,情況開始發(fā)生變化。Kubernetes 部署中的請求延遲要比 EC2 上的高出 10 倍。如果不找到解決辦法,不光是后續(xù)微服務(wù)遷移無法正常進行,整個項目都有遭到廢棄的風(fēng)險。

為什么 Kubernetes 中的延遲要遠高于 EC2?  

為了查明瓶頸,我們收集了整個請求路徑中的指標(biāo)。這套架構(gòu)非常簡單,首先是一個 API 網(wǎng)關(guān)(Zuul),負(fù)責(zé)將請求代理至運行在 EC2 或者 Kubernetes 中的微服務(wù)實例。在 Kubernetes 中,我們僅代表和 NGINX Ingress 控制器,后端則為運行有基于 Spring 的 JVM 應(yīng)用程序的 Deployment 對象。  

  1. EC2 
  2.                          +---------------+ 
  3.                        |  +---------+  | 
  4.                        |  |         |  | 
  5.                     +-------> BACKEND |  | 
  6.                    |    |  |         |  | 
  7.                    |    |  +---------+  | 
  8.                   |    +---------------+ 
  9.         +------+  | 
  10. ublic       |      |  | 
  11.      -------> ZUUL +--+ 
  12. raffic      |      |  |              Kubernetes 
  13.             +------+  |    +-----------------------------+ 
  14.                       |    |  +-------+      +---------+ | 
  15.                       |    |  |       |  xx  |         | | 
  16.                       +-------> NGINX +------> BACKEND | | 
  17.                            |  |       |  xx  |         | | 
  18.                            |  +-------+      +---------+ | 
  19.                            +-----------------------------+ 

問題似乎來自后端的上游延遲(我在圖中以「xx」進行標(biāo)記)。將應(yīng)用程序部署至 EC2 中之后,系統(tǒng)大約需要 20 毫秒就能做出響應(yīng)。但在 Kubernetes 中,整個過程卻需要 100 到 200 毫秒。

我們很快排除了隨運行時間變化而可能出現(xiàn)的可疑對象。JVM 版本完全相同,而且由于應(yīng)用程序已經(jīng)運行在 EC2 容器當(dāng)中,所以問題也不會源自容器化機制。另外,負(fù)載強度也是無辜的,因為即使每秒只發(fā)出 1 項請求,延遲同樣居高不下。另外,GC 暫停時長幾乎可以忽略不計。

我們的一位 Kubernetes 管理員詢問這款應(yīng)用程序是否具有外部依賴項,因為 DNS 解析之前就曾引起過類似的問題,這也是我們目前找到的可能性最高的假設(shè)。

假設(shè)一:DNS 解析

在每一次請求時,我們的應(yīng)用程序都像域中的某個 AWS ElasticSearch 實例(例如 elastic.spain.adevinta.com)發(fā)出 1 到 3 條查詢。我們在容器中添加了一個 shell,用于驗證該域名的 DNS 解析時間是否過長。

來自容器的 DNS 查詢結(jié)果:

  1. [root@be-851c76f696-alf8z /]# while truedo dig "elastic.spain.adevinta.com" | grep time; sleep 2; done 
  2. ;; Query time: 22 msec 
  3. ;; Query time: 22 msec 
  4. ;; Query time: 29 msec 
  5. ;; Query time: 21 msec 
  6. ;; Query time: 28 msec 
  7. ;; Query time: 43 msec 
  8. ;; Query time: 39 msec 

來自運行這款應(yīng)用程序的 EC2 實例的相同查詢結(jié)果:

  1. bash-4.4while truedo dig "elastic.spain.adevinta.com" | grep time; sleep 2; done 
  2. ;; Query time: 77 msec 
  3. ;; Query time: 0 msec 
  4. ;; Query time: 0 msec 
  5. ;; Query time: 0 msec 
  6. ;; Query time: 0 msec 

前者的平均解析時間約為 30 毫秒,很明顯,我們的應(yīng)用程序在其 ElasticSearch 上造成了額外的 DNS 解析延遲。

但這種情況非常奇怪,原因有二:

  • Kubernetes 當(dāng)中已經(jīng)包含大量與 AWS 資源進行通信的應(yīng)用程序,而且都沒有出現(xiàn)延遲過高的情況。因此,我們必須弄清引發(fā)當(dāng)前問題的具體原因。
  • 我們知道 JVM 采用了內(nèi)存內(nèi)的 DNS 緩存。從配置中可以看到,TTL 在 $JAVA_HOME/jre/lib/security/java.security 位置進行配置,并被設(shè)置為 networkaddress.cache.ttl = 10。JVM 應(yīng)該能夠以 10 秒為周期緩存所有 DNS 查詢。

為了確認(rèn) DNS 假設(shè),我們決定剝離 DNS 解析步驟,并查看問題是否可以消失。我們的第一項嘗試是讓應(yīng)用程序直接與 ELasticSearch IP 通信,從而繞過域名機制。這需要變更代碼并進行新的部署,即需要在 /etc.hosts 中添加一行代碼以將域名映射至其實際 IP:

  1. 34.55.5.111 elastic.spain.adevinta.com 

通過這種方式,容器能夠以近即時方式進行 IP 解析。我們發(fā)現(xiàn)延遲確實有所改進,但距離目標(biāo)等待時間仍然相去甚遠。盡管 DNS 解析時長有問題,但真正的原因還沒有被找到。

網(wǎng)絡(luò)管道

我們決定在容器中進行 tcpdump,以便準(zhǔn)確觀察網(wǎng)絡(luò)的運行狀況。

  1. [root@be-851c76f696-alf8z /]# tcpdump -leni any -w capture.pcap 

我們隨后發(fā)送了多項請求并下載了捕捉結(jié)果(kubectl cp my-service:/capture.pcap capture.pcap),而后利用 Wireshark 進行檢查。

DNS 查詢部分一切正常(少部分值得討論的細(xì)節(jié),我將在后文提到)。但是,我們的服務(wù)處理各項請求的方式有些奇怪。以下是捕捉結(jié)果的截圖,顯示出在響應(yīng)開始之前的請求接收情況。

Kubernetes 用了,延迟高了 10 倍,问题在哪?

數(shù)據(jù)包編號顯示在第一列當(dāng)中。為了清楚起見,我對不同的 TCP 流填充了不同的顏色。

從數(shù)據(jù)包 328 開始的綠色部分顯示,客戶端(172.17.22.150)打開了容器(172.17.36.147)間的 TCP 連接。在最初的握手(328 至 330)之后,數(shù)據(jù)包 331 將 HTTP GET /v1/..(傳入請求)引向我們的服務(wù),整個過程耗時約 1 毫秒。

來自數(shù)據(jù)包 339 的灰色部分表明,我們的服務(wù)向 ElasticSearch 實例發(fā)送了 HTTP 請求(這里沒有顯示 TCP 握手,是因為其使用原有 TCP 連接),整個過程耗費了 18 毫秒。

到這里,一切看起來還算正常,而且時間也基本符合整體響應(yīng)延遲預(yù)期(在客戶端一側(cè)測量為 20 到 30 毫秒)。

但在兩次交換之間,藍色部分占用了 86 毫秒。這到底是怎么回事?在數(shù)據(jù)包 333,我們的服務(wù)向 /latest/meta-data/iam/security-credentials 發(fā)送了一項 HTTP GET 請求,而后在同一 TCP 連接上,又向 /latest/meta-data/iam/security-credentials/arn:.. 發(fā)送了另一項 GET 請求。

我們進行了驗證,發(fā)現(xiàn)整個流程中的每項單一請求都發(fā)生了這種情況。在容器內(nèi),DNS 解析確實有點慢(理由同樣非常有趣,有機會的話我會另起一文詳加討論)。但是,導(dǎo)致高延遲的真正原因,在于針對每項單獨請求的 AWS Instance Metadata Service 查詢。

假設(shè)二:指向 AWS 的流氓調(diào)用

兩個端點都是 AWS Instance Metadata API 的組成部分。我們的微服務(wù)會在從 ElasticSearch 中讀取信息時使用該服務(wù)。這兩條調(diào)用屬于授權(quán)工作的基本流程,端點通過第一項請求產(chǎn)生與實例相關(guān)的 IAM 角色。

  1. / # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ 
  2. arn:aws:iam::<account_id>:role/some_role 

第二條請求則向第二個端點查詢實例的臨時憑證:

  1. / # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/arn:aws:iam::<account_id>:role/some_role` 
  2.     "Code" : "Success"
  3.     "LastUpdated" : "2012-04-26T16:39:16Z"
  4.     "Type" : "AWS-HMAC"
  5.     "AccessKeyId" : "ASIAIOSFODNN7EXAMPLE"
  6.     "SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  7.     "Token" : "token"
  8.     "Expiration" : "2017-05-17T15:09:54Z" 

客戶可以在短時間內(nèi)使用這些憑證,且端點會定期(在 Expiration 過期之前)檢索新憑證。這套模型非常簡單:出于安全原因,AWS 經(jīng)常輪換臨時密鑰,但客戶端可以將密鑰緩存幾分鐘,從而抵消檢索新憑證所帶來的性能損失。

照理來說,整個過程應(yīng)該由 AWS Java SDK 為我們處理。但不知道為什么,實際情況并非如此。搜索了一遍 GitHub 問題,我們從 #1921 當(dāng)中找到了需要的線索。

AWS SDK 會在滿足以下兩項條件之一時刷新憑證:

  • Expiration 已經(jīng)達到 EXPIRATION_THRESHOLD 之內(nèi),硬編碼為 15 分鐘。
  • 最后一次刷新憑證的嘗試大于 REFRESH_THRESHOLD,硬編碼為 60 分鐘。

我們希望查看所獲取憑證的實際到期時間,因此我們針對容器 API 運行了 cURL 命令——分別指向 EC2 實例與容器。但容器給出的響應(yīng)要短得多:正好 15 分鐘。現(xiàn)在的問題很明顯了:我們的服務(wù)將為第一項請求獲取臨時憑證。由于有效時間僅為 15 分鐘,因此在下一條請求中,AWS SDK 會首先進行憑證刷新,每一項請求中都會發(fā)生同樣的情況。

為什么憑證的過期時間這么短?

AWS Instance Metadata Service 在設(shè)計上主要適合 EC2 實例使用,而不太適合 Kubernetes。但是,其為應(yīng)用程序保留相同接口的機制確實很方便,所以我們轉(zhuǎn)而使用 KIAM,一款能夠運行在各個 Kubernetes 節(jié)點上的工具,允許用戶(即負(fù)責(zé)將應(yīng)用程序部署至集群內(nèi)的工程師)將 IAM 角色關(guān)聯(lián)至 Pod 容器,或者說將后者視為 EC2 實例的同等對象。其工作原理是攔截指向 AWS Instance Metadata Service 的調(diào)用,并利用自己的緩存(預(yù)提取自 AWS)及時接上。從應(yīng)用程序的角度來看,整個流程與 EC2 運行環(huán)境沒有區(qū)別。

KIAM 恰好為 Pod 提供了周期更短的臨時憑證,因此可以合理做出假設(shè),Pod 的平均存在周期應(yīng)該短于 EC2 實例——默認(rèn)值為 15 分鐘。如果將兩種默認(rèn)值放在一起,就會引發(fā)問題。提供給應(yīng)用程序的每一份證書都會在 15 分鐘之后到期,但 AWS Java SDK 會對一切剩余時間不足 15 分鐘的憑證做出強制性刷新。

結(jié)果就是,每項請求都將被迫進行憑證刷新,這使每項請求的延遲提升。接下來,我們又在 AWS Java SDK 中發(fā)現(xiàn)了一項功能請求,其中也提到了相同的問題。

相比之下,修復(fù)工作非常簡單。我們對 KIAM 重新配置以延長憑證的有效期。在應(yīng)用了此項變更之后,我們就能夠在不涉及 AWS Instance Metadata Service 的情況下開始處理請求,同時返回比 EC2 更低的延遲水平。

總結(jié)  

根據(jù)我們的實際遷移經(jīng)驗,最常見的問題并非源自 Kubernetes 或者該平臺其他組件,與我們正在遷移的微服務(wù)本身也基本無關(guān)。事實上,大多數(shù)問題源自我們急于把某些組件粗暴地整合在一起。

我們之前從來沒有復(fù)雜系統(tǒng)的整合經(jīng)驗,所以這一次我們的處理方式比較粗糙,未能充分考慮到更多活動部件、更大的故障面以及更高熵值帶來的實際影響。

在這種情況下,導(dǎo)致延遲升高的并不是 Kubernetes、KIAM、AWS Java SDK 或者微服務(wù)層面的錯誤決策。相反,問題源自 KIAM 與 AWS Java SDK 當(dāng)中兩項看似完全正常的默認(rèn)值。單獨來看,這兩個默認(rèn)值都很合理:AWS Java SDK 希望更頻繁地刷新憑證,而 KIAM 設(shè)定了較低的默認(rèn)過期時間。但在二者結(jié)合之后,卻產(chǎn)生了病態(tài)的結(jié)果。是的,各個組件能夠正常獨立運行,并不代表它們就能順利協(xié)作并構(gòu)成更龐大的系統(tǒng)。 

 

責(zé)任編輯:張燕妮 來源: 高效開發(fā)運維
相關(guān)推薦

2016-10-11 17:38:40

WIFI網(wǎng)絡(luò)卡頓

2022-03-07 10:41:09

云計算容器Kubernetes

2023-11-07 12:07:22

2019-11-01 10:57:07

延遲TCPBuffer

2020-06-11 08:05:47

nginx線程池數(shù)據(jù)

2020-12-24 19:29:08

PCIntel芯片

2020-06-12 14:44:06

線程池模式nginx

2021-12-08 12:50:39

代碼MyBatisJava

2021-01-11 18:57:21

微軟Windows 10Windows

2024-02-07 13:37:39

AWS系統(tǒng)應(yīng)用程序

2021-06-27 17:07:02

Snapchat QU網(wǎng)絡(luò)協(xié)議網(wǎng)絡(luò)

2024-05-11 09:24:15

性能Go團隊

2021-02-02 15:38:19

Disruptor緩存Java

2020-07-22 01:21:26

軟件開發(fā)開發(fā)代碼

2024-08-29 13:16:51

2017-05-31 15:36:59

5G頻譜傳感器

2019-06-21 08:39:23

SQLmysql索引

2015-07-20 08:51:55

釣魚網(wǎng)站深信服

2009-07-01 18:05:54

JSP中文亂碼

2024-07-12 11:44:39

點贊
收藏

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