Subscribe to receive notifications of new posts:

Subscription confirmed. Thank you for subscribing!

我們的構建過程:Cloudflare Radar 2.0 背後的技術

Loading...

23 min read
How we built it: the technology behind Cloudflare Radar 2.0

Radar 2.0 是在 Radar 1.0 的基礎上建置,並於上個月在 Cloudflare 的 Birthday Week 期間作為完整的產品改進發布。我們希望使用者能夠更輕鬆地找到深入解析和瀏覽我們的資料,並總體上提供更好更快的使用者體驗。

我們正在構建一個 Supercloud。Cloudflare 的現有產品包括網路、安全性、存取控制、運算、儲存等方面的數百種功能。

本部落格將從工程角度解釋我們如何建置新 Radar。我們希望透過這種方式,證明任何人都可以在我們的堆疊之上建置涉及高要求和多個架構層的複雜網站,以及這個過程有多麼簡單。

希望這將激勵其他開發人員告別傳統的軟體架構,使用更高效的現代技術來建置他們的應用程式。

高等級架構

下圖是 Radar 2.0 架構的鳥瞰圖。如您所見,它分為三個主要層:

  • 核心層是我們存放資料湖、資料探索工具和後端 API 的地方。
  • Cloudflare 網路層是我們託管和執行 Radar 並為公用 API 提供服務的地方。
  • 用戶端層本質上是在瀏覽器中執行的其他所有內容。我們稱之為 Radar Web 應用程式。

如您所見,Cloudflare 產品隨處可見。它們提供了大規模託管和安全執行程式碼的基礎資源,還提供了端到端執行應用程式所需的其他建置組塊。

這些功能隨時可用,且緊密整合到我們的生態系統和工具中,只需按一下以及幾行程式碼,工程團隊就不必一直浪費時間做無用功,可以將時間用於必不可少的事情:他們的應用程式邏輯。

讓我們深入研究一下。

Cloudflare Pages

Radar 2.0 是使用我們以開發人員為中心的網站託管平台 Cloudflare Pages 部署的。在早期,您只能在 Pages 上託管靜態資產,這對許多使用案例都有幫助,包括與 HugoJekyllGatsby 等靜態網站產生器整合。儘管如此,當您的應用程式需要某種伺服器端或使用單一部署的進階邏輯時,它無法解決此類情況。

幸運的是,Pages 最近新增了對執行自訂 Worker 指令碼的支援。使用 Functions,您現在可以執行伺服器端程式碼並啟用通常使用單獨的 Worker 實作的任何類型的動態功能。

Cloudflare Pages Functions 還允許您使用 Durable ObjectsKVR2D1,就像普通 Worker 一樣。我們在開發人員文件中提供了有關如何執行此操作的出色文件以及更多內容。此外,該團隊還撰寫了一篇關於如何建置完整堆疊應用程式的部落格,詳細描述了所有步驟。

Radar 2.0 需要伺服器端功能的原因有兩個:

  • 轉譯 Radar 並執行 Remix 的伺服器端。
  • 實作和服務我們的前端 API。

Remix 和伺服器端轉譯

我們在 Radar 2.0 上將 Remix 與 Cloudflare Pages 結合使用。

Remix 遵循伺服器/用戶端模型,並在您無法控制使用者網路的前提下工作,因此 Web 應用程式必須減少它們透過網路傳送的 Javascript、CSS 和 JSON 的數量。為實現此目的,它們將一些邏輯移動到伺服器。

在這種情況下,用戶端瀏覽器將獲得預先呈現的 DOM 元件和預先擷取的 API 呼叫的結果,其中包含適量的 JSON、Javascript 和 CSS 程式碼,並根據 UI 需求進行了適當調整。此處為更詳細技術解釋

通常,Remix 需要一個 Node.js 伺服器來完成所有這些操作,但是:它也可以在 Cloudflare Workers 和 Pages 上執行。

