阿里一面:Nacos配置中心交互模型是 push 還是 pull ?(原理+源碼分析)

對于Nacos大家應該都不太陌生,出身阿里名聲在外,能做動態服務發現、配置管理,非常好用的一個工具。然而這樣的技術用的人越多面試被問的概率也就越大,如果只停留在使用層面,那面試可能要吃大虧。

比如我們今天要討論的話題,Nacos在做配置中心的時候,配置數據的交互模式是服務端推過來還是客戶端主動拉的?

圖片

這里我先拋出答案:客戶端主動拉的!

接下來咱們扒一扒Nacos的源碼,來看看它具體是如何實現的?

配置中心

Nacos之前簡單回顧下配置中心的由來。

簡單理解配置中心的作用就是對配置統一管理,修改配置后應用可以動態感知,而無需重啟。

因為在傳統項目中,大多都采用靜態配置的方式,也就是把配置信息都寫在應用內的ymlproperties這類文件中,如果要想修改某個配置,通常要重啟應用才可以生效。

但有些場景下,比如我們想要在應用運行時,通過修改某個配置項,實時的控制某一個功能的開閉,頻繁的重啟應用肯定是不能接受的。

尤其是在微服務架構下,我們的應用服務拆分的粒度很細,少則幾十多則上百個服務,每個服務都會有一些自己特有或通用的配置。假如此時要改變通用配置,難道要我挨個改幾百個服務配置?很顯然這不可能。所以為了解決此類問題配置中心應運而生。

圖片

配置中心

推與拉模型

客戶端與配置中心的數據交互方式其實無非就兩種,要么推push,要么拉pull

推模型

客戶端與服務端建立TCP長連接,當服務端配置數據有變動,立刻通過建立的長連接將數據推送給客戶端。

優勢:長鏈接的優點是實時性,一旦數據變動,立即推送變更數據給客戶端,而且對于客戶端而言,這種方式更為簡單,只建立連接接收數據,并不需要關心是否有數據變更這類邏輯的處理。

弊端:長連接可能會因為網絡問題,導致不可用,也就是俗稱的假死。連接狀態正常,但實際上已無法通信,所以要有的心跳機制KeepAlive來保證連接的可用性,才可以保證配置數據的成功推送。

拉模型

客戶端主動的向服務端發請求拉配置數據,常見的方式就是輪詢,比如每3s向服務端請求一次配置數據。

輪詢的優點是實現比較簡單。但弊端也顯而易見,輪詢無法保證數據的實時性,什么時候請求?間隔多長時間請求一次?都是不得不考慮的問題,而且輪詢方式對服務端還會產生不小的壓力。

長輪詢

開篇我們就給出了答案,nacos采用的是客戶端主動拉pull模型,應用長輪詢(Long Polling)的方式來獲取配置數據。

額?以前只聽過輪詢,長輪詢又是什么鬼?它和傳統意義上的輪詢(暫且叫短輪詢吧,方便比較)有什么不同呢?

短輪詢

不管服務端配置數據是否有變化,不停的發起請求獲取配置,比如支付場景中前段JS輪詢訂單支付狀態。

這樣的壞處顯而易見,由于配置數據并不會頻繁變更,若是一直發請求,勢必會對服務端造成很大壓力。還會造成推送數據的延遲,比如:每10s請求一次配置,如果在第11s時配置更新了,那么推送將會延遲9s,等待下一次請求。

圖片

為了解決短輪詢的問題,有了長輪詢方案。

長輪詢

長輪詢可不是什么新技術,它不過是由服務端控制響應客戶端請求的返回時間,來減少客戶端無效請求的一種優化手段,其實對于客戶端來說與短輪詢的使用并沒有本質上的區別。

客戶端發起請求后,服務端不會立即返回請求結果,而是將請求掛起等待一段時間,如果此段時間內服務端數據變更,立即響應客戶端請求,若是一直無變化則等到指定的超時時間后響應請求,客戶端重新發起長鏈接。

圖片

Nacos初識

為了后續演示操作方便我在本地搭了個Nacos注意:?運行時遇到個小坑,由于Nacos默認是以cluster集群的方式啟動,而本地搭建通常是單機模式standalone,這里需手動改一下啟動腳本startup.X中的啟動模式。

