雲計算

【 CDN 最佳實踐】CDN 加速 OSS 常見問題及處理思路

作者:燁爍

CDN 加速 OSS 是常見的站點動靜分離的方式,可以實現將靜態資源存儲在 OSS 上,並通過 CDN 加速 OSS 實現靜態資源的訪問加速效果。但是在實際使用的過程中可能會出現使用方法以及配置上的問題導致使用上出現難題。本文檔主要就 CDN 加速 OSS 的配置以及各注意事項進行描述已解決本使用場景中遇到的問題。

  1. 使用場景描述

圖 1 所示即是常見的站點動靜分離的解決方案。從該圖中可以查看到整個站點數據包括動態資源和靜態資源兩個部分,其中動態資源主要是指站點的 web 程序以及數據庫等內容,其主要部署在雲服務器 ECS 上(數據庫可部署在 RDS 上)。該部分控制了整個站點的業務邏輯,用戶會發動態請求到業務服務器,業務服務器決定了系統邏輯返回給客戶以什麼動態數據。而另外一部分則是以靜態腳本(例如 css 、 js 文件等)、圖片、音視頻等靜態資源。這些靜態資源存儲在 OSS 中,然後通過 CDN 對這些靜態資源的下載操作進行加速。而維護 OSS 中的數據則可以通過 ECS 內網操作 OSS 以進行增刪改操作。
image.png

圖 1. 動靜分離架構示意圖

這樣設計的優勢在於:

  1. 靜態資源的訪問將直接通過 CDN 的邏輯直接返回給客戶端,而不需要佔用 ECS 的各項負載(主要包括帶寬、 CPU 以及內存等)。同時靜態資源的上傳也可以通過客戶端直接上傳至 OSS ,避免再經過ECS 。
  2. CDN 和 OSS 本身提供的下行帶寬非常的高( OSS 限制 5Gbps ,而 CDN 不限制)。因此 ECS 僅需要保證動態數據所佔用的帶寬資源即可(一般動態資源佔用的下行帶寬相比於靜態資源較少),可以節省ECS 的帶寬規格,節約成本。
  3. 同一數據中心的 ECS 和 OSS 之間是可以直接通過阿里雲的內網進行數據交互的,因此可以保證 ECS 和
    OSS 的網絡質量。
  4. CDN 提供了靠近客戶端的節點緩存靜態資源,因此在訪問靜態資源時會優先在 CDN 節點中獲取以減少網絡傳輸距離。保證了靜態資源的服務質量。同時 CDN 本身提供全球節點加速,可以一定程度的緩解運營商的國際鏈路對訪問帶來的影響。
  5. 常見問題及解決方案

CDN 加速 OSS 的配置方法可以參考通過 CDN 加速 OSS Bucket,但是經常有用戶配置完成後發現使用異常的情況,大致可以分為以下三類。接下來我們詳細描述:

解析未生效。

問題1:域名解析異常。
在 CDN 加速 OSS 的場景中當 CDN 和 OSS 都配置完成後將分別得到 CNAME 域名, CDN 本身有加速域名對應的 CNAME 域名,而OSS 有本身的域名。這裡生效時需要用戶設置該域名的 CNAME 解析到 CDN 的 CNAME 域名上方可生效。例如圖 2 中即是 CDN 加速域名及其對應的 CNAME 域名,用戶在配置完成 DNS 解析後可以通過圖 3 的方式驗證測試。
image.png

圖 2. CDN 的 CNAME 域名示意圖

image.png

圖 3. dig命令檢測解析是否生效示意圖

問題 2 :域名選擇錯誤。
使用 CDN 加速 OSS 的場景是肯定需要用戶提供一個域名解析到 CDN 上方可提供服務。而這裡常有客戶選擇自己域名的主域名或者www子域名等已經使用的域名添加到 CDN 和 OSS 上。
由於域名本身限制一個主機記錄僅能夠配置一個 A 記錄或者 CNAME 記錄,因此如果該域名已經解析到您的服務器上的話請不要將該域名再添加在 CDN 和 OSS 上。特別需要注意的是如圖 4 中的“自動添加CNAME 記錄”的操作將會直接在雲解析中添加 CNAME 記錄,因此如果該域名有其他的用途可能會導致訪問異常。
image.png

圖 4. 自動添加解析記錄示意圖

訪問異常。

