在現代應用程式開發中,支援多客戶和採用微服務架構已成為提升系統可靠性、可擴充套件性和彈性的重要策略。本文將探討如何利用負載平衡器和 Kubernetes 等技術來實作多客戶支援,並逐步引導讀者使用 Node.js 和 Express 建立第一個微服務。同時,文章也涵蓋了設定開發環境、Docker 容器化和容器協調等實務操作,幫助讀者建立完整的微服務開發流程。

透過負載平衡器,我們可以有效地將流量分佈到多個伺服器,避免單點故障並提高系統的整體吞吐量。Kubernetes 則提供了一個自動化的平臺,用於佈署、擴充套件和管理容器化的應用程式,簡化了微服務的維運管理。此外,細粒度的可擴充套件性控制允許我們根據不同服務的需求獨立調整資源,最佳化資源利用率並降低成本。文章將以實際案例示範如何在 Node.js 環境下建立 HTTP 伺服器,並逐步引導讀者理解程式碼的每個環節,包含使用 Express 框架簡化伺服器建立流程,以及 npm 套件管理工具的使用。

如何擴充套件應用程式以支援多客戶

為了讓應用程式能夠支援多客戶,需要進行擴充套件以確保系統的可靠性和效能。這可以透過使用負載平衡器(load balancers)來實作,負載平衡器可以將流量分配到多個伺服器上,從而提高系統的整體吞吐量和可用性。

負載平衡器的作用

負載平衡器允許我們複製服務以實作冗餘和提高吞吐量。透過複製個別的服務,我們可以對可擴充套件性進行細粒度的控制。這意味著我們可以根據不同服務的需求,獨立地擴充套件或縮減它們,從而更好地利用資源並提高系統的整體效能。

Kubernetes 叢集的應用

在生產環境中,我們的應用程式佈署在一個 Kubernetes 叢集中。Kubernetes 提供了一個自動化的方式來佈署、擴充套件和管理容器化的應用程式。透過 Kubernetes,我們可以輕鬆地建立和管理多個服務的複製品,從而實作高用性和可擴充套件性。

實作細粒度可擴充套件性的優點

複製個別的服務允許我們對可擴充套件性進行細粒度的控制。這意味著我們可以根據每個服務的具體需求進行擴充套件或縮減,而不是整個應用程式一起擴充套件。這種方法不僅可以提高資源利用率,也可以降低成本,因為我們只需要為需要擴充套件的服務付費。

內容解密:

# Kubernetes 叢集架構
- 使用負載平衡器分配流量
- 複製服務以實作冗餘和提高吞吐量
- 透過 Kubernetes 自動化佈署和管理容器化應用程式

圖表翻譯:

  graph LR
    A[客戶請求] --> B[負載平衡器]
    B --> C[服務複製1]
    B --> D[服務複製2]
    C --> E[容器化應用程式1]
    D --> F[容器化應用程式2]
    E --> G[Kubernetes 叢集]
    F --> G

透過這種架構,我們可以輕鬆地擴充套件應用程式以支援多客戶,並確保系統的高用性和效能。

建立您的第一個微服務

在本章中,我們將學習如何構建一個由多個微服務組成的應用程式。但是在我們可以構建多個微服務之前,我們必須先學習如何構建一個單個微服務。在本章中,我們將建立我們的第一個微服務。這個簡單的微服務做得很少,但它闡述了過程,以便您可以理解它並重複它。

2.1 新工具

在本章中,我們的微服務是使用JavaScript編寫並在Node.js上執行的。但是,請注意,我們可以使用任何技術堆積堆疊來構建微服務。使用微服務構建應用程式給了我們很多自由度,可以選擇技術堆積堆疊。

2.2 取得程式碼

本章附帶許多工作示例專案。每個專案的程式碼都可以在GitHub上找到。你可以克隆或下載程式碼倉函式庫以跟隨書中的示例。我強烈建議你在閱讀書籍時執行這些示例。這是你獲得實踐經驗和最大化學習收益的最佳方式。

2.3 為什麼選擇Node.js?