圖片

直接執行/bin/startup.X就可以了,默認用戶密碼均是nacos

圖片

幾個概念

Nacos配置中心的幾個核心概念:dataIdgroupnamespace,它們的層級關系如下圖:

圖片

dataId:是配置中心里最基礎的單元,它是一種key-value結構,key通常是我們的配置文件名稱,比如:application.ymlmybatis.xml,而value是整個文件下的內容。

目前支持JSONXMLYAML等多種配置格式。

圖片

group:dataId配置的分組管理,比如同在dev環境下開發,但同環境不同分支需要不同的配置數據,這時就可以用分組隔離,默認分組DEFAULT_GROUP

namespace:項目開發過程中肯定會有devtestpro等多個不同環境,namespace則是對不同環境進行隔離,默認所有配置都在public里。

架構設計

下圖簡要描述了nacos配置中心的架構流程。

客戶端、控制臺通過發送Http請求將配置數據注冊到服務端,服務端持久化數據到Mysql。

客戶端拉取配置數據,并批量設置對dataId的監聽發起長輪詢請求,如服務端配置項變更立即響應請求,如無數據變更則將請求掛起一段時間,直到達到超時時間。為減少對服務端壓力以及保證配置中心可用性,拉取到配置數據客戶端會保存一份快照在本地文件中,優先讀取。

圖片

這里我省略了比較多的細節,如鑒權、負載均衡、高可用方面的設計(其實這部分才是真正值得學的,后邊另出文講吧),主要弄清客戶端與服務端的數據交互模式。

下邊我們以Nacos 2.0.1版本源碼分析,2.0以后的版本改動較多,和網上的很多資料略有些不同 地址:https://github.com/alibaba/nacos/releases/tag/2.0.1

客戶端源碼分析

Nacos配置中心的客戶端源碼在nacos-client項目,其中NacosConfigService實現類是所有操作的核心入口。

說之前先了解個客戶端數據結構cacheMap,這里大家重點記住它,因為它幾乎貫穿了Nacos客戶端的所有操作,由于存在多線程場景為保證數據一致性,cacheMap采用了AtomicReference原子變量實現。

/*** groupKey -> cacheData.*/
private?final?AtomicReference<Map<String, CacheData>> cacheMap =?new?AtomicReference<Map<String, CacheData>>(new?HashMap<>());

cacheMap是個Map結構,key為groupKey,是由dataId, group, tenant(租戶)拼接的字符串;value為CacheData對象,每個dataId都會持有一個CacheData對象。

獲取配置

Nacos獲取配置數據的邏輯比較簡單,先取本地快照文件中的配置,如果本地文件不存在或者內容為空,則再通過HTTP請求從遠端拉取對應dataId配置數據,并保存到本地快照中,請求默認重試3次,超時時間3s。

圖片

獲取配置有getConfig()getConfigAndSignListener()這兩個接口,但getConfig()只是發送普通的HTTP請求,而getConfigAndSignListener()則多了發起長輪詢和對dataId數據變更注冊監聽的操作addTenantListenersWithContent()

@Override
public?String?getConfig(String dataId, String group,?long?timeoutMs)?throws?NacosException?{return?getConfigInner(namespace, dataId, group, timeoutMs);
}@Override
public?String?getConfigAndSignListener(String dataId, String group,?long?timeoutMs, Listener listener)throws?NacosException?{String content = getConfig(dataId, group, timeoutMs);worker.addTenantListenersWithContent(dataId, group, content, Arrays.asList(listener));return?content;
}

注冊監聽

客戶端注冊監聽,先從cacheMap中拿到dataId對應的CacheData對象。

public?void?addTenantListenersWithContent(String dataId, String group, String content,List<? extends Listener> listeners)?throws?NacosException?{group = blank2defaultGroup(group);String tenant = agent.getTenant();// 1、獲取dataId對應的CacheData,如沒有則向服務端發起長輪詢請求獲取配置CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);synchronized?(cache) {// 2、注冊對dataId的數據變更監聽cache.setContent(content);for?(Listener listener : listeners) {cache.addListener(listener);}cache.setSyncWithServer(false);agent.notifyListenConfig();}
}

