iT邦幫忙

2025 iThome 鐵人賽

DAY 17
0
Cloud Native

與雲原生精靈共舞:APISIX使用者的兩年旅程系列 第 17

Ch11 - APISIX設定斷路器與限流,保護上游服務的兩大關鍵防線

  • 分享至 

  • xImage
  •  

「什麼!服務受到DoS攻擊,資料庫無法負荷交易,服務癱瘓了!?」

一天早晨,聽說別部門服務受到DoS阻斷式攻擊,更蝦趴的是來源是內部IP,實際是因爲客戶端設置錯誤,造成頻繁請求,最終導致資料庫無法負荷交易,間接造成服務處理節點癱瘓失效。

這也造成了我開始接觸Apache APISIX的原因。

那幾天開始與不同部門的IT人員交流,討論該如何避免相似問題再度發生。恰恰那段時間之前,在學習了解微服務的概念,聽過朋友提到過斷路器/熔斷器。

不知道大家有沒有這樣的經驗:再使用高功率電器產品的時候,像是使用吹風機吹頭髮、開個烤箱烤土司、用微波爐加熱便當......然後就跳電了。

這時候需要先把高功率電子產品關閉,再去找到總電閘把電閘打開。

跳電,其實是一種保護機制。電線的電流壓力達到臨界,再增加可能引起電線走火、電器產品毀壞,更糟糕可能引起大型火災,人財兩失。跳電,是為了預防更大的危險。而電閘跳開的機構,就叫做「斷路器」,跳開形成斷路/電流無法形成迴路,電器產品便無法使用。

更早以前家庭使用的斷路器,同時也是熔斷器。熔斷器我在一些產品上還有看過,像是旅用萬國轉接頭。其原理是透過一根低熔點的金屬細絲形成整體迴路,也因此叫做「保險絲」。當電流增加,金屬絲溫度也上升,最後達到金屬絲融化的極限溫度,金屬融化也就無法形成迴路。「保險絲」犧牲自己,用斷路保護後面的家庭與電器。