下面是使用 Cloudflare Pages 讓 Remix 伺服器在 Workers 上執行的程式碼:

import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
import * as build from "@remix-run/dev/server-build";

const handleRequest = createPagesFunctionHandler({
  build: {
    ...build,
    publicPath: "/build/",
    assetsBuildDirectory: "public/build",
  },
  mode: process.env.NODE_ENV,
  getLoadContext: (context) => ({
    ...context.env,
    CF: (context.request as any).cf as IncomingRequestCfProperties | undefined,
  }),
});

const handler: ExportedHandler<Env> = {
  fetch: async (req, env, ctx) => {
    const r = new Request(req);
    return handleRequest({
      env,
      params: {},
      request: r,
      waitUntil: ctx.waitUntil,
      next: () => {
        throw new Error("next() called in Worker");
      },
      functionPath: "",
      data: undefined,
    });
  },
};

在 Remix 中,當使用者與應用程式互動並對其作出變更(例如,按一下功能表選項)時,路由會處理變更。Remix 路由可以具有載入程式動作預設匯出。載入程式處理用於擷取資料的 API 呼叫(GET 方法)。動作處理指向伺服器的提交(POST、PUT、PATCH、DELETE 方法)並傳回回應。預設匯出處理 React 中為該路由傳回的 UI 程式碼。沒有預設匯出的路由僅傳回資料。

由於 Remix 同時在伺服器和用戶端上執行,因此它可以變得智慧,並知道哪些內容可以在伺服器端預先擷取和運算,哪些內容必須通過網路連線,從而最佳化所有內容以提高效能和回應能力。

下面是中斷中心頁面的 Radar 路由範例,為了便於閱讀而進行了簡化。

import type { MetaFunction } from "@remix-run/cloudflare";
import { useLoaderData } from "@remix-run/react";
import { type LoaderArgs } from "@remix-run/server-runtime";

export async function loader(args: LoaderArgs) {
  const ssr = await initialFetch(SSR_CHARTS, args);
  return { ssr, };
}

export default function Outages() {
  const { ssr } = useLoaderData<typeof loader>();

  return (
    <Page
      filters={["timerange"]}
      title={
        <>
          <Svg use="icon-outages" />
          {t("nav.main.outage-center")}
        </>
      }
    >
      <Grid columns={[1, 1, 1, 1]}>
        <Card.Article colspan={[1, 1, 1, 1]} rowspan={[1, 1, 1, 1]}>
          <Card.Section>
            <Components.InternetOutagesChoropleth ssr={ssr} />
          </Card.Section>
          <Divider />
          <Card.Section>
            <Components.InternetOutagesTable ssr={ssr} />
          </Card.Section>
        </Card.Article>
      </Grid>
    </Page>
  );
}

以下是它產生的結果:

Remix 和 SSR 還可以幫助您改善 Lighthouse 評分和 SEO。它可以透過減少從伺服器到瀏覽器的擷取次數和資訊傳輸次數以及預先呈現 DOM,來顯著改善累積佈局偏移首次內容繪制最大内容繪製等指標。

另一個將應用程式移植到 Remix 的專案是 Cloudflare TV。以下是變更前後其指標的樣子。

Radar 的 Desktop Lighthouse 在效能、可存取性、最佳做法和 SEO 方面的分數現在接近 100%。

我們在 Radar 2.0 上廣泛使用的另一個 Cloudflare 產品是 Speed。我們特別要提到 Early Hints 功能。Early Hints 是一種新的 Web 標準,它定義了一個新的 HTTP 103 標頭,伺服器可以使用它來通知瀏覽器可能需要哪些資產來呈現網頁,同時它仍然會被請求,從而顯著縮短載入時間。

您可以使用具有 Early Hints 的 Cloudflare Pages

API

Radar 有兩個 API。可以直接存取我們的資料來源的後端,以及可在網際網路上使用的前端。

後端 API