在本章中,我們使用Node.js來構建微服務。為什麼選擇Node.js?其中一個優點是,我們可以選擇自己喜歡的技術堆積堆疊。我喜歡Node.js,並且在日常工作中使用它,但我也有其他理由選擇它。

使用Node.js的優點

  • Node.js是網路導向和高效能的,使其非常適合構建微服務。
  • Node.js是一個流行且廣泛使用的平臺,這意味著有許多人、工具和資源可供使用。
  • Node.js非常適合構建小型、高速和輕量級的服務,並避免了許多其他平臺的不必要包袱。

使用JavaScript的優點

  • JavaScript是一種全端語言,可以用於應用程式的後端和前端。
  • 使用JavaScript可以減少心理上下文切換,因為我們可以在整個應用程式中使用相同的語言。

2.4 建立您的第一個微服務

現在,我們將建立我們的第一個微服務。這個簡單的微服務是一個HTTP伺服器,向使用者傳送串流媒體影片。

const http = require('http');

http.createServer((req, res) => {
    res.writeHead(200, {'Content-Type': 'video/mp4'});
    // 傳送影片內容
}).listen(3000, () => {
    console.log('伺服器啟動於連線埠3000');
});

內容解密:

  • http模組:Node.js內建的HTTP模組,用於建立HTTP伺服器。
  • createServer方法:建立一個HTTP伺服器例項。
  • req物件:代表HTTP請求。
  • res物件:代表HTTP回應。
  • writeHead方法:設定HTTP回應頭。
  • listen方法:啟動HTTP伺服器並指定監聽連線埠。

2.5 設定生產和開發環境

現在,我們需要設定生產和開發環境。我們將使用Docker和Kubernetes來管理我們的微服務。

  graph LR
    A[開發環境] -->|Docker|> B[生產環境]
    B -->|Kubernetes|> C[容器協調]

圖表翻譯:

  • 圖表展示了開發環境、生產環境和容器協調之間的關係。
  • 開發環境使用Docker建立容器。
  • 生產環境使用Kubernetes進行容器協調。

軟體開發哲學

在我們開始撰寫程式碼之前,我想簡要介紹一下我的軟體開發哲學,這將是我們在整個開發過程中所遵循的原則。這些原則將在我們的開發工作中不斷體現,因此有必要進行簡要的解釋。我將我的開發哲學總結為以下三點:

  1. 迭代:這是開發過程中的關鍵要素。我所指的是小規模的個人迭代,而不是通常在敏捷開發中所指的較大的迭代(例如衝刺)。我透過一系列的小型個人工作迭代來撰寫程式碼,每次迭代都會增加和編輯程式碼,如圖 2.1 所示。在這種工作方式中,每次迭代都會給我們反饋。這些反饋允許我們發現當我們偏離正軌時,並立即進行糾正。快速迭代使我們能夠緊密地將工作與不斷演變的目標對齊。

注意:小規模、快速的程式碼增量是軟體開發旅程中的必備要素。

  1. 保持可工作狀態:在每次迭代中,我們只會進行少量的程式碼編寫。具體多少取決於我們正在做什麼以及難度如何。但是,關鍵是它應該足夠小,以便我們可以輕鬆地理解和測試剛剛撰寫的程式碼。

每次迭代都必須產生可工作和經過測試的程式碼。這是最重要的因素。你是否曾經輸入整頁程式碼,然後苦苦掙扎數小時才讓它工作?當我們以小型、經過良好測試的程式碼迭代工作時,一天結束時累積的結果是一大塊可工作的程式碼。你可以在圖 2.1 中看到這個過程。

  flowchart TD
    A[開始] --> B[撰寫少量程式碼]
    B --> C[測試程式碼]
    C --> D[迭代反饋]
    D --> E[糾正偏差]
    E --> F[重複過程]

程式碼與測試

每次迭代都會撰寫少量程式碼並進行測試。這個過程不斷重複,直到完成整個開發任務。

圖表翻譯:

圖 2.1 展示了一系列的小型、經過良好測試的程式碼變更,最終結果是一大塊可工作的程式碼。每次迭代都是收集反饋的機會,讓我們可以及時發現問題並進行糾正。

  1. 從簡單到複雜:這是我們開發過程中的第三個原則。從簡單開始,逐步增加複雜度,可以讓我們更好地控制開發過程,避免不必要的複雜性。

