我們目前架構使用的 MemoryRateLimiterStorage
計數器,所有的限流狀態、計次,都存在 JVM 的記憶體中:
private static final ConcurrentHashMap<String, Counter> storage = new ConcurrentHashMap<>();
這在單一 AP Server (Application Server) 的環境下運作正常,但在多 AP 實例的分散式環境下會遇到一些挑戰,如:
狀態隔離:每個 AP 實例都有自己的記憶體空間
用戶A 在 AP01 已經用完了 5 次的請求額度,但 LoadBalancer 將他下個請求路由到了 AP02,由於 AP02 沒有用戶A 的請求紀錄,所以又會重新開始計次,等於用戶A 最終使用了超出預期的限流次數。
無法水平擴展:如果沒有做分散式的限流置,新增的 AP 實例不會繼承現有的限流狀態,重啟的應用會丟失所有限流紀錄,無法實現統一限流。
所以我們接下來要努力的方向,就是如何將現有架構擴展成分散式的系統,讓多個獨立的 AP 實例可以共享統一份限流狀態,因此我們需要一個外部的、持久的、高可用的狀態儲存系統。而這條路上我們要跨越的核心挑戰包括但不限於:
選擇 Redis 不一定是因為它是「最完美」的解決方案,而是因為它是「最 Balance」的,它在一致性、效能、複雜度之間取得了平衡。明天開始實作 SpringBoot 裡 Redis Client 的基礎配置。