後端 API 是使用 PythonPandas FastAPI 編寫的,並受 Cloudflare AccessJWT 權杖經過驗證的原始拉取 (AOP) 設定的保護。使用 Python 可以讓團隊中的任何人、工程師或資料科學家輕鬆協作並為改進和擴展 API 做出貢獻,這是非常有用的。我們的資料科學團隊使用 JupyterHubJupyter Notebooks 作為其資料探索工作流程的一部分,這使得原型設計和重用程式碼、演算法和模型變得特別容易和快速。

然後,它透過基於 Strawberry 的 GraphQL 伺服器與上游前端 API 通訊。使用 GraphQL 可以輕鬆建立複雜的查詢,為內部使用者和分析師提供從我們龐大的資料集合構建報告所需的靈活性。

前端 API

我們在 Cloudflare Workers 之上構建了 Radar 的前端 API。此 Worker 有兩個主要功能:

  • 它使用 GraphQL 從後端 API 擷取資料,然後對其進行轉換。
  • 它提供了一個任何人都可以使用的公用 REST API,包括 Radar。

在我們的核心 API 前面使用 Worker 使我們能夠輕鬆新增和分離微服務,並且還新增了值得注意的功能,例如:

  • Cloudflare  的快取 API 允許更精細地控制要快取的內容和快取時間,並支援我們使用的 POST 請求和可自訂的快取控制標頭。
  • 使用 R2 的過時回應。當後端 API 由於某種原因無法為請求提供服務,並且快取了過時的回應時,它將直接從 R2 提供,從而為終端使用者提供更好的體驗。
  • CSVJSON 輸出格式。CSV 格式很方便,讓資料科學家、分析師和其他人能夠更輕鬆地使用 API 並直接從其他工具使用我們的 API 資料。

對我們的 OpenAPI 3 結構描述產生器和驗證程式開放原始碼

前端 API 的最後一個功能是OpenAPI 3支援。我們自動產生一個 OpenAPI 結構描述,並使用它驗證使用者輸入。這是透過我們在 itty-router 之上建置的自訂庫完成的,我們也使用該自訂庫。今天,我們將對這項工作開放原始碼。

itty-router-openapi 為 Cloudflare Workers 提供了一個簡單緊湊的 OpenAPI 3 結構描述產生器和驗證程式。查看我們的 GitHub 存放庫以獲取有關如何使用它的更多資訊和詳細資料。

Developer’s Documentation

今天,我們還推出了 Radar API 的開發人員文件頁面,您可以在其中找到有關我們的資料授權、基本概念、入門方式和可用 API 方法的更多資訊。Cloudflare Radar 的 API 是免費的,允許學者、資料偵探和其他 Web 愛好者根據我們全球網路的資料調查全球網際網路使用情況。

為了方便使用我們的 API,我們還整理了一個 Colab Notebook 範本,您可以使用、複製和擴展到您的使用案例中。

Radar 應用程式

Radar 應用程式是在瀏覽器中執行的程式碼。我們已經討論過 Remix,但我們還要使用什麼?

Radar 依賴於大量的資料視覺效果。圖表和地圖之類的東西對我們來說是必不可少的。我們決定在其他兩個框架之上建置可重用的視覺效果元件庫:visx,「用於 React 的表達性低級視覺效果基本類型的集合」;D3,用於基於資料操作 DOM 的強大 JavaScript 庫;以及 MapLibre ,一個開放原始碼的地圖視覺效果堆疊。

這是我們正在運轉的視覺效果元件之一。我們稱之為「PewPew 地圖」。

這是它的 Remix React 程式碼,每當我們需要在頁面中使用它時,將用到以下程式碼:

<Card.Section
    title={t("card.attacks.title")}
    description={t("card.attacks.description")}
  >
    <Flex gap={spacing.medium} align="center" justify="flex-end">
      <SegmentedControl
        label="Sort order:"
        name="attacksDirection"
        value={attacksDirection}
        options={[
          { label: t("common.source"), value: "ORIGIN" },
          { label: t("common.target"), value: "TARGET" },
        ]}
      onChange={({ target }: any) => setAttacksDirection(target.value)}
      />
    </Flex>

    <Components.AttacksCombinedChart
      ssr={ssr}
      height={400}
      direction={attacksDirection}
    />
  </Card.Section>

SVG

我們對 Radar 所做的另一項變更是將影像和圖形資產切換到可縮放向量圖形。SVG 很棒,因為它們本質上是一種聲明性圖形語言。它們是帶有向量資訊的 XML 文字檔案。因此,它們可以輕鬆操作、轉換、儲存或索引,當然,它們能夠以任意大小呈現,在任何裝置上以任何解析度產生美麗、清晰的結果。

與點陣圖格式相比,SVG 的尺寸也非常小且高效,並且支援國際化,使其更容易翻譯成其他語言(當地語系化),從而提供更好的可存取性

下面是一個經過檢查的 Radar 泡泡圖範例,您可以在其中看到嵌入的 SVG 程式碼和 <text/> 字串。

Cosmos

React Cosmos 是一個「用於在隔離環境中開發和測試 UI 元件的沙箱」。我們想將 Cosmos 與 Radar 2.0 一起使用,因為它是完美的專案:

  1. 它有很多視覺元件;有些很複雜,並且具有許多設定選項和功能。
  2. 這些元件在不同環境中具有不同資料的多個頁面之間具有高度可重用性。
  3. 我們擁有一支多學科團隊;每個人都可以在前端傳送 pull 請求並新增或變更程式。

Cosmos 充當元件庫,可在其中查看我們的即用型視覺效果和小工具選擇區,從簡單的按鈕到複雜的圖表,您可以即時使用它們的選項並查看會發生什麼。任何人都可以做到,不論是設計師和工程師,還是其他專案利益相關者。這有效地改善了團隊溝通,並能夠加快貢獻和反覆速度。

以下是我們的 Cosmos 在動作時的螢幕擷取畫面:

持續整合和開發

持續整合對於任何開發現代軟體的團隊都很重要。Cloudflare Pages 提供了多個選項來與使用直接上傳的 CI 工具搭配使用,這些選項都現成可用。該團隊已經提供了有關如何使用 GitHub Actions、CircleCI 和 Travis 執行此操作的文件和範例,但您也可以使用其他產品。

在我們的例子中,我們在內部使用 BitBucket 和 TeamCity 來建置和部署我們的版本。我們的工作流程會在幾分鐘內自動建置、測試和部署 Radar 2.0,並完成經核准的 PR 和後續合併。

單元測試使用 Vitest 完成,E2E 測試則使用 Playwright 進行。計劃進行視覺迴歸測試,Playwright 也可以對此提供幫助

此外,在發佈到生產環境之前,我們有多個環境來暫存和測試我們的版本。我們的 CI/CD 設定讓開發人員能夠輕鬆地從一個環境切換到另一個環境,或快速復原任何不需要的部署。

同樣,Cloudflare Pages 使用預覽部署、別名或分支組建控制可以輕鬆執行此操作。使用環境的普通 Workers 也是如此。

快速預覽和通知

我們承認,Radar 1.0 在執行 CI/CD 時並不是特別快。我們曾遇到過幾次,從提交程式碼到部署,快速檢修可能需要花費 30 分鐘時間,我們對此感到沮喪。

因此,我們投入了大量資金,以確保新的 CI 能夠快速、高效且充滿激情。

我們最後做的一件很酷的事情,是快速預覽推送到程式碼存放庫的任何提交的連結。結合使用組建期間的智慧快取和在提交超出正常發佈分支時執行異步測試,我們能夠將部署時間縮短到幾秒鐘。

當任何人將程式碼推送到任何分支時,我們會到聊天中收到以下通知:

任何人都可以關注聊天中有關特定分支的對話,並在發生新變更時收到通知。

超快的組建、預覽連結和通知將改變遊戲規則。工程師可以完成從一個想法或一個快速檢修方案,到在一個連結上向產品經理或其他團隊成員展示結果的過程。任何人只需快速按一下連結,就可以查看完全工作的 Radar 端到端版本的變更。

可存取性和當地語系化

Cloudflare 致力於 Web 可存取性。最近我們宣佈了如何升級 Cloudflare 的儀表板以遵守產業可存取性標準,但這一前提對我們的所有資產都有效。當地語系化也是如此。2020 年,我們對儀表板進行了國際化,新增了對新語言和地區設定的支援。

可存取性和當地語系化是齊頭並進的,兩者都很重要,但它們也是不同的。Web 內容可存取性指南定義了許多有關可存取性的最佳做法,包括使用色彩和對比度、標籤、SVG、捷徑、手勢等。A11Y 專案頁面是瞭解更多資訊的絕佳資源。

但是,當地語系化(也稱為 L10n)在啟動新專案時更像是一項技術要求。這關於確保您選擇正確的庫和框架集,以便更輕鬆地新增新翻譯,而無需工程依賴或程式碼重寫。

我們希望 Radar 在這兩個方面都表現良好。我們的設計系統認真對待 Cloudflare 的設計和品牌指南,並新增了盡可能多的 A11Y 良好做法,且該應用程式完全瞭解其頁面和 UI 元件中的當地語系化字串。

新增新語言就像翻譯單個 JSON 檔案一樣簡單。下面是包含預設美式英文字串的 en-US.json 檔案片段:

{
  "abbr.asn": "Autonomous System Number",
  "actions.chart.download.csv": "Download chart data in CSV",
  "actions.chart.download.png": "Download chart in PNG Format",
  "actions.chart.download.svg": "Download chart in SVG Format",
  "actions.chart.download": "Download chart",
  "actions.chart.maximize": "Maximize chart",
  "actions.chart.minimize": "Minimize chart",
  "actions.chart.share": "Share chart",
  "actions.download.csv": "Download CSV",
  "actions.download.png": "Download PNG",
  "actions.download.svg": "Download SVG",
  "actions.share": "Share",
  "alert.beta.link": "Radar Classic",
  "alert.beta.message": "Radar 2.0 is currently in Beta. You can still use {link} during the transition period.",
  "card.about.cloudflare.p1": "Cloudflare, Inc. ({website} / {twitter}) is on a mission to help build a better Internet. Cloudflare's suite of products protects and accelerates any Internet application online without adding hardware, installing software, or changing a line of code. Internet properties powered by Cloudflare have all web traffic routed through its intelligent global network, which gets smarter with every request. As a result, they see significant improvement in performance and a decrease in spam and other attacks. Cloudflare was named to Entrepreneur Magazine's Top Company Cultures 2018 list and ranked among the World's Most Innovative Companies by Fast Company in 2019.",
  "card.about.cloudflare.p2": "Headquartered in San Francisco, CA, Cloudflare has offices in Austin, TX, Champaign, IL, New York, NY, San Jose, CA, Seattle, WA, Washington, D.C., Toronto, Dubai, Lisbon, London, Munich, Paris, Beijing, Singapore, Sydney, and Tokyo.",
  "card.about.cloudflare.title": "About Cloudflare",
...

我們很快將以其他語言發佈 Radar,敬請期待。

Radar 報告和 Jupyter Notebooks

Radar 報告是使用資料探索和講故事的方式來深入分析特定主題的文件。部分報告通常會不時更新。我們的季度 DDoS 攻擊趨勢IPv6 採用都是 Radar 報告的範例。

這些報告的來源是 Jupyter Notebooks。我們的資料科學團隊使用我們的內部 Jupyter Hub 工具與其他利益相關者一起研究一些使用案例或主題。完成所有反覆運算和探索並簽署工作後,將生成一個 Notebook。

Jupyter Notebook 是一個 JSON 文件,其中包含文字、原始程式碼、多媒體(如影像或圖表)以及其他中繼資料。它是呈現資料科學專案的事實標準,每個資料科學家都使用它。

使用 Radar 1.0 時,將 Jupyter Notebook 轉換為 Radar 頁面是一個漫長的手動過程,涉及許多工程和設計資源,並給所有相關人員帶來很多挫敗感。即使更新已經發佈的 Notebook 也經常會給我們帶來麻煩。

Radar2.0 改變了這一切。我們現在有一個完全自動化的流程,它擷取使用簡單規則和內部方針清單設計的 Jupyter Notebook,將其自動轉換,將產生的 HTML 和資產託管在 R2 貯體中,然後將其發佈在報告頁面上。

轉換為 HTML 的過程考慮了我們的設計系統和 UI 元件,會產生一個漂亮的文件,通常是長篇,與 Radar 的外觀和感覺完美匹配。

我們最終將對此工具開放原始碼,以便任何人都可以使用它。

更多的 Cloudflare,更少的擔憂

我們提供了一些範例,展示如何使用 Cloudflare 的產品和功能來建置下一代應用程式,而無需過多擔心與您的業務或邏輯無關的事情。不過,有一些不見了。

在應用程式啟動並執行后,您必須保護它免受不良流量和惡意行為者的侵害。Cloudflare 為您提供現成可用的 DDoSWAF機器人管理保護,只需點擊一下即可獲得。

例如,以下是我們的一些安全性規則。這是我們在應用程式中不必擔心的流量,因為 Cloudflare 會偵測到它並根據我們的規則對其進行處理。

我們也不需要擔心從舊網站到新網站的重新導向。Cloudflare 有一個稱為大量重新導向的功能,使用此功能,您可以直接在儀表板上輕鬆建立重新導向清單。

同樣重要的是,每次我們談論您可以使用我們的儀表板做什麼時,我們實際上也在說您可以使用 Cloudflare 的 API 做同樣的事情。我們的儀表板完全建立在它們之上。如果您是基礎結構即程式碼類型的人,我們也可以滿足您的需求;您可以使用 Cloudflare Terraform 提供者

部署和管理 Workers、R2 貯體或 Pages 網站顯然也可以編寫指令碼。Wrangler 是一個命令列工具,可用於執行此操作及更多操作。它甚至更進一步,讓您能夠本機執行完整的應用程式,在部署之前在您的電腦上模擬我們的堆疊。

結語

我們希望您喜歡 Radar 團隊的這篇文章,並受到啟發,在我們的 Supercloud 之上建置您的下一個應用程式。我們將繼續改進和創新 Radar 2.0 的新功能,與您分享我們的發現並對我們的工具開放原始碼。

與此同時,我們在開發人員 Discord 伺服器上開啟了一個 Radar 聊天室。歡迎加入並向我們提問,團隊熱切希望收到回饋以及與您討論 Web 技術。

您也可以在 Twitter 上關注我們,瞭解更多 Radar 更新動態。

我們會保護 整個企業網路, 協助客戶打造 有效率的網際網路規模應用程式, 加快任何 網站或網際網路應用程式 阻擋 DDoS 攻擊, 讓 駭客無機可乘, 還能夠協助您 順利展開 Zero Trust 之旅

透過任何裝置造訪 1.1.1.1, 即可開始使用我們的免費應用程式,讓您的網際網路更快速且更安全。

若要深入瞭解我們協助構建更美好網際網路的使命,請從 這裡開始。 您正在尋找新的職業方向,請查看 我們的開放職缺

開發人員週 Cloudflare Radar (TW) Cloudflare Workers (TW) Cloudflare Pages (TW) 繁體中文 (TW)

Follow on Twitter

Celso Martinho |@celso
Cloudflare |Cloudflare

Related Posts