透過遵循這三個原則,我們可以確保開發過程的順暢和高效,並最終產生出高品質的軟體產品。

建立微服務的哲學

在建立微服務的過程中,我們需要遵循一些基本的哲學。首先,我們需要確保我們的程式碼是可工作的,並且在每次修改後仍然保持可工作的狀態。這意味著我們需要在小的、易於測試的增量中工作,以避免出現太多的錯誤或問題。

其次,我們需要從簡單開始,逐漸增加複雜度。這意味著我們不應該嘗試一次性建立一個複雜的系統,而是應該從簡單的程式碼開始,然後逐步增加功能和複雜度。

最後,我們需要確保我們的程式碼是模組化的,並且每個模組都是獨立的和可測試的。這意味著我們需要使用像Node.js這樣的工具來建立和執行我們的微服務,並且需要使用像Docker這樣的工具來管理和佈署我們的微服務。

微服務的優點

微服務有很多優點,包括:

  • 可擴充套件性:微服務可以獨立擴充套件,這意味著我們可以根據需要增加或減少每個服務的例項數量。
  • 容錯性:如果一個微服務出現問題,其他微服務可以繼續執行,這意味著整個系統可以保持可用。
  • 靈活性:微服務可以使用不同的語言和框架來實作,這意味著我們可以根據需要選擇最合適的工具和技術。

建立單一微服務的開發環境

要建立一個微服務,我們需要設定一個開發環境。這個環境需要包括以下幾個部分:

  • Node.js:我們需要安裝Node.js來執行我們的微服務。
  • 程式碼編輯器:我們需要一個程式碼編輯器來編寫和修改我們的程式碼。
  • 執行環境:我們需要一個執行環境來執行我們的微服務。

執行單一微服務

要執行一個單一的微服務,我們可以使用Node.js直接執行它。這個過程包括以下幾個步驟:

  1. 建立一個新的Node.js專案:我們需要建立一個新的Node.js專案來包含我們的微服務程式碼。
  2. 編寫微服務程式碼:我們需要編寫我們的微服務程式碼,包括定義API介面和實作業務邏輯。
  3. 執行微服務:我們可以使用Node.js直接執行我們的微服務。

使用Docker管理多個微服務

當我們需要管理多個微服務時,我們可以使用Docker來幫助我們。Docker是一個容器化平臺,可以幫助我們建立、執行和管理多個微服務。

微服務開發環境

下圖展示了我們的單一微服務開發環境:

  graph LR
    A[程式碼編輯器] -->|編寫程式碼|> B[Node.js專案]
    B -->|執行程式碼|> C[執行環境]
    C -->|產生結果|> D[結果]

在這個環境中,我們可以使用程式碼編輯器來編寫和修改我們的程式碼,然後使用Node.js直接執行它。這個過程可以幫助我們快速地開發和測試我們的微服務。

安裝 Git

要存取本章的範例專案和程式碼,您需要存取 GitHub 上的 Bootstrapping Microservices 組織(請參考第 2.2 節中的連結)。圖 2.4 顯示了每個程式碼倉函式庫的結構。每個子目錄(例如 example-1、example-2 等)都是一個可執行的專案,您可以自己執行它來跟隨書中的內容(假設您不想親自輸入所有程式碼)。

開發電腦 Node.js 專案

主機作業系統(Linux、Windows 或 macOS)

Visual Studio

程式碼

(或其他 IDE) Node.js

我們的

微服務 您:開發者 圖 2.3 我們在第 2 章中使用的單一服務開發環境

每個目錄都包含

一個完整的可執行範例。

您可以執行

程式碼並跟隨書中的內容。

Git 安裝步驟

  1. 下載 Git:存取 Git 官方網站,下載適合您作業系統的 Git 安裝包。
  2. 安裝 Git:按照安裝指示,完成 Git 的安裝。
  3. 設定 Git:安裝完成後,設定您的 Git 使用者名稱和電子郵件地址,以便提交程式碼時能夠識別您的身份。
  4. 驗證 Git 安裝:開啟終端機或命令提示符,輸入 git --version 來驗證 Git 是否已經成功安裝。

