您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Soul高可用網關中配置緩存三大同步策略是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
網關是流量請求的入口,在微服務架構中承擔了非常重要的角色,網關高可用的重要性不言而喻。在使用網關的過程中,為了滿足業務訴求,經常需要變更配置,比如流控規則、路由規則等等。因此,網關動態配置是保障網關高可用的重要因素。那么,Soul
網關又是如何支持動態配置的呢?
使用過 Soul
的同學都知道,Soul
的插件全都是熱插拔的,并且所有插件的選擇器、規則都是動態配置,立即生效,不需要重啟服務。但是我們在使用 Soul
網關過程中,用戶也反饋了不少問題
依賴 zookeeper
,這讓使用 etcd
、consul
、nacos
注冊中心的用戶很是困擾
依賴 redis
、influxdb
,我還沒有使用限流插件、監控插件,為什么需要這些
因此,我們對 Soul
進行了局部重構,歷時兩個月的版本迭代,我們發布了 2.0
版本
數據同步方式移除了對 zookeeper
的強依賴,新增 http 長輪詢
以及 websocket
限流插件與監控插件實現真正的動態配置,由之前的 yml
配置,改為 admin
后臺用戶動態配置
答:首先,引入配置中心,會增加很多額外的成本,不管是運維,而且會讓 Soul
變得很重;另外,使用配置中心,數據格式不可控,不便于 soul-admin
進行配置管理。
答:soul作為網關,為了提供更高的響應速度,所有的配置都緩存在JVM的Hashmap中,每次請求都走的本地緩存,速度非常快。所以本文也可以理解為分布式環境中,內存同步的三種方式。
先來張高清無碼圖,下圖展示了 Soul
數據同步的流程,Soul
網關在啟動時,會從從配置服務同步配置數據,并且支持推拉模式獲取配置變更信息,并且更新本地緩存。而管理員在管理后臺,變更用戶、規則、插件、流量配置,通過推拉模式將變更信息同步給 Soul
網關,具體是 push
模式,還是 pull
模式取決于配置。關于配置同步模塊,其實是一個簡版的配置中心。
在 1.x
版本中,配置服務依賴 zookeeper
實現,管理后臺將變更信息 push
給網關。而 2.x
版本支持 webosocket
、http
、zookeeper
,通過 soul.sync.strategy
指定對應的同步策略,默認使用 http
長輪詢同步策略,可以做到秒級數據同步。但是,有一點需要注意的是,soul-web
和 soul-admin
必須使用相同的同步機制。
如下圖所示,soul-admin
在用戶發生配置變更之后,會通過 EventPublisher
發出配置變更通知,由 EventDispatcher
處理該變更通知,然后根據配置的同步策略(http、weboscket、zookeeper),將配置發送給對應的事件處理器
如果是 websocket
同步策略,則將變更后的數據主動推送給 soul-web
,并且在網關層,會有對應的 WebsocketCacheHandler
處理器處理來處 admin
的數據推送
如果是 zookeeper
同步策略,將變更數據更新到 zookeeper
,而 ZookeeperSyncCache
會監聽到 zookeeper
的數據變更,并予以處理
如果是 http
同步策略,soul-web
主動發起長輪詢請求,默認有 90s 超時時間,如果 soul-admin
沒有數據變更,則會阻塞 http 請求,如果有數據發生變更則響應變更的數據信息,如果超過 60s 仍然沒有數據變更則響應空數據,網關層接到響應后,繼續發起 http 請求,反復同樣的請求
基于 zookeeper 的同步原理很簡單,主要是依賴 zookeeper
的 watch 機制,soul-web
會監聽配置的節點,soul-admin
在啟動的時候,會將數據全量寫入 zookeeper
,后續數據發生變更時,會增量更新 zookeeper
的節點,與此同時,soul-web
會監聽配置信息的節點,一旦有信息變更時,會更新本地緩存。
soul
將配置信息寫到zookeeper節點,是通過精細設計的。
websocket
和 zookeeper
機制有點類似,將網關與 admin
建立好 websocket
連接時,admin
會推送一次全量數據,后續如果配置數據發生變更,則將增量數據通過 websocket
主動推送給 soul-web
使用websocket同步的時候,特別要注意斷線重連,也叫保持心跳。soul
使用java-websocket
這個第三方庫來進行websocket
連接。
public class WebsocketSyncCache extends WebsocketCacheHandler { /** * The Client. */ private WebSocketClient client; public WebsocketSyncCache(final SoulConfig.WebsocketConfig websocketConfig) { ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, SoulThreadFactory.create("websocket-connect", true)); client = new WebSocketClient(new URI(websocketConfig.getUrl())) { @Override public void onOpen(final ServerHandshake serverHandshake) { //.... } @Override public void onMessage(final String result) { //.... } }; //進行連接 client.connectBlocking(); //使用調度線程池進行斷線重連,30秒進行一次 executor.scheduleAtFixedRate(() -> { if (client != null && client.isClosed()) { client.reconnectBlocking(); } }, 10, 30, TimeUnit.SECONDS); }
zookeeper、websocket 數據同步的機制比較簡單,而 http 同步會相對復雜一些。Soul 借鑒了 Apollo
、Nacos
的設計思想,取決精華,自己實現了 http
長輪詢數據同步功能。注意,這里并非傳統的 ajax 長輪詢!
http 長輪詢機制如上所示,soul-web 網關請求 admin 的配置服務,讀取超時時間為 90s,意味著網關層請求配置服務最多會等待 90s,這樣便于 admin 配置服務及時響應變更數據,從而實現準實時推送。
http 請求到達 sou-admin 之后,并非立馬響應數據,而是利用 Servlet3.0 的異步機制,異步響應數據。首先,將長輪詢請求任務 LongPollingClient
扔到 BlocingQueue
中,并且開啟調度任務,60s 后執行,這樣做的目的是 60s 后將該長輪詢請求移除隊列,即便是這段時間內沒有發生配置數據變更。因為即便是沒有配置變更,也得讓網關知道,總不能讓其干等吧,而且網關請求配置服務時,也有 90s 的超時時間。
public void doLongPolling(final HttpServletRequest request, final HttpServletResponse response) { // 因為soul-web可能未收到某個配置變更的通知,因此MD5值可能不一致,則立即響應 List<ConfigGroupEnum> changedGroup = compareMD5(request); String clientIp = getRemoteIp(request); if (CollectionUtils.isNotEmpty(changedGroup)) { this.generateResponse(response, changedGroup); return; } // Servlet3.0異步響應http請求 final AsyncContext asyncContext = request.startAsync(); asyncContext.setTimeout(0L); scheduler.execute(new LongPollingClient(asyncContext, clientIp, 60)); } class LongPollingClient implements Runnable { LongPollingClient(final AsyncContext ac, final String ip, final long timeoutTime) { // 省略...... } @Override public void run() { // 加入定時任務,如果60s之內沒有配置變更,則60s后執行,響應http請求 this.asyncTimeoutFuture = scheduler.schedule(() -> { // clients是阻塞隊列,保存了來處soul-web的請求信息 clients.remove(LongPollingClient.this); List<ConfigGroupEnum> changedGroups = HttpLongPollingDataChangedListener.compareMD5((HttpServletRequest) asyncContext.getRequest()); sendResponse(changedGroups); }, timeoutTime, TimeUnit.MILLISECONDS); // clients.add(this); } }
如果這段時間內,管理員變更了配置數據,此時,會挨個移除隊列中的長輪詢請求,并響應數據,告知是哪個 Group 的數據發生了變更(我們將插件、規則、流量配置、用戶配置數據分成不同的組)。網關收到響應信息之后,只知道是哪個 Group 發生了配置變更,還需要再次請求該 Group 的配置數據。有人會問,為什么不是直接將變更的數據寫出?我們在開發的時候,也深入討論過該問題,因為 http 長輪詢機制只能保證準實時,如果在網關層處理不及時,或者管理員頻繁更新配置,很有可能便錯過了某個配置變更的推送,安全起見,我們只告知某個 Group 信息發生了變更。
// soul-admin發生了配置變更,挨個將隊列中的請求移除,并予以響應 class DataChangeTask implements Runnable { DataChangeTask(final ConfigGroupEnum groupKey) { this.groupKey = groupKey; } @Override public void run() { try { for (Iterator<LongPollingClient> iter = clients.iterator(); iter.hasNext(); ) { LongPollingClient client = iter.next(); iter.remove(); client.sendResponse(Collections.singletonList(groupKey)); } } catch (Throwable e) { LOGGER.error("data change error.", e); } } }
當 soul-web
網關層接收到 http 響應信息之后,拉取變更信息(如果有變更的話),然后再次請求 soul-admin
的配置服務,如此反復循環。
get soul-admin.jar
> wget https://yu199195.github.io/jar/soul-admin.jar
start soul-admin.jar
java -jar soul-admin.jar -Dspring.datasource.url="your mysql url" -Dspring.datasource.username='you username' -Dspring.datasource.password='you password'
visit : http://localhost:8887/index.html username:admin password :123456
get soul-bootstrap.jar
> wget https://yu199195.github.io/jar/soul-bootstrap.jar
start soul-bootstrap.jar
java -jar soul-bootstrap.jar
此文介紹了soul
作為一個高可用的微服務網關,為了優化響應速度,在對配置規則選擇器器數據進行本地緩存的三種方式,學了此文,我相信你對現在比較流行的配置中心有了一定的了解,看他們的代碼也許會變得容易,我相信你也可以自己寫一個分布式配置中心出來。3.0版本已經在規劃中,肯定會給大家帶來驚喜。
以上就是Soul高可用網關中配置緩存三大同步策略是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。