問題 1 :回源 host 未綁定在 OSS 的域名管理
CDN 的回源設置包括:回源地址(可以設置為 IP 或者域名)、回源端口和回源 Host 幾個參數。由於 OSS 是沒有提供固定 IP ,而是通過 OSS 域名提供服務的,因此 CDN 回源 OSS 時回源地址寫 OSS 的公網域名即可(注意:CDN 回源都是通過公網回源的,因此這裡只能夠填寫 OSS 的公網域名,不可以使用 OSS 的內網地址)。而回源端口則可以選擇 80 或者 443 分別代表了 http 協議回源和 https 協議回源的兩種方式。而回源 Host 參數表示了 CDN 請求回到源站時HTTP 的 Request 頭中的 Host 字段的值。
該 Host 字段指代了源站服務器上具體是哪個應用 server 提供服務的,在 OSS 的場景中由於同一區域的 OSS 是由提供一組前端機提供服務,因此前端機是需要根據 Host 字段識別具體訪問的是哪個bucket 中的數據。
在 CDN 加速 OSS 的場景中的回源 Host 設置方法一般有兩種:設置回源 Host 為 OSS 本身的域名和設置為加速域名。如果設置為 OSS 本身的域名當然 OSS 前端機是可以識別為訪問的哪個 Bucket ;而如果設置加速域名那麼是需要將該域名綁定在該 Bucket 的自定義域名中,如圖 5 中所示的 wqvod.pier39.cn 這個加速域名回源 Host 為加速域名時時需要在Bucket中綁定該域名不能才可以正常訪問的。
image.png

圖 5. 回源Host示意圖

問題 2 :OSS 默認首頁不生效
OSS 可以配置靜態託管功能,可以配置默認首頁和 404 頁面。默認首頁即使通過 Bucket 的根目錄即可直接訪問設置的默認首頁 html 。例如如下圖的配置,當訪問 “http://dongchics.oss-cn-hangzhou.aliyuncs.com/” 時就會顯示 “http://dongchics.oss-cn-hangzhou.aliyuncs.com/1.html” 的內容提供服務。
image.png

圖 6. 默認首頁設置示意圖

但是當添加 CDN 加速 OSS 後並且在 CDN 上配置“私有 Bucket 回源”功能後會發現通過 CDN 加速域名的根目錄訪問無法獲取得到 OSS的默認首頁,而訪問得到的是如下圖所示的一個 XML 文件。從該文件的內容上可以查看到返回的內容是 OSS 調用 listObjects 返回的結果,其原因就是當開啟“私有 Bucket 回源”後, CDN 訪問 OSS 的URL 就會是簽名 URL ,而帶有簽名參數的 URL 訪問 OSS 的根目錄是不會執行默認首頁跳轉邏輯的,而是直接調用了 listObjects 並顯示返回如圖7中的結果,因此該問題的處理方案即使關閉“私有 Bucket 回源”即可。
image.png

圖 7. 默認首頁未生效示意圖

問題 3 :CDN 導致 OSS 文件大小變化
OSS 通過 putObject 等上傳方式都是會在 response 頭中記錄content-length 和 content-MD5 的信息返回給客戶端,如圖8所示。用戶可以根據該信息確定本地下載得到的文件是否與 OSS 服務器端存儲的數據是否一致。
image.png

圖 8. Response頭信息示意圖

但是當客戶使用 CDN 加速 OSS 後驗證本地的數據有時會發現本地下載的文件與 OSS 上存儲的文件的 content-length 或者 content-MD5不一致。出現該情況有以下原因:

  • 獲取 CDN 上的歷史緩存。由於 OSS 上的文件更新而 CDN 上仍然緩存著歷史的舊數據導致的該問題,可以通過刷新 CDN 緩存解決。
  • CDN 的智能壓縮功能。 CDN 會對滿足特定條件的文件自動做 gzip壓縮,當客戶端發送的 Request 頭有 Accept-Encoding : gzip ,即表示客戶端支持 gzip 壓縮並且滿足CDN智能壓縮就會進行壓縮,而壓縮後就會導致該文件更改為 chunked 編碼,將無法獲取得到 content-length 。
  • CDN 的頁面優化功能。 CDN 針對於 html 文件提供了 trim 的功能,即 CDN 在開啟頁面優化功能後可以幫助用戶自動去掉 html 頁面中的空格以及註釋,這樣可以減少下行流量。但是這就會導致客戶端接收到的 content-length 或者 content-MD5 發生變化。
  • HTTP 劫持問題。當如果客戶端到 CDN 的 L1 節點或者 CDN 的 L2 節點回源到源站使用 HTTP 協議時數據傳輸是非加密的,因此是有可能出現在網絡傳輸的過程中包內容被篡改的情況。這種情況就會導致客戶端接收與 OSS 存儲內容不一致。該問題可以通過修改為 HTTPS 協議規避該問題。

問題 4 :CDN 回源到老版本圖片處理域名
OSS 默認提供的是“oss-cn-.aliyuncs.com”的域名提供服務,但是針對於老版本的圖片處理仍然提供了“img-cn-.aliyuncs.com”供老版本的圖片處理樣式方式訪問(通過@!樣式名或者@樣式處理串)。但是相比於 OSS 本身的域名,圖片處理域名是不提供 HTTPS 協議的,因此在 CDN 上回源到 OSS 圖片處理域名是不可以設置回源到 443 端口的,同時是不可以開啟協議跟隨回源功能的,否則將會導致 HTTPS 協議訪問出現異常的情況。