內容解密:

以上步驟將引導您完成 Git 的安裝和設定。Git 是一個版本控制系統,能夠幫助您管理程式碼的變更和協作。透過安裝和設定 Git,您將能夠存取和下載本章的範例程式碼,並跟隨書中的內容進行學習和實踐。

  flowchart TD
    A[下載 Git] --> B[安裝 Git]
    B --> C[設定 Git]
    C --> D[驗證 Git 安裝]

圖表翻譯:

此圖表顯示了 Git 安裝的步驟流程。從下載 Git 開始,接著是安裝 Git,然後是設定 Git,最後是驗證 Git 安裝。每個步驟都很重要,確保您能夠成功安裝和使用 Git。

建立微服務開發環境

在開始建立微服務之前,我們需要建立一個合適的開發環境。這包括安裝必要的工具和軟體,以便我們可以順暢地進行開發工作。

下載程式碼

首先,我們需要下載本章的程式碼。您可以透過存取GitHub倉函式庫並下載zip檔案來完成此操作。或者,如果您熟悉Git,可以使用Git命令來克隆倉函式庫。

git clone https://github.com/your-repo/bootstrapping-microservices-2nd-edition.git

安裝Git

如果您尚未安裝Git,現在是安裝的好時機。Git是一種版本控制系統,允許您跟蹤程式碼變化並與他人合作。您可以在Git官網上找到安裝。

git --version

這個命令可以檢查您的Git版本。如果您尚未安裝Git,將會顯示一個錯誤訊息。

安裝VS Code

VS Code是一種流行的編輯器,提供了豐富的功能和擴充套件,以支援各種程式設計語言。我推薦使用VS Code,因為它輕量、效能優異且可定製。

安裝Node.js

Node.js是一種JavaScript執行環境,允許您在伺服器端執行JavaScript程式碼。它是本章中所有微服務的基礎。

node --version
npm --version

這些命令可以檢查您的Node.js和npm版本。

建立HTTP伺服器

現在,我們可以開始建立一個簡單的HTTP伺服器。這個伺服器將用於提供影片串流功能。

步驟1:建立Node.js專案

首先,我們需要建立一個新的Node.js專案。這個專案將包含我們的微服務程式碼。

mkdir my-microservice
cd my-microservice
npm init

步驟2:安裝Express

Express是一種流行的Node.js框架,提供了快速建立Web應用的功能。

npm install express

步驟3:建立HTTP伺服器

現在,我們可以建立一個簡單的HTTP伺服器。

const express = require('express');
const app = express();

app.get('/video', (req, res) => {
  // 處理影片串流邏輯
});

app.listen(3000, () => {
  console.log('伺服器啟動於連線埠3000');
});

這個程式碼建立了一個簡單的HTTP伺服器,監聽連線埠3000上的請求。

建立 HTTP 伺服器進行影片串流

建立 Node.js 專案

要開始建立一個 Node.js 專案,首先需要建立一個目錄來存放專案的原始碼和組態。可以使用終端機中的 mkdir 命令(適用於 Linux 和 macOS)或 md 命令(適用於 Windows)來建立目錄。例如:

mkdir my-new-project

md my-new-project

接著,使用 cd 命令切換到新建立的目錄:

cd my-new-project

初始化 Node.js 專案

在目錄中,使用 npm init 命令來初始化一個空的 Node.js 專案。為了簡化過程,可以使用 -y 引數跳過互動式問題:

npm init -y

這將建立一個 package.json 檔案,其中包含預設值。雖然這些預設值可以稍後修改,但現在可以先使用預設值繼續進行。

package.json 檔案結構

package.json 檔案包含了 Node.js 專案的相關資訊,包括依賴項、入口點等。以下是 package.json 檔案的一個基本結構:

{
  "name": "my-new-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {}
}

這個檔案定義了專案的名稱、版本、描述、入口點等基本資訊。