如沒有則向服務端發起長輪詢請求獲取配置,默認的Timeout時間為30s,并把返回的配置數據回填至CacheData對象的content字段,同時用content生成MD5值;再通過addListener()注冊監聽器。

圖片

CacheData也是個出場頻率非常高的一個類,我們看到除了dataId、group、tenant、content這些相關的基礎屬性,還有幾個比較重要的屬性如:listenersmd5(content真實配置數據計算出來的md5值),以及注冊監聽、數據比對、服務端數據變更通知操作都在這里。

圖片

其中listeners是對dataId所注冊的所有監聽器集合,其中的ManagerListenerWrap對象除了持有Listener監聽類,還有一個lastCallMd5字段,這個屬性很關鍵,它是判斷服務端數據是否更變的重要條件。

在添加監聽的同時會將CacheData對象當前最新的md5值賦值給ManagerListenerWrap對象的lastCallMd5屬性。

public?void?addListener(Listener listener)?{ManagerListenerWrap wrap =(listener?instanceof?AbstractConfigChangeListener) ??new?ManagerListenerWrap(listener, md5, content):?new?ManagerListenerWrap(listener, md5);
}

看到這對dataId監聽設置就完事了?我們發現所有操作都圍著cacheMap結構中的CacheData對象,那么大膽猜測下一定會有專門的任務來處理這個數據結構。

圖片

變更通知

客戶端又是如何感知服務端數據已變更呢?

我們還是從頭看,NacosConfigService類的構造器中初始化了一個ClientWorker,而在ClientWorker類的構造器中又啟動了一個線程池來輪詢cacheMap

圖片

而在executeConfigListen()方法中有這么一段邏輯,檢查cacheMap中dataId的CacheData對象內,MD5字段與注冊的監聽listener內的lastCallMd5值,不相同表示配置數據變更則觸發safeNotifyListener方法,發送數據變更通知。

void?checkListenerMd5()?{for?(ManagerListenerWrap wrap : listeners) {if?(!md5.equals(wrap.lastCallMd5)) {safeNotifyListener(dataId, group, content, type, md5, encryptedDataKey, wrap);}}
}

safeNotifyListener()方法單獨起線程,向所有對dataId注冊過監聽的客戶端推送變更后的數據內容。

圖片

客戶端接收通知,直接實現receiveConfigInfo()方法接收回調數據,處理自身業務就可以了。

configService.addListener(dataId, group,?new?Listener() {@Overridepublic?void?receiveConfigInfo(String configInfo)?{System.out.println("receive:"?+ configInfo);}@Overridepublic?Executor?getExecutor()?{return?null;}
});

為了理解更直觀我用測試demo演示下,獲取服務端配置并設置監聽,每當服務端配置數據變化,客戶端監聽都會收到通知,一起看下效果。

public?static?void?main(String[] args)?throws?NacosException, InterruptedException?{String serverAddr =?"localhost";String dataId =?"test";String group =?"DEFAULT_GROUP";Properties properties =?new?Properties();properties.put("serverAddr", serverAddr);ConfigService configService = NacosFactory.createConfigService(properties);String content = configService.getConfig(dataId, group,?5000);System.out.println(content);configService.addListener(dataId, group,?new?Listener() {@Overridepublic?void?receiveConfigInfo(String configInfo)?{System.out.println("數據變更 receive:"?+ configInfo);}@Overridepublic?Executor?getExecutor()?{returnnull;}});boolean?isPublishOk = configService.publishConfig(dataId, group,?"我是新配置內容~");System.out.println(isPublishOk);Thread.sleep(3000);content = configService.getConfig(dataId, group,?5000);System.out.println(content);
}

結果和預想的一樣,當向服務端publishConfig數據變化后,客戶端可以立即感知,愣是用主動拉pull模式做出了服務端實時推送的效果。

數據變更 receive:我是新配置內容~
true
我是新配置內容~

服務端源碼分析

Nacos配置中心的服務端源碼主要在nacos-config項目的ConfigController類,服務端的邏輯要比客戶端稍復雜一些,這里我們重點看下。

處理長輪詢

服務端對外提供的監聽接口地址/v1/cs/configs/listener,這個方法內容不多,順著doPollingConfig往下看。

圖片