問題 5 :CDN 加速後 OSS 的 CORS 配置未生效
當出現來自不同的域的 JavaScript 動態請求其他域的靜態資源時會觸發瀏覽器的跨域請求,而這時瀏覽器會在 HTTP 的 Request 頭中添加Origin 頭表示是由哪個域訪問該資源的。而 OSS 作為靜態資源存儲產品是允許設置 CORS 頭設置允許哪些域進行跨域訪問的。詳細的設置請參考OSS 的 CORS 設置
OSS 當接收到客戶端的 Request 頭中帶有 Origin 頭並且與 CORS 配置匹配的話那麼會在 Response 頭中 Access-Control-Allow-Origin等頭信息表示允許跨域訪問。但如果 Request 頭沒有 CORS 頭的話那麼 OSS 是不會返回 Access-Control-Allow-Origin 等頭信息。這種情況在使用 CDN 加速 OSS 的時候就會導致如果歷史有沒有跨域請求OSS 的返回信息緩存在 CDN 節點上,下次訪問觸發跨域時直接獲取緩存數據導致鑑權不通過的。
該問題最好的解決方案就是在 CDN 上配置 CORS 頭,這樣保證不管客戶端是否有觸發跨域請求都會在 Response 帶有 Access-Control-Allow-Origin 等頭信息的。避免由於歷史的未觸發 CORS 的緩存數據影響真正的跨域請求,具體的設置請參考CDN配置CORS頭

問題 6 :過濾參數導致回源請求缺失
OSS 的權限包括公共讀寫、公共讀和私有三種權限,對公共讀的Bucket 執行寫操作核對私有的 Bucket 執行讀和寫的操作時都是需要訪問的時候加上身份驗證的簽名參數的。這裡以讀為例,以 URL 的方式讀取 OSS 的資源時是需要加上 OSSAccessKeyId 、 Expires 和Signature 三個參數的 queryString 的參數才可以正常訪問的,如果沒有添加這些參數就會報“403 Access Denied”的錯誤。
而 CDN 上是提供了過濾參數的功能是指當 CDN 收到請求 URL 後去除掉 URL 中的 querystring 查看是否有緩存文件命中,如果沒有的話就會使用沒有 querystring 的 URL 回源拉取資源。例如:由於 CDN加速 OSS 的訪問URL是“http://wqtest.test.com/1.jpg? Expires=1511700494&OSSAccessKeyId=TMP.AQGmSnv_MDL_qdYESUo2KTjtyS5aqHdRVF8Cjko_zeyEC4rwnnOWyTVfoBAHMC4CFQDa1RE0F6h3Z1s0RV3OyZfdL1jmFgIVAM2ENr7Ae5c1LqDyi3LO2ba4seyk&Signature=NS8xhKGyyHEzzIK4CmqaxzCcfwo%3D”,其中 wqtest.test.com 是開啟了過濾參數的 CDN 加速域名。那麼CDN 節點在受到該請求後會將該 URL 改寫成“http://wqtest.test.com/1.jpg”,然後依次查看 CDN 的 L1 節點和L2 節點上是否有緩存數據,如果有的話就直接將該緩存數據反饋給客戶端,否則就會回源到 OSS 。而這時 OSS 如果是私有的話接收到該請求將無法正常訪問就會拋出 403 Access Denied 的錯誤。
這裡最直接的處理辦法就是關閉過濾參數功能,這樣回源的時候就會帶上完整的 querystring 。但是這樣設置同樣會帶來一個問題就是當queryString 中的參數發生更改後那麼 CDN 會認為是完全不同的 URL重新緩存,因此這種情況下可能會導致 CDN 緩存命中率下降。其他的解決方案建議參考後面的“問題 7 :私有 Bucket 回源和鑑權功能的設置”。

問題 7 :私有 Bucket 回源和鑑權功能的設置
在問題 6 中我們介紹了當 OSS 設置為私有時不可以開啟過濾參數並且當簽名 querystring 發生變化時還會影響 CDN 緩存命中率。該問題的解決方案就是 CDN 開啟私有 Bucket 回源。
該功能將使 CDN 的請求回源 OSS 的時候自動帶上簽名 querystring參數,而不需要客戶自己在請求 CDN 的時候設置。這樣即實現了 OSS 本身資源的安全防護而又不影響 CDN 的緩存命中率。
同時如果客戶需要對 CDN 的請求也要求鑑權的話可以在 CDN 上配置鑑權功能,同時鑑權參數發生更改是不影響緩存命中率的。

刷新問題。

CDN 加速 OSS 的場景提供了 OSS 源文件更新後提供自動刷新 CDN緩存的功能,該功能是在 OSS 控制檯的域名管理頁面中開啟,如圖 9所示。開啟該功能是需要該域名同時在 CDN 和 OSS 上綁定才可以正常使用,否則就很按照圖 8 中的第一條記錄無法開啟該功能。
image.png

圖 9. CDN 緩存自動刷新示意圖

Leave a Reply

Your email address will not be published. Required fields are marked *