Fastly 全球規模邊緣雲計算實踐

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"GIPHY 提供大量的 GIF 媒體內容。事實上,每天有超過 100 億條內容。除代表 GIF 實際下載的媒體請求外,我們還提供了公共 API 和 SDK 服務,讓開發者可以在他們的產品中使用,從而使他們的用戶能夠訪問我們龐大的庫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"和很多每天都有大量流量的科技公司一樣,我們面臨着可擴展性的挑戰。系統必須能夠處理大量的請求 (在每秒 10000 個請求之內),並且響應延遲很小。最糟糕的事莫過於等待加載,特別是 GIF!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這就是邊緣雲平臺(edge cloud platform)發揮作用的地方:邊緣雲平臺並不是讓我們的 AWS 服務器處理每個請求,而是儘可能多地緩存媒體內容和搜索結果 JSON 負載。這樣做是非常有效的,因爲媒體內容和 API 響應都不會頻繁改變。邊緣雲平臺服務器還將請求負載分配給不同的區域。我們使用 Fastly 驅動邊緣雲平臺,爲用戶提供了數十億條內容。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Fastly 解決方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Fastly 提供多種功能,使我們能夠大規模地交付內容。這些特性可以大致歸類爲:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"緩存分層"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"緩存管理"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"邊緣計算"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"緩存分層"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基本邊緣雲平臺的設置是將內容緩存在邊緣。這些服務器節點分佈在全球,向在其區域內發送請求的用戶提供緩存內容。如果邊緣節點沒有任何內容,則會向原始服務器(origin server)發送請求,以便檢索內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/54\/546c0b0777fa75e610a62c41490f5ee2.jpeg","alt":"image.png","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣的單層設置存在缺陷。每一個邊緣節點都根據其區域的請求維護自己的緩存。所以,一個新的內容片段可能不會在任何一個邊緣節點上被緩存,這可能會導致當每個邊緣節點都重複相同的內容請求時,到我們的原始服務器的流量會激增。由於病毒式內容的流行程度越來越高,這種行爲常會出現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Fastly 提供名爲 Origin Shield 的第二層緩存服務。現在,可以從 Origin Shield 層檢索緩存中沒有請求內容的邊緣節點,請求只需要到達我們的原始服務器。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/31\/312c48b1ab8975bf2fb628fdeecc3f2e.jpeg","alt":"image.png","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"緩存管理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"既然內容被緩存在邊緣和 Origin Shield,我們需要設法管理其緩存策略。並不是所有的內容都應該保持相同的緩存時間,或者說 TTL(Time to Live,生存時間)。例如,單個 GIF 的信息不會有太大的變化,所以它的 API 響應可以在一個相當長的一段時間內被緩存。而 "},{"type":"link","attrs":{"href":"https:\/\/developers.giphy.com\/docs\/api\/endpoint#trending","title":null,"type":null},"content":[{"type":"text","text":"Trending Endpoint"}]},{"type":"text","text":" 的 API 響應則返回當前趨勢 GIF 的持續更新列表,由於趨勢的性質,它需要在一個較短的 TTL 上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Fastly 是由 Varnish 驅動的,所以所有的配置都採用 Varnish 配置語言(VCL)代碼的形式執行。邊緣和 Origin Shield 都運行 VCL 代碼,因此我們能夠通過一些簡單的 VCL 代碼,基於 API 端點路徑設置各種緩存 TTL:"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# in vcl_fetch\nif (req.url ~ \"^\/v1\/gifs\/trending\") {\n # set 5 minute ttl for trending responses\n set beresp.ttl = 600s;\n return(deliver);\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"並不總是用 VCL 代碼來設置緩存 TTL。發送到 Origin 的 API 請求,可以在 Origin 的響應中對緩存控制指令進行編碼。僅需設置 VCL 代碼即可使其被重寫。在 Origin 中,我們可以通過在 API 響應中設置緩存控制頭,將這一決定傳遞給 Fastly 的 Origin Shield 和邊緣節點。尤其是 Surrogate-Control 頭,因爲這個頭將僅用於 Fastly 節點。所以我們可以更新上述 VCL,使 Surrogate-Control 優先於端點緩存策略,如下所示:"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# in vcl_fetch\nif (beresp.http.Surrogate-Control ~ \"max-age\" || beresp.http.Cache-Control ~ \"(s-maxage|max-age)\"\n) {\n # upstream set some cache control headers, so Fastly will use its cache TTL\n return(deliver);\n} else {\n # no cache headers, so use cache policies for endpoints\n if (req.url ~ \"^\/v1\/gifs\/trending\") {\n # set 10 minute ttl for trending responses\n set beresp.ttl = 600s;\n return(deliver);\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過這樣的設置,我們可以讓緩存內容通過動態 TTL 策略自動失效,從而滿足我們的需求,但是如果我們不希望等待緩存自然過期,也需要顯式地讓緩存失效。只需通過緩存鍵(URL)就可以讓緩存失效。對於媒體來說,這很有效,但是對 API 的響應有點複雜。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"例如,我們的 API 搜索端點可以爲不同的查詢返回相同的 GIF,但是如果我們希望使其失效,則無法知道每個可能生成 GIF 的 URL:"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# same GIF can appear in the response of all of these API calls\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY1__&q=haha\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY1__&q=hehe\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY2__&q=lol\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY3__&q=laugh"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於這種情況,我們利用了 Fastly 的代理鍵(Surrogate Key)!顧名思義,代理鍵能夠唯一地識別緩存的內容,與緩存鍵的方式基本相同。與緩存鍵不同,每個存儲結果可以有多個代理鍵,我們可以設置代理鍵。通過在每個 API 響應中顯示的 GIF ID,使我們可以確定包含特定 GIF 的多個緩存內容:"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# same GIF (gif_id_abc) can appear in the response of all of these API calls\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY1__&q=haha\n Assign Surrogate Key: gif_id_abc\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY1__&q=hehe\n Assign Surrogate Key: gif_id_abc\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY2__&q=lol\n Assign Surrogate Key: gif_id_abc\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY3__&q=laugh\n Assign Surrogate Key: gif_id_abc"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還可以爲同一內容添加多個代理鍵:"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"https:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY1__&q=haha\n Assign Surrogate Key: gif_id_abc gif_id_def key_KEY1 q_haha\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY1__&q=hehe\n Assign Surrogate Key: gif_id_abc gif_id_123 key_KEY1 q_hehe\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY2__q=lol\n Assign Surrogate Key: gif_id_abc, gif_id_321 gif_id_456 key_KEY2 q_lol\nhttps:\/\/api.giphy.com\/v1\/gifs\/search?api_key=__KEY3__&q=laugh\n Assign Surrogate Key: gif_id_abc key_KEY3 q_laugh"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代理鍵是一個強大的特性,可以讓我們選擇合適的緩存,非常精確而簡單地使其失效。通過這種設置,我們可以在下列情況使緩存失效:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使所有包含特定 GIF 的緩存 API 響應失效;"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使針對特定 API 鍵的所有緩存 API 響應無效;"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使查詢某些單詞的所有緩存 API 響應無效。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"在邊緣運行代碼"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"VCL 爲我們在邊緣雲平臺的配置方面提供了大量功能。我們之前展示了配置如何爲邊緣和 Origin Shield 節點設置各種緩存 TTL 策略,但是我們還可以使用 VCL 設置請求信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以用代碼來重寫傳入的請求 URL。如果我們需要修改我們的 API 端點,那麼這樣做會更方便,而不用麻煩我們的消費者來更新他們的調用。"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# in vcl_recv\nif (req.url ~ “^\/some-old-endpoint”) {\n # rewrite to the new endpoint\nset req.url = regsub(req.url, “\/some-old-endpoint”, “\/new-and-improved-endpoint”);\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還可以選擇一定比例的傳入請求來測試實驗特性。利用 Fastly 的"},{"type":"link","attrs":{"href":"https:\/\/developer.fastly.com\/reference\/vcl\/functions\/randomness\/","title":null,"type":null},"content":[{"type":"text","text":"隨機性庫"}]},{"type":"text","text":",我們可以爲某些請求中添加一個特殊的頭,以實現原始服務器上的新行爲。"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# in vcl_recv\nset req.http.new_feature = 0\nif (randombool(1,10000)) {\n # .01% of the traffic gets to see the new feature\nset req.http.new_feature = 1;\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它結合了 Fastly 的邊緣字典,使得我們可以用最少的代碼建立不同的行爲。"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# API keys that will have a percentage of their request use the new feature\ntable new_feature_access {\n “__API_KEY1__”: “1”,\n “__API_KEY2__”: “5”,\n “__API_KEY3__”: “1000”,\n}\nsub vcl_recv {\nset req.http.new_feature = 0\n# check if request has an api key that is setup to have a percentage of its requests use the new feature\nif (randombool(std.atoi(table.lookup(new_feature_access, subfield(req.url.qs, \"api_key\", \"&\"), \"0\"))\n,10000)) {\nset req.http.new_feature = 1;\n}\nreturn(lookup);\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這只是觸及了 VCL 實現的功能的皮毛。如果你想知道還有什麼可以做的,可以在"},{"type":"link","attrs":{"href":"https:\/\/developer.fastly.com\/","title":null,"type":null},"content":[{"type":"text","text":"這裏"}]},{"type":"text","text":"找到 Fastly 的文檔!"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"技巧提示"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們使用 Fastly 的很多特性來爲世界提供 GIF 動畫內容。但是,當你可以使用如此多的特性時,配置邊緣雲平臺可能會變得非常複雜,因此,下面是一些我們推薦的技巧提示可以幫助你完成這個任務。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"在邊緣和 Origin Shield 中執行 VCL"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於兩層緩存設置,有一個需要記住的關鍵問題是,將在邊緣和 Origin Shield 執行相同的 VCL 代碼。這可能導致 VCL 代碼在請求\/響應的狀態信息更改時出現意外的結果。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"舉例來說,我們之前的 VCL 代碼將根據由上游緩存控制頭或 VCL 代碼本身指定的緩存 TTL,爲 Origin Shield 和邊緣節點設置緩存 TTL:"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# in vcl_fetch\nif (beresp.http.Surrogate-Control ~ \"max-age\" || beresp.http.Cache-Control ~ \"(s-maxage|max-age)\"\n) {\n # upstream set some cache control headers, so Fastly will use its cache TTL\n return(deliver);\n} else {\n # no cache headers, so use cache policies for endpoints\n if (req.url ~ \"^\/v1\/gifs\/trending\") {\n # set 10 minute ttl for trending responses\n set beresp.ttl = 600s;\n return(deliver);\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假設對於 "},{"type":"link","attrs":{"href":"https:\/\/developers.giphy.com\/docs\/api\/endpoint#trending","title":null,"type":null},"content":[{"type":"text","text":"Trending Endpoint"}]},{"type":"text","text":",我們也設置了響應的 Cache-Control 頭,這樣我們就可以指示調用方將內容緩存到另一段的時間。這樣做只需按以下步驟:"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# in vcl_fetch\nif (beresp.http.Surrogate-Control ~ \"max-age\" || beresp.http.Cache-Control ~ \"(s-maxage|max-age)\"\n) {\n # upstream set some cache control headers, so Fastly will use its cache TTL\n return(deliver);\n} else {\n # no cache headers, so use cache policies for endpoints\n if (req.url ~ \"^\/v1\/gifs\/trending\") {\n # set 10 minute ttl for trending responses\n set beresp.ttl = 600s;\n # set 30 second ttl for callers\n set beresp.http.cache-control = \"max-age=30\";\n return(deliver);\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Origin Shield 會執行這段 VCL 代碼,向響應的頭添加 Cache-Control 頭,並將其返回到邊緣。但是,在邊緣處,它將看到響應中設置了 Cache-Control,並會執行 if 語句。這將導致邊緣節點使用 30 秒的緩存 TTL,而不是預期的 10 分鐘!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"幸運的是,Fastly 提供了一種區分邊緣和 Origin Shield 的方法,它在請求中設置了頭("},{"type":"codeinline","content":[{"type":"text","text":"Fastly-FF"}]},{"type":"text","text":"):"}]},{"type":"codeblock","attrs":{"lang":"c"},"content":[{"type":"text","text":"# in vcl_fetch\nif (req.url ~ \"^\/v1\/gifs\/trending\") {\n # set 10 minute ttl for trending responses\n set beresp.ttl = 600s;\n return(deliver);\n}\n# in vcl_deliver\nif (!req.http.Fastly-FF) {\n # set 30 second ttl for callers\n set resp.http.cache-control = \"max-age=30\";\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過這個添加,Cache-Control 頭將僅在邊緣節點上設置,我們的緩存策略再次按預期運行!"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"調試和測試"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們剛纔提到的陷阱可能難以發現和調試。VCL 代碼只是運行在服務器上,並向你顯示響應和響應頭信息。只需將調試信息添加到自定義頭信息中,並在響應中查看它們,但是這很快就會變得不方便了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所幸的是,"},{"type":"link","attrs":{"href":"https:\/\/developer.fastly.com\/learning\/vcl\/fiddle\/","title":null,"type":null},"content":[{"type":"text","text":"Fastly Fiddle 工具"}]},{"type":"text","text":"在執行 VCL 代碼時能得到更好的信息。在這個工具中,我們可以模擬各種 VCL 代碼部分,並瞭解 Fastly 的邊緣以及 Origin Shield 服務器將如何處理 VCL 代碼的信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以下是上述示例的 "},{"type":"link","attrs":{"href":"https:\/\/fiddle.fastlydemo.net\/fiddle\/4001c4c6","title":null,"type":null},"content":[{"type":"text","text":"fiddle"}]},{"type":"text","text":",顯示雙重執行 VCL 將影響緩存 TTL。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們在左邊的適當部分設置了 VCL,然後執行它,查看 Fastly 將如何處理右邊的請求:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/85\/85722e28bb404b338782d4f402cdb7eb.jpeg","alt":"image.png","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上圖展示了在請求通過 edge 和 Origin Shield 節點時,關於它的生命週期的許多有用信息。實際環境中,VCL 代碼可能會非常複雜,而這個工具在這種情況下非常出色。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"作者簡介:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Ethan Lu,API 團隊技術領導。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"原文鏈接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/engineering.giphy.com\/how-giphy-uses-fastly-to-achieve-global-scale\/","title":null,"type":null},"content":[{"type":"text","text":"https:\/\/engineering.giphy.com\/how-giphy-uses-fastly-to-achieve-global-scale\/"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章