服務端根據請求header中的Long-Pulling-Timeout屬性來區分請求是長輪詢還是短輪詢,這里咱們只關注長輪詢部分,接著看LongPollingService(記住這個service很關鍵)類中的addLongPollingClient()方法是如何處理客戶端的長輪詢請求的。

圖片

正常客戶端默認設置的請求超時時間是30s,但這里我們發現服務端“偷偷”的給減掉了500ms,現在超時時間只剩下了29.5s,那為什么要這樣做呢?

用官方的解釋之所以要提前500ms響應請求,為了最大程度上保證客戶端不會因為網絡延時造成超時,考慮到請求可能在負載均衡時會耗費一些時間,畢竟Nacos最初就是按照阿里自身業務體量設計的嘛!

圖片

此時對客戶端提交上來的groupkey的MD5與服務端當前的MD5比對,如md5值不同,則說明服務端的配置項發生過變更,直接將該groupkey放入changedGroupKeys集合并返回給客戶端。

MD5Util.compareMd5(req, rsp, clientMd5Map)

如未發生變更,則將客戶端請求掛起,這個過程先創建一個名為ClientLongPolling的調度任務Runnable,并提交給scheduler定時線程池延后29.5s執行。

ConfigExecutor.executeLongPolling(new?ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));

這里每個長輪詢任務攜帶了一個asyncContext對象,使得每個請求可以延遲響應,等延時到達或者配置有變更之后,調用asyncContext.complete()響應完成。

asyncContext 為 Servlet 3.0新增的特性,異步處理,使Servlet線程不再需要一直阻塞,等待業務處理完畢才輸出響應;可以先釋放容器分配給請求的線程與相關資源,減輕系統負擔,其響應將被延后,在處理完業務或者運算后再對客戶端進行響應。

圖片

ClientLongPolling任務被提交進入延遲線程池執行的同時,服務端會通過一個allSubs隊列保存所有正在被掛起的客戶端長輪詢請求任務,這個是客戶端注冊監聽的過程。

如延時期間客戶端據數一直未變化,延時時間到達后將本次長輪詢任務從allSubs隊列剔除,并響應請求response,這是取消監聽。收到響應后客戶端再次發起長輪詢,循環往復。

圖片

處理長輪詢

到這我們知道服務端是如何掛起客戶端長輪詢請求的,一旦請求在掛起期間,用戶通過管理平臺操作了配置項,或者服務端收到了來自其他客戶端節點修改配置的請求。

怎么能讓對應已掛起的任務立即取消,并且及時通知客戶端數據發生了變更呢?

數據變更

管理平臺或者客戶端更改配置項接位置ConfigController中的publishConfig方法。

圖片

值得注意得是,在publishConfig接口中有這么一段邏輯,某個dataId配置數據被修改時會觸發一個數據變更事件Event

ConfigChangePublisher.notifyConfigChange(new?ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime()));

仔細看LongPollingService會發現在它的構造方法中,正好訂閱了數據變更事件,并在事件觸發時執行一個數據變更調度任務DataChangeTask

圖片

訂閱數據變更事件

DataChangeTask內的主要邏輯就是遍歷allSubs隊列,上邊我們知道,這個隊列中維護的是所有客戶端的長輪詢請求任務,從這些任務中找到包含當前發生變更的groupkeyClientLongPolling任務,以此實現數據更變推送給客戶端,并從allSubs隊列中剔除此長輪詢任務。

圖片

DataChangeTask

而我們在看給客戶端響應response時,調用asyncContext.complete()結束了異步請求。

圖片

結束語

上邊只揭開了nacos配置中心的冰山一角,實際上還有非常多重要的技術細節都沒提及到,建議大家沒事看看源碼,源碼不需要通篇的看,只要抓住核心部分就夠了。就比如今天這個題目以前我真沒太在意,突然被問一下子吃不準了,果斷看下源碼,而且這樣記憶比較深刻(別人嚼碎了喂你的知識總是比自己咀嚼的差那么點意思)。

nacos的源碼我個人覺得還是比較樸素的,代碼并沒有過多炫技,看起來相對輕松。大家不要對看源碼有什么抵觸,它也不過是別人寫的業務代碼而已,just so so!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77125.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77125.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77125.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DAY09:【pytorch】nn網絡層

