前言
原本我不太想写这片文章,因为从根本上来说,”自选IP”、”优选IP”、”优选域名”这些概念都不是官方说法,说好听点是”民间偏方”,说难听点是”邪道”(老界王神如实说),我在之前的文章中也有专门的篇幅纠正过这个说法(参见文章:家庭資料中心系列cloudflare教學(七) CF worker功能介紹及基於worker實作」乞丐版APO for WordPress」功能加速網站存取的實操、驗證及相關技術原理研究中关于优选IP部分的描述)。不过,时至今日,看到仍然不少的朋友因为不了解cloudflare CDN加速网站访问的原理,没有按照cloudflare官方的优化理念对网站访问进行优化,反而是把精力花在研究这些”邪道”上面(君不见超级赛亚人3最后连正常聚气都做不到了?),想想还是写了这片文章,至少让大家能够把力气真正用在刀刃上。
註1:這篇文章純屬技術上的闡述,沒有針對誰的意思,如果不小心對誰有言語上的冒犯請見諒,當然如果大家有不同的技術意見也歡迎在文章評論區或者留言板進行討論。
註2:CDN加速網站訪問雖然只是一句話,但在真正的實現中其實包含了很多技術點,更別說cloudflare的CDN,為了能講清楚,我只能從頭開始說了。
背景知識
很久很久以前
在CDN技術大行其道之前,傳統的建站方式還是以自建機房使用伺服器搭建web網站為主流。當時的自建機房項目,找寬頻業者申請一個線路(最早運營商還只是提供2兆的E1接口,用戶需要自己買一台cisco 2600路由器用E1模組連接運營商的E1接口,cisco 2600自帶的10兆電口當做運營商線路最終提供的RJ45 接口,擱在現在,就相當於買個cisco路由器當光電轉換器用來連接運營商提供的光纖,想想真是奢華啊,不過那個時候這個配置可是標配),然後買個防火牆,用一個電口當做wan 口來連接ciaco 2600 路由器的10 兆電口,一個電口連內網三層交換機做lan口,然後從運營商送的一堆IPv4公網位址中選一個出來做內網到外網的NAT位址,再選一個在防火牆上將該公網IP的tcp 80埠直接指向內網伺服器IP的80埠,頂多再設定一個tcp 21埠的映射,一個機房建設工程基本上就算完事了。
那時候,由於訪客還不多(家庭寬頻都還沒普及,貌似還是isdn?),網站發布使用一個IPv4公網IP+2兆的寬頻已經綽綽有餘了,當時也還沒有什麼訪問體驗的概念,網站頁面能打開就行,5秒還是8秒感覺也無所謂。
後來,隨著國內家庭寬頻的快速發展以及出現多家寬頻業者並立的格局,引發了新的問題:電信寬頻用戶訪問網通(現在是聯通)地址的網站速度奇慢無比,而對於網通寬頻用戶造訪電信地址的網站也是如此,這是因為業者之間的流量會進行網間結算,費用還很貴,各個業者都不約而同的對出網流量進行限制。
所以,當時各大ICP(網易、新浪等)只能在電信、網通的網路內分別搭建資料中心,來確保不同業者使用者在不產生出網流量的情況下得到好的存取體驗(小業者用戶就苦了,例如鐵通)。
網易、新浪對外只有一個域名,如何能讓電信和網通用戶在訪問同一個域名時,能夠準確的訪問到自家運營商網內網易、新浪對應的數據中心呢?這裡就引出了第一個重要技術點:全域伺服器負載平衡。
DNS工作原理
在讲”全局服务器负载均衡”之前需要先复习一下基础知识-“DNS的工作原理”。
我們正常上網時,只需要打開瀏覽器輸入想要造訪的網域並回車,之後就可以隨意瀏覽網頁了。只是這個大家習以為常的過程其實是靠一系列DNS伺服器合作的結果,如下圖:
從上圖可以看到:當使用者在瀏覽器中輸入目標網域(以www.tangwudi.com
為例)並回車之後,使用者作業系統會先向Local DNS務器(也就是平常大家直接在電腦或路由器上設定的dns位址,例如223.5.5.5、119.29.29.29、8.8.8.8等等)服以遞歸的方式詢問想要存取網域的IP位址,隨後Local DNS伺服器會以迭代的方式從更多上級DNS伺服器查詢到目標網域的IP位址,並把結果傳回給用戶,在這期間,上級DNS (根網域伺服器、頂級網域名稱伺服器、權威網域伺服器)從頭到尾看到的都是Local DNS伺服器在問東問西,而不是使用者的真實IP(這點mark一下,很重要)。
註1:其實第一步就查詢Local DNS是不準確的,如果真要較真,第一步、應該是瀏覽器查詢自身的dns緩存,如果有則直接使用,如果沒有則繼續往下走;第二步驟、呼叫作業系統的功能,此時應該是先看作業系統本地的dns快取裡有沒有,有則直接使用,沒有就查本地的host文件,如果還沒有,才會向Local DNS發起請求。
註2:關於DNS的遞迴查詢和迭代查詢,有興趣的朋友可以自己研究下,這個不是本文的重點,只是隨便提一嘴。
全域伺服器負載平衡(Global Server Load Balance)
繼續前面的話題,全域伺服器負載平衡(下文簡稱全域負載平衡,也叫智慧DNS)為什麼能實現讓電信用戶存取電信網內對應的資料中心、讓網通用戶存取網通網內對應的資料中心呢?
原理其實很簡單,根據上一節DNS原理部分講述的內容,上級DNS伺服器都能夠看到Local DNS發來的請求,所以只要負責網易、新浪域名解析的權威DNS伺服器能夠額外判斷一下Local DNS的來源IP位址歸屬:如果Local DNS是電信位址,那麼就近返回電信網內資料中心的IP;同樣的,如果Local DNS是網通位址,就近返回網通內部網路資料中心的IP就行了。
不过,权威DNS服务器的主要职责毕竟是DNS解析,并且本来负担就大,还要额外多做事也不太合适,所以把这个额外的判断工作交给了专门的设备”全局负载均衡”来完成:本来Local DNS的查询到了权威DNS服务器就该得到结果了,现在权威服务器又多说了一句”我虽然是老大,但是这事我已经交给小弟全权处理了,这是它的地址,你去找它吧”,然后Local DNS又多了一轮查询(如下图红框所示):
注1:全局负载均衡名字很高大上,其实本质上也就是一台正常的DNS服务器,只是因为其内置了全国(或者全球)的IP地址库,所以能够基于Local DNS的源IP判断其归属。比如基于bind9自建DNS服务器,只需创建包含不同解析结果的区域文件,然后使用view语句将不同的dns查询的来源IP地址段关联到不同区域文件即可实现最简单的”智能”解析。
註2:專業的全域負載平衡(例如F5的GTM)具備更多的商用功能,如果部署在多個資料中心並且能夠互相配合,同時結合資料中心多出口鏈路負載平衡以及應用的多活部署,這些組合起來就可以實現(同城/異地)災備資料中心、兩地三中心、多活資料中心方案。
CDN的實現原理
“多重影分身”:让源站内容无处不在
傳統的自建網站方式一個最大的問題在於來源站伺服器位置是唯一的。例如公網IP是4.4.4.4,那麼全國(乃至全球)的用戶訪問都只能老實根據公網路由去這個地址獲取網站內容,如果是網絡通暢還好說,如果網絡不通暢(類似以前電信/網通互相限制,或國內用戶想訪問國外),那難度簡直不下於西天取經:需要經歷九九八十一難。
那么,能不能在源站服务器位置唯一的情况下,让网站的内容遍布天下,让所有访问者都能即时取得呢?当然可以,就是对源站服务器使用”多重影分身术”:CDN。
虽然只有一个源站,但是通过CDN,理论上可以将源站内容镜像到全国各个区域的缓存服务器上(以nginx图标来代表缓存服务器),可以让源站”无所不在”,同时也能将源站的性能压力卸载到各个缓存服务器上(理论上传统对源站的众多性能要求,比如并发连接数、新建连接数等都不那么重要了):
但是在現實的具體實作中,並沒有採取將來源站內容全部鏡像到快取伺服器,這是因為直接鏡像來源站內容到快取伺服器這種方式會有以下問題:
1. 儲存效率與成本問題
• 海量數據難以鏡像:來源站上的內容可能非常龐大,包含大量的文件、影片、圖片等。如果將所有來源站內容完全鏡像到所有快取伺服器上,需要非常巨大的儲存空間。這會大幅增加CDN營運商的硬體成本,特別是全球分佈的多個資料中心都要儲存這些資料。
• 按需快取更有效率:透過按需快取的策略,CDN伺服器只儲存使用者實際請求過的內容,減少不必要的儲存消耗,提高了儲存效率,並降低了成本。
2. 內容動態性和時效性
• 動態內容的變化:某些內容是動態產生的或頻繁更新的,例如使用者個人化頁面或即時新聞。這類內容無法被長期緩存,需要根據用戶的請求即時回源獲取最新版本,因此無法透過簡單的鏡像全部緩存到CDN節點。
• 內容時效性:某些內容可能有時效限制,例如短期活動頁面、折扣資訊或時事新聞。將這些內容完全鏡像可能導致過期內容仍被緩存,帶來使用者體驗問題和資料同步困難。
3. 網路頻寬與傳輸成本
• 全量鏡像增加頻寬需求:如果將來源站所有內容傳輸到快取伺服器,特別是對於一些大型網站或串流平台,會產生巨大的頻寬需求。這不僅增加了源站的負載,還會顯著提高傳輸成本,尤其是跨區域的資料傳輸費用。
• 避免不必要的流量:按需回源可以減少不必要的流量傳輸,只在使用者實際需要內容時才從來源站拉取,這樣可以優化網路資源的使用,避免浪費頻寬。
4. 資料更新與同步的複雜性
• 源站內容更新頻繁:如果來源站內容頻繁更新,CDN需要持續監控和同步所有快取的內容,這增加了複雜性和管理成本。按需回源的模式則可以減少這種複雜性,只需要在內容被要求時確保其最新版本。
• 一致性管理問題:全量鏡像到快取伺服器意味著每次來源站有更新,所有快取伺服器都需要同步更新,否則會導致內容不一致。而透過按需回源,CDN節點可以根據快取策略自動檢查內容是否需要更新,有效減少一致性管理的壓力。
5. 不同區域使用者需求差異
• 內容請求分佈不均衡:不同區域的使用者對來源站內容的需求是不同的,例如某些內容可能只在某個特定區域受歡迎。全量鏡像所有內容到全球的CDN節點會導致許多不必要的資料存儲,特別是針對那些幾乎沒有使用者存取的內容。而按需回源可以更聰明地根據不同區域的需求來快取相關內容,優化儲存資源的使用。
因此,最终采用的办法是缓存服务器在需要时对源站进行”回源”(当CDN节点没有缓存到用户请求的内容时,需要将请求转发回到源站服务器来获取该内容)的方式,也就是吃自助餐提倡的”按需取餐”。
注:缓存服务器的”回源速度”是一个非常重要的考量因素,只不过,通常国内各个CDN供应商和国内云主机供应商之间网络都有优化(有些就是一家),回源速度再慢也慢不到哪里去,所以这里不多讲。
傳統基於全域負載平衡的DNS調度
CDN虽然能用分布式的缓存服务器让源站内容”无所不在”,但是如何让用户能找到离自己最近的缓存服务器却是个值得考究的问题,最简单的实现就是全局负载均衡+各地分布的缓存服务器。
以國內用戶造訪我的部落格網址www.tangwudi.com
為例,假設我在全國多個區域都部署了nginx伺服器來做快取伺服器,當用戶請求訪問www.tangwudi.com
的時候,最後收到dns查詢請求的全域負載平衡設備會根據使用者使用的Local DNS位址作為參考傳回一個它認為最近的快取伺服器位址,如下圖:
所以使用了全域負載平衡進行了DNS調度之後,每個區域的使用者都會感覺自己存取速度大大提升(本地存取當然速度快~)。
註1:理論上如果使用運營商預設提供的DNS伺服器位址,例如重慶電信的用戶使用61.128.128.68,成都電信的用戶使用61.139.2.69,那麼全域負載平衡能夠準確判斷出發起DNS請求的是哪個運營商的用戶,回傳的就近IP位址也會是最準確的。但大家可能因為各種原因會修改Local DNS的位址(例如想使用阿里的doh,就會把DNS伺服器位址改為阿里的DNS位址:223.5.5.5),這種情況下,全域負載平衡依靠判斷Local DNS伺服器ip而回傳的就近位址也未必就是真的最近,只不過都在國內,慢點也察覺不到而已。
註2:其實也有DNS請求中能攜帶用戶真實IP的方式,這樣全域負載平衡設備就能得到用戶真實的源IP位址,從而返回最有效的就近訪問IP,這種技術就是EDNS。不過這個功能需要dns客戶端、Local DNS以及最終的權威DNS伺服器皆支援(中途各級DNS都支援最好),所以實現難度比較大。
基於DNS調度方式實現CDN的限制
在上一節中,我使用最簡單的基於全域負載平衡的實現方式來講述CDN的工作原理,嚴格意義上來說,雖然沒有錯,但是卻有局限的:這種方式通常只適合特定的、局部化的需求場合,例如企業自用或只針對特定區域(例如國內)提供服務,如果要做大做強擴展全球,這種方式就會產生很多問題:
1. 無法實現全球的流量分配
• 地理位置影響存取速度:CDN的一個重要功能是根據用戶的地理位置將請求路由到離用戶最近的伺服器節點,單一區域還好,如果服務範圍擴展到全球仍舊依賴DNS或其他方式來決定流量路由,可能導致路由不準確、反應速度變慢。
2. 更複雜的流量管理
• DNS負載平衡的局限性:CDN通常需要依賴DNS負載平衡來實現流量分配。雖然DNS負載平衡可以根據Local DNS位址(甚至EDNS實現的用戶IP位址)進行路由選擇,但它的準確度和彈性都不夠好(更別說大家還喜歡改Local DNS位址),且DNS記錄更新較慢,無法即時應對網路變化。
• 故障切換更複雜:如果某個節點出現問題,使用DNS路由的CDN可能需要一定的時間才能更新DNS記錄,將流量重新導向到健康的節點。
3. 高延遲和不一致的網路效能
• 跨境流量延遲增加:使用者的請求可能會被路由到遠離他們的CDN節點,特別是當某些區域的DNS解析不夠精確時。這會導致跨境網路傳輸時間增加,影響使用者的體驗。
• 不一致的性能:不同使用者可能會因為網路路徑的差異而體驗到不同的存取速度。
4. 更高的網路複雜性和營運成本
• 需要複雜的地理DNS設置:為了實現全球或區域內的流量優化,CDN提供者需要投入更多的時間和資源來配置和維護地理DNS設置,以確保用戶請求能夠盡可能被路由到合適的節點。這不僅增加了營運成本,也使得系統的複雜性更高。
• 區域性壅塞問題:某些區域節點可能會承受更多的流量,導致區域性壅塞問題更加明顯。
5. DDoS防護效果較差
• 難以分散攻擊流量:DDoS攻擊可能集中指向一個特定的IP位址或節點,導致這個節點更容易被擊垮,整個服務受到影響。
• 更難實現全球防護:CDN難以透過多個節點分散和吸收攻擊流量,影響整體的安全性和穩定性。
6. 擴展性受限
• 難以靈活擴展全球節點:CDN可能需要單獨配置每個節點的IP位址,擴展難度較大,操作更複雜。
為了在全球部署CDN,就會遇到上述問題,而解決問題的關鍵就是Anycast IP技術。
Anycast(任播) IP技術
什麼是Anycast IP技術?
Anycast IP 是一種網路路由技術,其核心思想是將同一個IP位址分配給多個不同位置的伺服器節點,也就是說,多個伺服器共享一個IP位址。當使用者向這個IP位址發出請求時,網路會自動將請求路由到距離使用者最近的或最優的那個伺服器節點。
以肯德基外卖电话”400-880-3823″为例,当你拨打这个电话订餐时时,不论你在哪里,电话会自动连接到离你最近的那家KFC快餐店,这家快餐店会根据你的地址提供服务,整个过程对你来说是无缝的,你不需要手动选择哪家店,但是却享受了最近那家店的服务。
回到之前那張圖,如果全國部署了Anycast IP技術,並將www.tangwudi.com
網域的解析IP綁定到10.10.10.10這個任播IP上,那麼此時全域負載平衡完全可以偷懶,收到任何對www.tangwudi.com
網域的查詢都回應10.10.10.10(當然,一般不會這麼懶,還有要根據客戶區域回應不同的任播IP),而每個用戶使用這個IP作為目標IP進行訪問,仍舊可以訪問到離自己最近的快取:
CDN使用了Anycast IP 技術後,上一節提到的6個問題都解決了:
1. 全球或區域內的流量優化
• 快速回應:透過Anycast IP 技術,使用者的請求會自動路由到最近的CDN 節點。這顯著提升了用戶訪問的速度,尤其是在跨境訪問或全球用戶分佈較廣的情況下,減少了延遲。
• 智慧流量分配:Anycast使得相同IP可以在全球多個節點共享,因此無論用戶在哪裡,他們的請求都會被智慧分配到最優的伺服器,從而優化效能。
2. 簡化流量管理
• 即時路由最佳化:Anycast IP 會自動選擇最佳路徑,無需像傳統DNS負載平衡那樣頻繁更新或手動管理。這減少了流量管理的複雜性,並提高了網路的靈活性。
• 快速故障切換:Anycast可以在某個節點發生故障時,快速將流量切換到其他健康的節點,確保服務的連續性,而不必依賴較慢的DNS更新。
3. 更低延遲和一致的網路效能
• 地理位置優勢:Anycast IP 能夠根據用戶的實體位置,確保他們連接到最接近的節點,這意味著網路延遲降低,並為全球用戶提供更一致的效能。
• 消除跨境存取延遲:對於跨境或跨區域的流量,Anycast可以透過最佳路徑路由請求,減少了資料傳輸中的網路延遲問題。
4. 簡化的網路管理與成本控制
• 自動化流量調度:Anycast簡化了地理DNS設置,自動將用戶流量路由到最優節點,減少了手動配置的複雜性和管理成本。
• 有效分配流量:透過均衡流量,避免了某個節點過載,提升了整體網路的效率和效能,降低了額外的維護成本。
5. 增強的DDoS防護
• 分散攻擊流量:當DDoS攻擊發生時,Anycast技術能夠將攻擊流量分散到多個節點,減少單一節點承受的壓力,從而有效減輕攻擊的影響,並提升網路的安全性。
• 全球防護能力:Anycast使得攻擊流量可以在全球範圍內被吸收和分散,不再局限於某個區域或節點,這提升了整體網路的防護效果。
6. 靈活擴展性
• 簡化全球節點擴展:透過Anycast IP,CDN服務商可以輕鬆地在全球擴展新節點,而無需為每個節點配置不同的IP位址。這種擴展方式更靈活、更快速,幫助CDN服務商應對不斷增長的流量需求。
• 平衡網路負載:Anycast在全球範圍內分配流量時,使得流量更加均衡,減少了單一節點過載的風險,提升了服務的穩定性和可靠性。
使用Anycast IP 技術後,CDN 的優點在於更快的訪問速度(比慢悠悠來回往返的DNS查詢強)、更靈活的流量管理、更一致的網絡性能、更強的DDoS防護能力以及更靈活的擴展性。這些優點使得CDN能夠更好地為全球或大規模區域的用戶提供優質的服務,並確保網路的穩定和安全,只不過,相對於傳統的基於DNS調度的方式,Anycast IP的部署難度要高太多(涉及到骨幹網優化),所以並不適合小規模的CDN供應商或企業自建CDN的場景。
註:Anycast IP 說它是IP 位址,也的確是IP 位址,但是卻又不是我們平時隨處可見的普通的IP 位址(單播IP),它其實更像外表披著IP位址的一扇出口不確定的門(就像哆啦A夢的任意門,看著是個普普通通的門,推開後卻可能達到任何地方,所以即便某個時候推開門看到門外是A地,但是下一個時刻可能就變為了B地)。
使用cloudflare CDN加速網站訪問
基於Anycast IP的全球範圍CDN
cloudflare是全球提供整體解決方案的服務供應商(包括CDN、DDoS攻擊防護等服務),最關鍵的是,cloudflare也提供讓眾多個人站長受益的Free計畫(參見文章:家庭資料中心系列cloudflare教程(一) CF相關介紹及其對個人站長的效益),其中就包含了無限流量的CDN,之所以能如此豪橫,其中一個很關鍵的原因就是其遍布全球的部署Anycast IP的私有骨幹網和資料中心:
cloudflare國內現狀
可惜的是,牛逼如cloudflare也沒辦法在天朝自建骨幹網路。目前的折中方式是和京東雲合作,利用京東雲的網路延伸進國內,這會導致2個問題:
1、國內網路部分成本居高不下
京東可能讓cloudflare白嫖嗎? cloudflare在其他地方能省成本是因為自建網絡,現在不得不和國內雲供應商合作,成本高昂想都想得到,所以對於cloudflare來說,使用京東雲網絡的主要作用是滿足自身企業級大客戶(比如www.qualcomm.cn
,www.visa.cn
等等)在国内网站的使用,为此还出现了一个中国特有的服务”中国网络访问”,一般Free计划的用户肯定就只能流流口水了:
上图红框中的”中国网络访问”里直接访问京东云国内30个数据中心的意思有2个 :
- 1.網域解析的IP是京東雲的國內公網IP(全域負載平衡基於地域回傳的解析結果),所以國內用戶可以直接使用就近的京東雲國內IP來存取cloudflare企業用戶的網站,這個大家可以自行用正常網路去ping
www.qualcomm.cn
和www.ivsa.cn
就能知道。 - 2.如果cloudflare企業用戶國內網站的源站也是架設在國內,那麼當國內用戶在就近訪問的京東雲數據中心的緩存伺服器中找不到網站需要的內容時,該緩存伺服器可以直接從京東雲的這個資料中心進行回源。
2.對網路的掌控遠不如其自建的骨幹網
這也很正常,畢竟是藉用京東雲的網絡,肯定不可能像自家網絡一樣想就怎麼配就怎麼配,況且國內的網絡本來限制就大,導致很多cloudflare擅長的技術在國內不好使(比如Anycast ):
这也使得cloudflare只能根据京东云的网络情况因地制宜的打造有”中国特色”的服务,也因此导致了cloudflare的企业级用户的网站在国内解析地址也只是普通的国内公网地址(非Anycast IP)。
對使用Free計劃的個人站長的影響
上面这2个问题直接导致的后果就是:京东云国内的任何网络只会为购买了”中国网络访问”服务的cloudflare企业级用户服务,和订阅其他计划的用户没有任何关系,也就是说,除了那部分企业级用户,对于订阅包括Free计划(也包括其他付费计划)的用户来说,cloudflare在国内相当于没有网(本来也没有~)。
这其实对目标用户群不包含国内的Free计划用户(搭建的网站)是没任何影响的,毕竟世界范围到处都是cloudflare的数据中心,其他区域的访问者在访问Free计划用户搭建的网站时,只需使用DNS解析的Anycast IP可以直接被分配到最近的数据中心,如果要回源的话直接从这个最近的数据中心回源就是。虽然也使用不了很多高级功能(比如”Argo Smart Routing”),但是嘛,底子在那里,慢也慢不了太多(因为真实物理位置近)。
只是,對於目標用戶群包含國內的Free計劃的個人站長們(包括我)就慘了,因為國內沒有網,而按照cloudflare對網絡資源的管理和優化策略,來自國內訪問者的訪問請求通常會被cloudflare的Anycast IP引流到美國西部的資料中心(San Joses資料中心機率較大),導致的直接結果就是國內用戶訪問慢。
為什麼國內Free用戶會被指派到San Jose資料中心?原因大概有以下幾點:
• 1.成本管理:Cloudflare 的Free 方案是免費的,企業通常會把更多優質的資源(例如亞洲的高品質資料中心)優先分配給付費用戶。美國西部的資料中心相對較為廉價(主要原因),且離中國大陸較近(地理位置近、海底光纜較短、延遲較小),因此成為Free 用戶的常用分配地。
• 2.區域網路限制:中國大陸對國外的網路服務有一定的限制和監管要求,Cloudflare 在中國大陸的流量需要與當地的營運商和資料中心合作,這也可能導致非付費用戶的流量被優先轉發到美國資料中心,尤其是西部資料中心,因為其距離相對較近。
• 3.網路負載平衡:Cloudflare 的全球網路分散式流量調度系統會根據網路的負載情況選擇合適的資料中心來處理流量。在流量高峰時段或特定區域負載較大時,Free 計畫的使用者可能會被指派到更遠的伺服器(如美國西部),以減輕亞洲資料中心的負擔。
• 4.合作夥伴關係:Cloudflare目前在中國與京東雲的合作(之前是百度雲),雖然這種合作為中國大陸用戶提供了較好的訪問速度,但這種合作關係優先服務購買了中國網絡存取服務的企業級用戶,導致Free 用戶的流量繞道國外節點。
國內用戶造訪網站慢原因深入分析
上一節我最後提到國內用戶在訪問cloudflare Free計劃(的個人站長)搭建的網站會慢,是因為被分配到了美國西部的數據中心,大家可能會認為是理所當然:因為遠。雖然事實也的確是因為如此,但是也有必要將具體慢的原因進一步拆分成多個環節來研究,這樣才能便於後面進行有目的優化:
來看看國內用戶的存取請求在San Jose資料中心沒有命中快取時,包括回源在內的4步完整的流程:
如果以上述场景简单的估算时间,可以看到如果需要回源,以单程时间为”1″计算,那么总体时间为”4″。
注1:访问用户被分配到哪个数据中心,之后如果有回源需求就会从哪个数据中心”发起”回源请求,这是铁律,对 cloudflare所有计划的订阅者都一样(包括企业版用户),区别只在于企业级用户从开始就有更多的可选项(比如更多、更近的数据中心),这点大家要注意。
註2:這個只是最簡單的模擬示意,現實中到底有多少個1、2步的往返和多少個3、4步的往返決定了打開頁面所花費的總體時間。
常規優化思路
所谓常规优化思路,就是针对上节内容中的4步访问流程进行优化的思路:使用缓存规则或者页面规则的方式使第3、4步发生的次数尽量少,最好是没有,简单来说就是”廣積糧,緩稱王多缓存、少回源”。
靜態站點
這類站點最佳化目標是:全站快取不回源(所謂不回源是指除了第一次回源,後續就不需要了)。也不用折騰太多,只要配置好cloudflare的快取規則,把js、css、html、png等需要的內容全部快取即可,之後的存取速度慢不到哪裡去(雖然測試速度肯定不如國內的100ms以下,但是實際體驗差不了太多),而且還不用擔心DDoS攻擊。
大家可以使用我在cloudflare pages上部署的hexo測試網站來體驗(只有預設首頁,將會就一下):https://hexo.tangwudi.com。
動態站點
这类站点优化目标是:尽量多缓存、少回源。不过动态站点和静态站点不同,有些内容是不能被缓存的,以wordpress为例,特定URI( “/wp-admin”、”/wp-login”、”/wp-comment”等开头的内容)以及包含特定cookie字段(“wp-“、”logged_in”、”wordpress”、”comment_
“、”woocommerce_
“)的请求均不能缓存,所以需要将这部分内容进行排除,而除了这些内容以外的内容都要进行缓存,需要按优先级从上到下的方式分层配置缓存规则的策略(详细配置方式参见文章:家庭資料中心系列cloudflare教程(六) CF Cache Rules(快取規則)功能介紹及詳細設定教程)。
來一張效果對比,我的測試wordpress站點,在不使用任何快取規則,直接進行訪問的時候(也就是完整走完第1、2、3、4步),從發出請求到開始從伺服器(cloudflare資料中心)開始接收資料的時間(TTFB)為2.74秒:
而使用快取規則將可以快取的內容都快取之後,TTFB時間變成為了1.14秒:
講道理已經很可以了。
注1:TTFB (Time To First Byte)是”从发出页面请求到接收到应答数据第一个字节的时间总和”,它包含了DNS解析时间、 TCP连接时间、发送HTTP请求时间和获得响应消息第一个字节的时间,简单来说就是我们在浏览器输入域名并回车一直到看见页面内容开始出现的的时间。TTFB非常重要,因为平时我们在打开网页时整个网页内容全部呈现花了多少时间对用户来说其实并不敏感,真正敏感的是输入域名并按下回车,之后多久页面内容开始加载。
註2:分層快取(Tiered Caching)功能非常重要,一定要開啟:
分层缓存功能对于回源有很好的优化效果,虽然国内访问用户回源必须从San Jose数据中心发起回源请求,但是开启分层缓存功能之后,却可以不直接从San Jose对源站进行回源,而是询问更靠近源站的顶层数据中心(比如位于亚洲的数据中心),如果顶层数据中心缓存里也没有,那么顶层数据中心会对源站发起回源请求,在得到源站回复之后,通过cloudflare内部网络将内容告知San Jose数据中心,这比直接从San Jose数据中心通过公共网络以路由方式进行回源更快,分层缓存是唯一一种能在 Cloudflare 的 Free 计划中需要回源时,间接实现”就近回源”效果的机制。
進階最佳化思路-worker(適合動態網站)
所谓进阶优化思路,就是不在局限于cloudflare传统的缓存功能(基于缓存规则和页面规则),而是采用worker功能,结合以前cloudflare在github上发过的一个js脚本”Edge Cache HTML”来更加灵活、智能的控制缓存功能(详细的配置参见文章:家庭資料中心系列cloudflare教學(七) CF worker功能介紹及基於worker實作」乞丐版APO for WordPress」功能加速網站存取的實操、驗證及相關技術原理研究)。
基於worker的最佳化方式和cloudflare傳統的快取功能比起來,更適合動態類型的網站:
- 細粒度的緩存控制
• Worker 最佳化 允許你針對特定請求類型、URL、使用者狀態等條件自訂快取策略。例如可以為未登入使用者快取更多的內容,而為登入使用者動態產生個人化的部分。這種靈活性是傳統快取規則無法做到的。
• 可以透過 自訂Cache Key 來決定哪些請求共享緩存,哪些請求獨立緩存,從而提升緩存命中率。 - 動態內容的部分緩存
• Worker 允許你快取動態頁面的靜態部分。例如,部落格文章的主體內容可以緩存,而登入使用者的個人化部分則從來源伺服器取得。這種 分片緩存(Partial Caching)能夠顯著減少伺服器負載,並提高用戶回應速度。 - 更高的緩存命中率
• 使用Workers 可以提高快取命中率,特別是在多用戶、複雜內容的網站中。透過細緻地控制快取策略,你可以最大化快取利用率,減少不必要的回源請求。 - 避免過度回源
• Worker 可以為某些資源設定不同的快取TTL,或實現 快取預取,在用戶請求時將舊緩存返回,同時非同步回源獲取新的內容,更新緩存,而不影響用戶體驗。
如果你的網站有很多動態內容和用戶交互,Worker 優化方式的確會帶來顯著性能提升,比如我的測試wordpress站點使用worker優化方式之後之後TTFB從傳統緩存方式的1.14秒進一步降低到332.52毫秒:
註1:依舊不要忘記開啟分層快取功能。
註2:而對於主要提供靜態內容的網站,傳統快取方式配置得當已經可以取得不錯的效果了,就不需要折騰了。
附加知識:Argo Smart Routing
什么是”Argo Smart Routing”?
這個功能和咱們這種白嫖為主的個人站長其實關係不大(付費而且如此之貴),但是因為其是堂堂正正網絡級別的優化,所以我覺得還是可以提一下的。
“Argo Smart Routing”中的”Argo”并没有一个公开的具体缩写解释,但它可以理解为一个象征性名称,代表优化网络路径的解决方案。名字 “Argo” 可能是借用了希腊神话中的”Argonauts”(阿尔戈英雄),他们是乘坐名为 “Argo”的船进行远航探险的英雄们。这对应了 Argo Smart Routing 的核心概念——通过最优的路径在全球网络中快速、智能地传递数据。
那么,什么是”Argo Smart Routing”呢?
Argo Smart Routing 是Cloudflare 提供的進階網路最佳化服務,透過以下方式優化網路流量:
• 智慧路由選擇:它透過Cloudflare 的私有網絡,基於即時網路狀況動態選擇最快、最可靠的路徑,而不是使用傳統的基於BGP 協定的路由選擇。
• 降低延遲和丟包:透過避開擁塞或效能不佳的網路路徑,Argo 能夠大幅降低延遲和提高內容交付的可靠性。
• 減少回源時間:尤其是在回源請求上,Argo 可以找到更快的路徑,從而減少請求回源的時間,提高網站的整體回應速度。
“Argo Smart Routing”的优化原理
還是以這張圖中的存取流程為例說明:
1. 智能路由选择(以国内用户—>San Jose 数据中心为例)
未使用Argo Smart Routing:
當國內用戶造訪時,他們的請求會被Cloudflare 的 Anycast IP 分配到 San Jose 資料中心。没有 Argo 时,用户的请求会按照默认的路由选择方式传输,可能经过以下路径:”国内 → 东南亚 → 太平洋海缆 → San Jose”,在某些情况下,这条路径可能较为拥堵或存在高延迟,影响用户的访问体验。
使用Argo Smart Routing:
Argo Smart Routing 可以动态检测到不同路径的网络状况,自动选择延迟更低、拥堵更少的路径。当Argo 检测到采用默认路由选择方式的路径出现延迟或拥堵时,它可以选择通过更快的路径,例如:”国内 → 香港 → 太平洋海缆 → San Jose”。这样,虽然国内用户仍然被分配到 San Jose 資料中心,但資料傳輸路徑得到了最佳化,減少了往返的時間。
2. 降低延迟和丢包(以San Jose 数据中心—>国内用户为例)
未使用Argo Smart Routing:
從San Jose 資料中心傳送資料回國內時,傳統路由選擇可能導致某些路徑擁塞或網路節點不穩定,進而引發丟包現象。例如:資料包經過一條擁擠的連結(如某條海纜線路),使用者可能會體驗到資料遺失、頁面載入緩慢,甚至需要多次重傳資料包,導致更高的延遲。
使用Argo Smart Routing:
“Argo Smart Routing”能够监测不同网络节点的健康状况,避免丢包率高或网络不稳定的链路。当Argo 检测到从 “San Jose → 国内” 某条路径存在丢包或高延迟,它会自动选择更可靠的路径,例如:”San Jose → 新加坡 → 国内”或者”San Jose → 香港 → 国内”。通过这种智能调整,用户接收到的数据包更加稳定,减少了丢包现象,最终提升了访问体验。
3. 減少回源時間(以San Jose 資料中心到中國境內的來源伺服器為例)
未使用Argo Smart Routing:
如果 San Jose数据中心没有缓存国内用户请求的内容,它会向位于国内的源站发起回源请求。在没有 Argo 时,这个回源请求会使用默认的互联网路由选择方式,可能通过以下路径:”San Jose → 东南亚 → 中国”或者 “San Jose → 太平洋海缆 → 中国”,这些路径可能较长,或者存在拥堵问题,导致回源时间增加。
使用Argo Smart Routing:
“Argo Smart Routing”可以基于实时网络状况选择从San Jose 数据中心到国内源站的最佳回源路径,当 Argo 检测到回源路径中的某个节点拥堵,它会绕开拥堵节点,选择一条更快的路径,如:”San Jose → 香港 → 北京”,或者 “San Jose → 新加坡 → 北京”,通过这种智能路由选择,回源路径得到了优化,数据从源服务器获取的时间大大减少。
可以看出來,雖然第1、2、3、4步依然存在,但從網路路由層面來說,卻靈活高效了許多。
注1:”Argo Smart Routing”可以算是万金油,除了对HTTP类型的应用,对其他任何类型的应用都有效,这就是”网络层优化”(非应用层优化)的牛逼之处。
註2:也需要和分層快取選項搭配使用。
cloudflare網站優化概念總結
從cloudflare提供的多種網站優化方式,加上預設的就近訪問策略,可以總結出cloudflare在優化網站訪問方面的3點優化理念:
- 1.就近原則
這個就近原則包含了存取用戶就近分配到cloudflare的資料中心(所以cloudflare需要在全球大量建立資料中心,少數國家除外),也包含資料中心對來源站的就近回源。
注:关于就近回源这一点,除了开启”分层缓存”选项外,采用tunnel方式回源在某些时候会比采用公网地址方式回源更有优势。这是因为tunnel 建立了一条从cloudflare 数据中心到源站的私密路径,这可能绕过采用公网地址方式回源时潜在的公共线路拥堵和延迟。然而,具体的性能提升会依赖于网络状况、源站的物理位置、以及 Cloudflare 数据中心的分布,如果源站与 Cloudflare 数据中心之间的公共网络连接良好,性能差异可能不大。
理论上,使用 Cloudflare Tunnel 的 Free 计划用户”有可能”被分配到任何cloudflare数据中心,包括亚洲的数据中心。Cloudflare 会根据网络条件、流量负载和其他因素,自动将tunnel 连接到其认为的最优数据中心。因此,如果你在亚洲或你的用户大部分在亚洲,cloudflare可能会将tunnel连接到离你最近的亚洲数据中心。
不過,對於Free 計劃用戶的tunnel,cloudflare 的全球網路資源分配可能受到一定限制,相較於付費計劃,Free 用戶的tunnel更有可能在流量高峰時段被分配到較遠的資料中心。例如,儘管你地理上更接近亞洲的某個資料中心,cloudflare 可能仍會因為負載或其他原因將你分配到一個較遠的地點,例如美國的某個資料中心。
因此,在 Free 计划下,”不能完全保证”Free计划用户的tunnel被连接到亚洲的数据中心,但它是有可能的(采用公网地址方式回源就没可能了~),具体取决于 cloudflare 的网络动态分配。
仍然以之前的例子为例:国内访问用户被分配到San Jose数据中心,如果San Jose数据中心的缓存没有对应内容,会根据分层缓存的要求,向顶层数据中心(亚洲数据中心)请求内容,当顶层数据中心发现自己的缓存里也没有时,如果是公网地址回源方式,会直接通过公用网络向源站发起回源;如果是tunnel回源方式,tunnel 会接管此过程,确保通过安全的专线直接回源,绕过公共互联网,从而增强安全性并减少网络不稳定性。因此,使用”tunnel方式回源”在一定程度上相当于使用”公网地址回源”+”Argo Smart Routing”,多多少少又能白嫖一点。
不過,tunnel方式也不是萬能的,目前看來,國內使用tunnel方式建站最穩的是使用國內的雲主機,對於家庭寬頻建站而言,就要看當地寬頻業者對於cloudflare的IP位址段的訪問策略了,有些地方做了劣化,可能會導致tunnel本身不穩定。當然,大部分寬頻應該都沒問題。
- 2、路由優化
就近之後,仍舊還有路要走,對於剩下必須走的路,盡最大能力優化,讓這條路更好走(Argo Smart Routing)。
- 3.盡可能多的利用緩存
就算再好走的路,走多了依舊會腳痛,所以最好還是能少走一點路,比如以前要起一大早去鎮上趕集買菜買肉,現在只需要在村口的農貿市場買就行。
按照cloudflare的想法,第1、2點都是它的事,第3點才是希望我們自己做的事。
民间偏方之”自选IP”、”优选IP”、”优选域名”
“自选IP”、”优选IP”、”优选域名”的由来:因为中国国内用户使用解析到的Anycast IP访问free计划用户建立的网站时,会被分配到美国西部的San Jose数据中心而导致访问慢,所以这些free计划的用户就想用自己国内的IP去解析一些cloudflare企业级客户的网站域名(比如www.visa.com),获得其Anycast IP之后,使用特定软件去测试这些Anycast IP(或者干脆使用cloudflare公布的IP地址段),找出不掉包而延迟最小的那个IP,最后手动把自己网站的解析ip改成这个IP。
其實,這個想法本身是好的,是想解決前面提到的1、2、3、4步中第1、2步的問題,也是想手動實現cloudflare網站優化理念的第1步:就近原則,只不過,這種方式雖然看起來可能在某些特定情況下能夠「暫時」改善國內用戶訪問速度,但從長遠來看並不是一種可靠或推薦的做法(我以前手動改了IP之後,隔三差五就要造訪部落格看看速度正常不正常,最後被搞煩了,還是改回了預設解析),有以下幾點理由:
1. Cloudflare Anycast 機製本身的設計
• Cloudflare 的Anycast IP 分配機制是全球性的,依賴 動態路由,由Cloudflare 根據網路條件和地理位置來自動最佳化和分配。雖然不同的Anycast IP 段會對應不同的資料中心,但它並不是簡單地根據IP 位址來決定路由,而是根據網路拓撲和延遲、擁塞等即時因素動態決定。
• 即使手動指定某個IP 位址,Cloudflare 仍可能根據全球網路條件動態調整流量路徑,因此你的手動修改未必總是能夠維持有效的最佳化結果。
2. 違背Cloudflare 的最佳實務與服務設計
• 手動更改Anycast IP 並不符合Cloudflare 的最佳實踐。 Cloudflare 的設計是讓使用者使用其提供的DNS 服務,並透過其網路智慧分配最佳的路徑和IP。
• 強制綁定到某個特定IP 可能會讓流量被Cloudflare 識別為異常流量,影響存取的穩定性或導致其他不可預期的問題,例如SSL 憑證驗證問題、效能波動等。
3. IP 位址的變化和不可控性
• Cloudflare 定期會在不同地區的IP 段進行調整,某些特定的Anycast IP 段可能會被重新分配或被重新路由到其他地區。如果你手動指定了某個IP,它可能在一段時間後被路由到不同的區域,導致訪問速度不穩定(以前面Anycast IP部分提到的哆啦A夢的任意門為例,你某個時候推開門看到門外是在成都,關上門後就認為門外一直是成都,但是實際上下一刻門外已經是重慶了,嗯,有點像薛定諤的貓,不實際打開門是不知道結果的)。
• 此外,Cloudflare 為不同的客戶提供不同等級的服務(例如Free 計劃和Enterprise 計劃),手動解析到企業客戶的IP 段可能導致潛在的訪問限製或不穩定性,因為這些IP 段的分配和資源調度是針對企業級客戶最佳化的,Free 方案可能無法享受相同的優先順序:
況且,真以為Free計畫用戶手動把解析IP指過去cloudflare不知道嗎?並且還沒有對這種情形做任何防備嗎?只需要在這些IP段上啟用SNI分級監測:屬於企業計畫用戶網站域名的存取請求才正確處理,其他全部按照預設策略對待,愛咋滴咋滴就行了。
4. CDN 的智慧優化功能被繞過
• Cloudflare 的免費方案雖然沒有企業級的所有最佳化,但它仍然利用了Cloudflare 的全域網路和快取系統。手動綁定某個IP 會繞過Cloudflare 的智慧最佳化和路由選擇,反而可能會讓你失去某些最佳化效果,尤其是當網路條件改變時。
5. 潛在的法律與服務條款問題
• 這種做法可能會違反Cloudflare 的服務條款,尤其是如果你使用了非官方的手段去取得特定企業客戶的IP 位址進行手動解析。 Cloudflare 可能會對這種行為採取措施,甚至終止服務。
其實上面這些理由都只是明面上的官方說法,我真正不推薦的理由是太折騰了,有那精力反复折騰IP的話,先問問自己:緩存策略到底配置好沒有,該緩存的內容是不是都緩存了? wordpress類型的動態網站有沒有嘗試使用worker優化的方式?配置完成之後是不是最大化的減少了回源請求?要知道最影響網站體驗的是TTFB時間太長以及頻繁回源,如果這些都配置好了,對於wordpress類型的動態個人博客網站來說,使用worker優化方式打開頁面可以達到TTFB幾百毫秒的體驗;或是使用傳統快取方式開啟頁面達到TTFB 1秒以上的體驗,這樣還不夠支撐個人部落格的正常存取嗎?
一句話:就算我們只是白嫖用戶,但也要有素質、有尊嚴的白嫖~。
總結
總算寫完了,好累,本來只是想表達最後一段話的意思,結果發現沒憑沒據的,要有說服力需要先講清楚cloudflare的優化理念;然後想著既然這樣,就先把cloudflare的優化理念講清楚就行了,結果發現要講清楚cloudflare的Anycast IP,需要對比傳統CDN的的工作原理;跟著想乾脆把傳統CDN的工作原理講清楚得了,結果又牽扯到全局負載均衡的智能DNS調度;最後寫全域負載平衡的智慧DNS調度時,發現要講清楚需要先說DNS的基本工作原理。 。 。 。然後不知不覺寫了這麼多,我真的是服氣了。 。 。
不過還是很有收穫的,以前有幾個概念似懂非懂,理解得併不透徹(包括如此重要的分層緩存功能,我之前雖然也講過並建議打開,卻也沒有太過於重視),甚至還有謬誤的地方(我之前認為Argo Smart Routing會改變發起回源請求的資料中心),不過為了寫這篇文章算是徹底搞清楚了(把簡單的思路具體化後變成文字真的很重要),因此這篇文章也可以作為我給之前寫的所有cloudflare相關的內容做的一個更高角度的概括與總結。
註:如果有朋友對本文中的許多概念有不了解的部分,可以從cloudflare學習地圖中查找,也許能夠找到答案。
ヾ(≧∇≦*)ゝ
这个表情的意思是?~