內容解密:

  • name 欄位指定了專案的名稱。
  • version 欄位指定了專案的版本號。
  • description 欄位提供了對專案的簡要描述。
  • main 欄位指定了專案的入口點,即程式執行的起始點。
  • scripts 欄位定義了可用的指令碼命令,例如測試命令。
  • keywords 欄位列出了與專案相關的關鍵字。
  • author 欄位指定了專案的作者。
  • license 欄位指定了專案使用的授權協定。
  • dependencies 欄位列出了專案依賴的其他套件。

建立 HTTP 伺服器

要建立一個 HTTP 伺服器,需要使用 Node.js 的 http 模組。以下是一個基本的 HTTP 伺服器實作:

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

這個程式碼建立了一個 HTTP 伺服器,監聽 3000 連線埠,並傳回「Hello World」字串作為回應。

圖表翻譯:

  graph LR
    A[Client] -->| Request | B[Server]
    B -->| Response | A

這個圖表展示了客戶端和伺服器之間的請求和回應過程。

影片串流

要實作影片串流,需要使用 Node.js 的 fs 模組來讀取影片檔案,並使用 http 模組來傳輸影片資料。以下是一個基本的影片串流實作:

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
  if (req.url === '/video') {
    const videoFile = 'path/to/video.mp4';
    fs.readFile(videoFile, (err, data) => {
      if (err) {
        console.error(err);
        res.writeHead(500, {'Content-Type': 'text/plain'});
        res.end('Error reading video file');
      } else {
        res.writeHead(200, {'Content-Type': 'video/mp4'});
        res.end(data);
      }
    });
  } else {
    res.writeHead(404, {'Content-Type': 'text/plain'});
    res.end('Not Found');
  }
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

這個程式碼建立了一個 HTTP 伺服器,監聽 3000 連線埠,並提供影片串流功能。當客戶端請求 /video 路由時,伺服器會讀取指定的影片檔案,並傳輸影片資料給客戶端。

圖表翻譯:

  graph LR
    A[Client] -->| Request /video | B[Server]
    B -->| Read video file | C[File System]
    C -->| Return video data | B
    B -->| Response | A

這個圖表展示了客戶端請求影片、伺服器讀取影片檔案、並傳輸影片資料給客戶端的過程。

建立 Node.js 專案

任何良好的專案都應該有一個 README 檔案,以便解釋如何設定和開始使用它。讓我們來探索一下 Node.js 專案的基本結構。

專案結構

一個典型的 Node.js 專案包含以下檔案和目錄:

  • package.json:包含專案的版本和其他相關資訊。
  • package-lock.json:用於追蹤所有相依套件的版本,包括巢狀相依套件。
  • README.MD:專案的 README 檔案。
  • node_modules:安裝的套件存放目錄。
  • src:原始碼目錄,包含 index.js 等檔案。

package.json

package.json 是 Node.js 專案的核心檔案,包含了專案的基本資訊,如名稱、版本、描述等。以下是 package.json 的範例內容:

{
  "name": "my-new-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "...",
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

這個檔案可以被手動編輯,以便更改專案的相關資訊。

package-lock.json

package-lock.json 是一個自動生成的檔案,用於追蹤所有相依套件的版本,包括巢狀相依套件。這個檔案不應該被手動編輯,而是由 npm 自動更新。

package.json vs. package-lock.json

雖然 package.json 可以指定相依套件的版本,但通常它只會指定最低版本或版本範圍。這可能會導致不同的開發人員或生產環境下使用不同的版本。為瞭解決這個問題,package-lock.json 被引入,以確保所有相依套件的版本一致。

提交 package-lock.json

為了確保所有團隊成員和生產環境使用相同的組態,應該提交 package-lock.json 到版本控制系統中。

建立 HTTP 伺服器

在建立 Node.js 專案後,可以開始增加程式碼。以下是建立一個簡單的 HTTP 伺服器的範例:

const http = require('http');

http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(3000, () => {
  console.log('Server running on port 3000');
});

這個範例建立了一個簡單的 HTTP 伺服器,監聽 3000 連線埠,並傳回 “Hello World” 的字串。

圖表翻譯:

  graph LR
    A[HTTP Request] --> B[Node.js Server]
    B --> C[Response]
    C --> D[Client]

這個圖表展示了 HTTP 請求、Node.js 伺服器和客戶端之間的互動過程。

安裝 Express

為了從微服務中串流視訊,我們需要將其變成一個 HTTP 伺服器(也稱為網頁伺服器)。換句話說,它將對瀏覽器的 HTTP 請求做出反應,在本例中,瀏覽器請求播放串流視訊。為了實作我們的 HTTP 伺服器,我們將使用 Express。

Express 是 Node.js 上構建 HTTP 伺服器的事實標準框架。使用 Express 比只使用低階別 Node.js API 更容易建立網頁伺服器。Express 是 Node.js 上構建 HTTP 伺服器最受歡迎的程式函式庫。你可以在安裝 Express 的同時探索其它許多功能。

當然,我們可以在沒有 Express 的情況下直接在 Node.js 上建立 HTTP 伺服器,但 Express 允許我們在更高的抽象層次上完成這項工作,需要的程式碼更少,而且不需要使用低階別 Node.js API 時所需的複雜程式碼。使用 Express 也是一個很好的機會讓我們學習如何安裝 npm 套件以供我們的微服務使用。npm 是 Node.js 的套件管理器,它讓我們可以輕鬆地存取大量的套件,包括許多函式庫和框架,如 Express,讓我們可以快速、輕鬆地完成各種工作。

安裝 Express

我們可以使用以下命令從終端安裝最新版本的 Express:

npm install --save express

執行此命令會將 Express 套件安裝到我們的專案中。為了本章的目的,我決定使用 Express v5 beta:

npm install --save express@5.0.0-beta.1

Express v5 beta 支援非同步路由處理器,這將簡化後續的編碼。我希望當你讀到這段文字時,v5 已經不是 beta 版本了,不要太擔心 Express v4 和 v5 之間的差異;除了支援非同步路由處理器外,我沒有注意到任何其他值得注意的差異,而且本章中的所有程式碼範例都應該可以在兩個版本中執行(除了 Express v4 和更早版本會以略微不同的方式處理非同步錯誤)。

--save 引數會將相依性增加到 package.json 檔案中並進行追蹤。注意,--save 不再是必要的。在較舊版本的 Node.js 中,這是必需的;現在,它是預設行為。我明確包含 --save 以便突出其作用,但你不再需要使用它。

更新 package.json

安裝 Express 後,我們的 package.json 檔案將被更新,如下所示:

{
  "name": "example-1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    --snip--
  },
  "dependencies": {
    "express": "^5.0.0-beta.1"
  }
}

如你所見,現在我們有了一個 dependencies 欄位,其中包含了我們安裝的 Express 版本。

圖表翻譯:

  graph LR
    A[安裝 Express] --> B[更新 package.json]
    B --> C[確認相依性]
    C --> D[開始使用 Express]

這個圖表顯示了安裝 Express、更新 package.json 和確認相依性之間的關係。

建立一個簡單的 Express HTTP 伺服器

在開始構建影片串流微服務之前,我們需要先建立一個標準的 Express HTTP 伺服器。以下是建立一個簡單的 Express 伺服器的步驟:

從技術架構視角來看,建構支援多客戶的應用程式,負載平衡和微服務化是確保系統可擴充套件性和高用性的關鍵策略。本文深入探討瞭如何利用負載平衡器分配流量,並結合Kubernetes實作容器化應用程式的自動化佈署和管理。同時,文章也闡述了以Node.js和Express建構微服務的優勢,以及實踐中從簡單到複雜的迭代開發哲學。透過逐步建立HTTP伺服器和影片串流功能,展現了微服務架構的靈活性和可擴充套件性。然而,微服務化也帶來了服務間通訊、資料一致性和複雜度管理等挑戰。展望未來,Service Mesh等技術的發展將有助於簡化微服務的管理和維運,而Serverless的興起也為微服務架構的演進提供了新的方向。玄貓認為,對於尋求高擴充套件性和靈活性的應用程式而言,採用微服務架構並結合容器化技術,將是應對未來業務增長和技術變革的有效策略。