1、卷積層 1.1 Convolution 1.1.1 卷積操作 卷積運算&#xff1a;卷積核在輸入信號&#xff08;圖像&#xff09;上滑動&#xff0c;相應位置上進行乘加卷積核&#xff1a;又稱為濾波器、過濾器&#xff0c;可認為是某種模式、某種特征 1.1.2 卷積維度 一般情況下&#xf…

Pinpoint - 大型分布式系統的 APM(應用性能管理)工具

文章目錄 一、關于 Pinpoint最新版本&#xff08;2024/10/23&#xff09;-- v3.0.1PHP, PYTHON 二、概述支持的模塊 一、關于 Pinpoint Pinpoint 是一個用于大型分布式系統的 APM&#xff08;應用性能管理&#xff09;工具&#xff0c;由 Java / PHP/PYTHON 編寫。 受 Dapper …

設計模式實踐:模板方法、觀察者與策略模式詳解

目錄 1 模板方法1.1 模板方法基本概念1.2 實驗1.2.1 未使用模板方法實現代碼1.2.2 使用模板方法的代碼 2 觀察者模式2.1 觀察者模式基本概念2.2 實驗 3 策略模式3.1 策略模式基本概念3.2 實驗 1 模板方法 1.1 模板方法基本概念 定義&#xff1a;一個操作中的算法的骨架 &…

Vue 2.0和3.0筆記

Vue 3 關于組件 今天回顧了下2.0關于組件的內容&#xff0c;3.0定義組件的方式多了一種就是通過單文件組件&#xff08;Single-File Component&#xff09;的方式將Vue的模板&#xff0c;邏輯和樣式放到一個文件中&#xff0c;2.0則不同&#xff0c;它是將模板放到一個屬性中…

前端面試-微前端

1. 什么是微前端&#xff1f;它的核心價值是什么&#xff1f; 答案&#xff1a; 微前端是一種將前端應用拆分為獨立模塊的架構模式&#xff0c;每個模塊可由不同團隊獨立開發、測試、部署和運行。其核心價值包括&#xff1a; 技術棧無關性&#xff1a;支持 React、Vue、Angul…

Axure高保真AI算法訓練平臺

點擊下載《Axure高保真AI算法訓練平臺(.rp) 》 原型效果&#xff1a;https://axhub.im/ax9/69fdf8f2b10b59c3/#g1 摘要 本文介紹了一款功能全面且高效的AI算法訓練平臺&#xff0c;旨在為數據科學家、研究人員和工程師提供從數據準備到模型部署的一站式解決方案。該平臺由四大…

Ubuntu服務器日志滿audit:backlog limit exceeded了會報錯解決方案-Linux 審計系統 (auditd) 工具

auditd 是 Linux 系統中的審計守護進程&#xff0c;負責收集、記錄和監控系統安全相關事件。以下是相關工具及其功能&#xff1a; 核心組件 auditd - 審計守護進程 系統的審計服務主程序 收集系統調用信息并寫入日志文件 通常存儲在 /var/log/audit/audit.log auditctl - 審計控…

Windows10系統RabbitMQ無法訪問Web端界面

項目場景&#xff1a; 提示&#xff1a;這里簡述項目相關背景&#xff1a; 項目場景&#xff1a; 在一個基于 .NET 的分布式項目中&#xff0c;團隊使用 RabbitMQ 作為消息隊列中間件&#xff0c;負責模塊間的異步通信。開發環境為 Windows 10 系統&#xff0c;開發人員按照官…

Qt 的 事件隊列

Qt 的 事件隊列 是其核心事件處理機制之一&#xff0c;用于管理和分發系統與用戶生成的事件&#xff08;如鼠標點擊、鍵盤輸入、定時器、信號槽中的隊列連接等&#xff09;。理解 Qt 的事件隊列對多線程、界面響應以及異步處理尤為關鍵。 一、Qt 的事件處理模型概覽 Qt 是基于…

無人機自主導航與路徑規劃技術要點!

一、自主導航與路徑規劃技術要點 1. 傳感器融合 GPS/北斗定位&#xff1a;提供全局定位&#xff0c;但在室內或遮擋環境下易失效。 慣性測量單元&#xff08;IMU&#xff09;**&#xff1a;通過加速度計和陀螺儀實時追蹤姿態&#xff0c;彌補GPS信號丟失時的定位空缺。 …