https://ithelp.ithome.com.tw/upload/images/20251001/20112470zVQwspGrAf.png
(圖片來源: https://i.sstatic.net/NrcnJ.jpghttps://electronics.stackexchange.com/questions/227432/glass-fuse-selection-rule)

微服務,軟體的「斷路器」也是同樣目的。目的是為了保護上游服務節點,特別是軟體服務經常有自我恢復性,有可能在一段時間休息後就自我恢復。因此「斷路器」的作用,就是為了提供這一段空白的休息時間。

具有斷路器能力的反向代理工具,並不是只有Apache APISIX,Kong Gateway、Tyk也都有相關功能。會採用Apache APISIX的原因其實很單純:選擇上是第一個嘗試的,並且符合需求,也就沒有在嘗試其他工具。

難怪商業課上會討論「先行者優勢」🤔

其實像學習OAuth 2.0時,會使用「Keycloak」一樣,Apache APISIX最初也是個人私下學習為目的的。因此更多的不算是考量其商業價值,而是其原始碼授權和免費資源豐富性為考慮。Apache APISIX已經是Apache基金會下的頂級項目(Top-Level Project),使用友善Apache授權。貢獻至Apache前,項目有華人發起,當時相對豐富的中文資源。並且部落格還有一篇「有了NGINX和Kong,爲什麼還需要Apache APISIX - 韓飛」和BilBil研討會影片

https://ithelp.ithome.com.tw/upload/images/20251001/20112470u3SFTqnHbW.png

關於Apache APISIX的api-breaker斷路器plugin

APISIX的api-breaker Plugin大致邏輯如下:

「當上游端點回覆狀態碼是不健康的,並達到斷路觸發次數,則引發斷路時間。斷路時間由2秒、4秒、8秒方式倍增,直至斷路時間允許最大值(如300秒),提供上游恢復的休息時間。而當上游標記為不健康狀態,但回覆狀態碼是健康的,並達到回復成迴路的次數,則恢復轉發請求。」

因此需要考慮幾個部分的設定:

  • 什麼是不健康的回覆狀態碼?
  • 不健康臨界次數
  • 最大斷路時間
  • 什麼是健康的回覆狀態碼?
  • 視作健康臨界次數
  • 當斷路形成時,回覆給客戶端的狀態碼與內容是什麼?

接下來的DEMO會更為清楚以上結果。

DEMO: 斷路器LAB

1. 建立httpbin服務

為了收到「不健康的回覆狀態碼」,並不能像是「新竹百貨公司」的例子,簡單使用http-server。因此我們需要換一個上游,換成httpbin這個服務。你可以直接透過 https://httpbin.org/ 玩玩看,也可在本地透過docker建立起本地服務:

docker run -p 8085:80 kennethreitz/httpbin

或是同樣建立docker-compose.yaml檔案,並用docker compose up啓動服務:

services:
  httpbin01:
    image: kennethreitz/httpbin
    ports:
      - 8085:80

2. 設定APISIX路由

建立一個名稱為「httpbin」的路由。這次直接在路由設定上游節點內容:https://httpbin.org:443。你也可以添加/換成自架的httpbin服務http://localhost:8085

https://ithelp.ithome.com.tw/upload/images/20251001/20112470cpjEFqF4mZ.png

另外特別注意超時設定,可以維持預設的6秒即可。這次LAB會透過超時機制實現。

https://ithelp.ithome.com.tw/upload/images/20251001/20112470ayTQvgk1ff.png

3. 設定api-breakder plugin

參數 備註
什麼是不健康的回覆狀態碼? 504 Gateway回復上游超時
不健康臨界次數 3次
最大斷路時間 300秒
什麼是健康的回覆狀態碼? 200
視作健康臨界次數 3次
當斷路形成時,回覆給客戶端的狀態碼與內容是什麼? 回覆503狀態 內容「斷路器」

https://ithelp.ithome.com.tw/upload/images/20251001/20112470KUzJmgi7Lr.png

要在Dashboard設定斷路器,需要在apisix_dashboard_config/config.yamlplugins區段添加api-breaker
像是:

plugins:                          # plugin list (sorted in alphabetical order)
 - api-breaker

4. Delay API

https://ithelp.ithome.com.tw/upload/images/20251001/20112470GLC88w5jEb.png

這次LAB會利用httpbin的/delay/{delay} API來完成實驗。簡單來說瀏覽 http://localhost:9080/delay/2後,會等待2秒才收到回覆。

https://ithelp.ithome.com.tw/upload/images/20251001/201124705PMr2Uocc6.png

Apache APISIX同樣有一個plugin可以模擬超時行爲--fault-injection可以設定delay.duration

另外注意2秒的延遲情況,狀態碼是200。相對來說,如果延遲超過6秒,也就會觸發APISIX的Gateway超時,並且恢復狀態碼是504

https://ithelp.ithome.com.tw/upload/images/20251001/20112470hx2GfhvCOP.png

5. 觸發「斷路器api-breaker」plugin

現在來試試延遲10秒4次看看: http://localhost:9080/delay/10 。會發現回覆狀態碼變成了503,並且內容顯示「斷路器」。再看使用時間,幾乎是秒回。如果回去看APISIX的記錄,會發現它直接回覆,而不將請求轉發給上游處理。

https://ithelp.ithome.com.tw/upload/images/20251001/20112470D0DTgAXeyc.png

可能要再過個5分鐘(300秒),才會恢復到504的超時狀態。

限流

「斷路器」做法在上游節點已經發生問題時,才會發揮作用。如果對於平常流量使用有了解,知道正常使用情況如何,DoS攻擊又如何,那麼可以設定限流。

https://ithelp.ithome.com.tw/upload/images/20251001/20112470TqCuEnmGY2.png

在「高乘載管制」已經見過以請求數量限制流量的方式,APISIX還可以依照「請求數量」、「連線數量」進行限制。這節僅針對「高乘載管制」中「請求數量限制」進一步說明。設定的參數如下:

https://ithelp.ithome.com.tw/upload/images/20251001/20112470f94UCg9ztr.png

count: 1
time_window: 60
key_type: var
key: remote_addr
rejected_code: 429
rejected_msg: 高乘載管制
show_limit_quota_header: true

首先看到key_typekey的設定,表示針對remote_addr,也就是客戶端請求IP個別限制。如果192.168.56.9被限制流量了,192.168.56.10並不會因此受到影響。

接著看看rejected_coderejected_msg,這兩個參數顯示當請求數量超過後,APISIX回覆給客戶端的狀態碼和內容。

show_limit_quota_header則允許限制狀態恢復給客戶端了解。

最後是計算的時間窗格time_window和在時間窗格內允許的數量。方便實驗,設置成了60秒的時間窗格和僅1次的數量。

DEMO: 限流

可以同樣對「httpbin」路由套用「高乘載管制」的服務,然後請求 http://localhost:9080/get 一次看看

curl -s -v http://127.0.0.1:9080/get

https://ithelp.ithome.com.tw/upload/images/20251001/201124709o7w2IQdLe.png

第一次收到的狀態碼應該是200,並且在回覆的HEADER內可以看到限速狀態訊息。如果在60秒內再發送一次請求,則會收到429的狀態碼,而回覆內容是{"error_msg":"高乘載管制"}

https://ithelp.ithome.com.tw/upload/images/20251001/20112470FEVF91vC2J.png

本章節介紹了兩種上游節點的保護方式:「斷路」和「限流」。不過其實更挑戰的是,應該怎麼設定兩者才是適合的?這可能需要知道平常的使用情況,服務水平或垂直擴展的能力等等。也歡迎有人和我分享適合的做法~


上一篇
幕間2 - 啟用TLS遇到的兩個問題與解決方式:設定`fallback_sni` & 啓用 TLS 1.0
下一篇
Ch12 - 5 分鐘變身格式魔術師:APISIX 用 body-transformer 秒殺 JSON ↔ XML 資料轉換!
系列文
與雲原生精靈共舞:APISIX使用者的兩年旅程22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言