CDN: Push 和 Pull CDN 的應用場景與使用考量
什麼是 CDN ?
全名是 Content Delivery Network(內容傳遞網路),是一種透過分佈式的伺服器網路來加速網站和應用程式內容傳遞的技術。這些伺服器分佈在世界各地,目的是將內容更靠近用戶,從而提高訪問速度和效能。CDN 的伺服器稱為節點,當用戶請求網站內容時,CDN 會將請求路由到距離用戶最近的節點,提供最快的回應時間。
如果要我比喻 CDN 的話,他很像物流業者的倉庫。
舉例來說:物流業者有總倉庫和各個地點的小倉庫,當小倉庫設在離你家很近的地方,而且物流業者定期都會從總倉庫拉貨到你家旁邊的小倉庫的時候,當你訂貨購買,貨物只要從你家小倉庫送到你家就好,相當快速。
→ 所以,以台灣用戶來說,如果有節點在台灣,回應速度是最快的。
可以想像成:貨物從日本倉庫送來 vs 貨物從台灣倉庫直送的時間差
什麼是 Push 型 CDN ?
- 主動上傳內容: 在 push 型 CDN 中,需要「主動」將資源上傳到你指定的 storage,再配置 CDN 使其知道從哪個 storage 拿取資料並進行分發。
- 內容管理: 因為是主動上傳,開發者可以精確控制哪些文件被上傳到 storage 讓 CDN 分發,以及何時上傳。如果需要更新文件,也需要重新上傳到 storage,並且使 CDN cache 失效,以抓取新的內容。這種方式提供了更高的控制度,但也需要更多的主動管理
- cache 管理:可以透過 CDN 提供的 API 或控制面板主動清除或更新相關的 cache。或者可以使用檔案版本控制來管理內容更新。
舉例:css 檔案原本叫做test.css
,更新之後改成test_v2.css
這樣當 request 發出時,因為請求的是test_v2.css
所以不會拿舊的 cache 資料 - 優點:
- 內容僅在發生變更時才上傳到 storage 並觸發 CDN 更新,CDN 的 cache 時效可以設定較長,由於更新是主動控制的,減少頻繁檢查更新的需求,從而降低資源 ( origin ) 到 CDN 之間的流量。
- 即使伺服器當機,CDN 仍然可以透過用 storage 提供資源
- 缺點
- 需要額外設置 storage 作為資料來源,也需要定期刪除 storage 裡面陳舊的資料
什麼是 pull 型 CDN ?
- 自動拉取內容: 當用戶第一次請求某個資源時,CDN 節點會自動從 origin server(如你的主機) 抓取該資源並 cache 起來,後續請求則從 cache 中獲取。這個過程是自動化的,無需手動上傳。
- cache 管理: CDN 節點會根據設定的 cache 策略來決定資源 (assets) 的 cache 時間。當資源過期或被更新時,CDN 節點會再次從 origin server 抓取最新的資源。或者使用使用檔案版本控制來管理內容更新
- 適用動態和頻繁更新的內容: Pull 型 CDN 特別適合那些動態生成或頻繁更新的內容,因為它能自動檢測並拉取最新的資源,確保用戶獲得最新的內容。(但對於非常頻繁更新的內容,可能需要額外的配置來確保內容的即時性)
- 優點
- 較少的初始配置: 由於內容是根據用戶請求自動拉取,Pull 型 CDN 的初始配置簡單,設定好要抓取的來源即可,無需預先上傳大量資源。
- 缺點
- 如果 server 發生故障,CDN 將無法獲取資源。不過 CDN 會在 cache 過期前繼續提供舊的 cache 內容,即使 server 不可用。
為什麼要有 push CDN 的作法?
感覺 pull CDN 超方便,實際做過之後發現設置簡易,不像 push CDN 因為需要考慮上傳的資料為哪些、怎麼刪除 storage 陳舊資料、怎麼配置 CDN 抓取的 source 以及路徑等等問題,而且看完上面說明之後,查了很多資料還是不懂為什麽 pull CDN 沒有取代 push CDN???
舉例:假設我們有兩台伺服器:伺服器 A( EC2 - A ) 和伺服器 B ( EC2 - B )。並且 CDN 的來源站(Origin)被設置為 ELB,其中每台 EC2 有各自的資源 (assets),而 CDN 就是要去拿到這些資源做 cache。
以這個配置來說,透過 ELB 有可能是跟 EC2 - A 或 EC2 - B 拿到資源
先參考下圖簡易架構:
(ELB 就是 Elastic Load Balancer 的簡稱)
參考下圖的流程說明:
- 初始狀態:
- 伺服器 A 和伺服器 B 都運行著 version 1 的代碼。
- 資源 ( assets )(例如圖片、CSS 文件等)對應於 version 1。
- 部署開始:
- 我們開始部署新版本( version 2)。
- 部署過程中,伺服器 A 先完成了部署,開始運行 version 2 的程式碼。
- 伺服器 B 還在運行 version 1 的代碼,還沒開始 restart。
(什麼? 部署時伺服器不會同時重新啟動,部署竟然還會有時間差的問題?!)
- 請求處理:
- 使用者發出請求,ELB 發請求給伺服器 A,該請求被伺服器 A 接收到。
- 伺服器 A 使用 version 2 的代碼來處理請求,並返回一個引用到新資源(例如:
/assets/image_v2.png
)。 - 使用者的瀏覽器通過 Cloudfront 請求這個資源。
- 資源獲取:
- Cloudfront 會去尋找這個資源。如果它沒有 cache 到這個資源,可能會轉而請求 ELB ,而 ELB 剛好是轉給伺服器 B。
- 由於伺服器 B 還在運行 version 1 的程式碼,而這個新資源(
/assets/image_v2.png
)並不存在,伺服器 B 會回應一個 404 錯誤,表示找不到資源。
補充說明:剛剛前面提到伺服器 B 還沒 restart,這個情境是說伺服器仍在正常運行。如果還在部署中的機器,ELB 會用 health check 檢驗 EC2 回應狀態,失敗就不會發 request 給他。另外,這裡不考慮藍綠部署情境。
以上只是簡易版本,實際上如果只有兩台機器,部署時間差是很小的。
會需要考慮這個狀況應該是要有多台 EC2 的情境。由此可知,這也是為什麼 push CDN 仍然存在的原因。網路上還是很多影片教把資源存到 AWS 的 S3 裡統一管理。
用 Storage 儲存還有其他好處:
- 統一管理和版本控制:可以在 Storage 中擁有相同資源的多個版本
- 部署時間優化:可以節省部署時間,變成只要打包一次靜態檔案上傳到 Storage 共用即可,不需要每台 server 都做打包靜態檔案的動作
個人感想:我是覺得 push CDN 在使用上會需要花比較多心思,假設改善部署時間只有一分鐘的差異(微小),實際因為部署時間差造成 404 問題很少的話,我是不會特別去設定 storage 來做 push CDN 的,因為在設定跟考量的配置上,絕對是 pull CDN 樂勝。以上是我的感想,也歡迎留言跟我討論~