Before After:SQL整容級優化

首先說明這個優化有一定提升&#xff0c;但不是我所期望的 我接到一個涉及優化的SQL&#xff0c;具體內容實在太長。而且可能也不利于閱讀。于是我脫敏以及簡化一下。SQL中間大量的充斥著 (select 列名1 from t1 where t1.id t2.id ) A, (select 列名2 from t1 where t1.id …

道可云人工智能每日資訊|首屆世界人工智能電影節在法國尼斯舉行

道可云元宇宙每日簡報&#xff08;2025年4月15日&#xff09;訊&#xff0c;今日元宇宙新鮮事有&#xff1a; 杭州《西湖區打造元宇宙產業高地的扶持意見》發布 杭州西湖區人民政府印發《西湖區打造元宇宙產業高地的扶持意見》。該意見已于4月4日正式施行&#xff0c;有效期至…

JVM 為什么需要即時編譯器?

JVM之所以需要即時編譯器 (JIT Compiler)&#xff0c;是為了提高 Java 程序的執行性能&#xff0c;彌補純解釋器執行的不足。 我們可以從以下幾個角度來分析一下這個問題&#xff1a; 1. 解釋器的性能瓶頸: 逐條解釋的開銷: 解釋器需要逐條讀取 Java 字節碼指令&#xff0c;并…

PromptUp 網站介紹:AI助力,輕松創作

1. 網站定位與核心功能 promptup.net 可能是一個面向 創作者、設計師、營銷人員及藝術愛好者 的AI輔助創作平臺,主打 零門檻、智能化的內容生成與優化。其核心功能可能包括: AI藝術創作:通過輸入關鍵詞、選擇主題或拖放模板,快速生成風格多樣的數字藝術作品(如插畫、海報…

ThingsBoard3.9.1 MQTT Topic(1)

1.網關轉發子設備的遙測信息, Topic:v1/gateway/telemetry { "m1": [{ "mode": "CW", "temperature": 23 }], "m2": [{ "mode": "CW", "temperature": 23 }] } 說明&#xff1a;json格式&a…

React 入門教程:構建第一個 React 應用

本教程將帶你從零開始構建你的第一個 React 應用。我們將創建一個簡單的計數器應用&#xff0c;涵蓋 React 的基本概念和開發流程。 準備工作 在開始之前&#xff0c;請確保你的開發環境滿足以下要求&#xff1a; Node.js (建議使用最新的 LTS 版本) npm 或 yarn (Node.js 安…

vue3中,element-plus中el-input的v-model和value的用法示例

el-input的v-model&#xff0c;邦定響應式變量 <el-col :span"6"><el-form-item label"檢驗類別" prop"verifyType"><el-input v-model"applyAllInfo.applyBasicInfo.verifyTypeName" readonly /></el-form-item…

策略模式隨筆~

若感行文枯燥&#xff0c;請移步至文末Gitee地址中查看源碼自行測試感受策略模式之魅力。 一、策略模式的核心概念 策略模式的定義 定義算法族&#xff0c;封裝每個算法&#xff0c;使其可互換。 核心三要素 Context&#xff1a;上下文&#xff0c;負責接收客戶端請求并委托…

Linux的目錄結構(介紹,具體目錄結構)

目錄 介紹 具體目錄結構 簡潔的目錄解釋 詳細的目錄解釋 介紹 Linux的文件系統是采用級層式的樹狀目錄結構&#xff0c;在此結構的最上層是根目錄“/”。Linux的世界中&#xff0c;一切皆文件&#xff08;比如&#xff1a;Linux會把硬件映射成文件來管理&#xff09; 具體目…

AWS CloudFront加速S3配置跨域

1、點擊分配 源我們就選擇S3–>選擇我們要加速的S3存儲桶 2、創建OAC訪問方式 在我們的來源訪問處–>來源訪問控制設置(推薦)–>選擇創建新的OAC(Create new OAC)–>自定義名字按默認選項保存–>選擇剛剛新創建的OAC 3、選擇查看器的配置 根據具體情況&#x…