springcloud中gateway存在的意義

SpringCloudGateway和SpringCloudZuul一樣是微服務網關,不過Gateway是SpringCloud官方推出的,而Zuul是Netflix推出的 。
看其他人的一些文章說是Gateway是用于取代Zuul的第二代網關,這個我在官方找不到資料說明 。
主要術語
default-filters: 里面可以定義一些共同的filter,對所有路由都起作用
routes:具體的路由信息,是一個數組,每一個路由基本包含部分:
id:這個路由的唯一id,不定義的話為一個uuid
uri:http請求為lb://前綴 + 服務id;ws請求為lb:ws://前綴 + 服務id;表示將請求負載到哪一個服務上
predicates:表示這個路由的請求匹配規則,只有符合這個規則的請求才會走這個路由 。為一個數組,每個規則為并且的關系 。
filters:請求轉發前的filter,為一個數組 。
order:這個路由的執行order
網關請求
SpringCloudGateway限流原理與實踐
緩存、降級和限流是開發高并發系統的三把利器 。緩存的目的是提升系統訪問速度和增大系統能處理的容量,可謂是抗高并發流量的銀彈;降級是當服務出現問題或者影響到核心流程的性能則需要暫時屏蔽,待高峰或者問題解決后再打開;而有些場景并不能用緩存和降級來解決,比如稀缺資源、寫服務、頻繁的復雜查詢,因此需有一種手段來限制這些場景的并發/請求量,即限流 。
限流的目的是通過對并發訪問/請求進行限速,或對一個時間窗口內的請求進行限速來保護系統 。一旦達到限制速率則可以拒絕服務、排隊或等待、降級 。
一般開發高并發系統常見的限流有:限制總并發數、限制瞬時并發數、限制時間窗口內的平均速率、限制遠程接口的調用速率、限制MQ的消費速率,或根據網絡連接數、網絡流量、CPU或內存負載等來限流 。
本文主要就分布式限流方法,對Spring Cloud Gateway的限流原理進行分析 。
分布式限流最關鍵的是要將限流服務做成原子化,常見的限流算法有:令牌桶、漏桶等,Spring Cloud Gateway使用Redis+Lua技術實現高并發和高性能的限流方案 。
令牌桶算法
令牌桶算法是一個存放固定容量令牌的桶,按照固定速率往桶里添加令牌 。令牌桶算法的描述如下:
假如用戶配置的平均速率為r,則每隔1/r秒一個令牌被加入到桶中;
假設桶最多可以存發b個令牌 。如果令牌到達時令牌桶已經滿了,那么這個令牌會被丟棄;
當一個n個字節大小的數據包到達,將從桶中刪除n個令牌,接著數據包被發送到網絡上;
如果令牌桶中少于n個令牌,那么不會刪除令牌,并且認為這個數據包在流量限制之外;
算法允許最長b個字節的突發,但從長期運行結果看,數據包的速率被限制成常量r 。對于在流量限制外的數據包可以以不同的方式處理:
它們可以被丟棄;
它們可以排放在隊列中以便當令牌桶中累積了足夠多的令牌時再傳輸;
它們可以繼續發送,但需要做特殊標記,網絡過載的時候將這些特殊標記的包丟棄 。
漏桶算法
漏桶作為計量工具(The Leaky Bucket Algorithm as a Meter)時,可以用于流量整形(Traffic Shaping)和流量控制(Traffic Policing),漏桶算法的描述如下:
【springcloud中gateway存在的意義】一個固定容量的漏桶,按照常量固定速率流出水滴;
如果桶是空的,則不需流出水滴;
可以以任意速率流入水滴到漏桶;
如果流入水滴超出了桶的容量,則流入的水滴溢出了(被丟棄),而漏桶容量是不變的 。
實踐
SpringCloudGateway限流方案
Spring Cloud Gateway 默認實現 Redis限流,如果擴展只需要實現Ratelimter接口即可,同時也可以通過自定義KeyResolver來指定限流的Key,比如我們需要根據用戶、IP、URI來做限流等等,通過exchange對象可以獲取到請求信息,比如:
用戶限流
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
SpringCloudGateway默認提供的RedisRateLimter 的核心邏輯為判斷是否取到令牌的實現,通過調用 META-INF/scripts/request_rate_limiter.lua 腳本實現基于令牌桶算法限流
這個要理解為什么做網關 。簡單扼要來講,就是為了處理每個服務都要做的事情 。你可以認為是切面變成了服務 。
路由,協議轉換,鑒權認證,熔斷,限流 。這些邏輯和你實際的業務代碼沒太大關系,但是每個業務服務都要搞一個,顯得很累贅重復 。那怎么辦呢?
兩種解決思路 。
一,使用gateway服務,所有的服務均接入和調用這個gateway,由gateway把這些通用問題處理了,再去請求實際的業務邏輯 。gateway是關鍵節點,瓶頸節點 。spring cloud gateway也是這樣 。它連接了系統的所有方方面面,是個大管家 。除了spring cloud gateway,其他的代表還有netty,kong,zuul等

springcloud中gateway存在的意義


圖侵刪

二,集成到本地,可以用sidecar,類似一個代理服務器 。sidecar就是那種有拖斗的三輪摩托車,旁邊的那個人輔助給你觀察 。下面是sidecar的架構 。
springcloud中gateway存在的意義


圖侵刪
啊不對,放錯了 。應該是下面這個 。
springcloud中gateway存在的意義


圖侵刪
其實萬變不離其宗 。首先,你確認有一些邏輯是通用的(鑒權,限流,路由),再是你提取了出來(變成了AOP切面邏輯),然后你把他寫成一個單獨的服務給這個服務用(sidecar),最后,你把這個服務給所有服務用(gateway) 。
淺顯的理解就是這樣 。

    推薦閱讀