1. 程式人生 > >使用 Node.js 搭建微服務閘道器

使用 Node.js 搭建微服務閘道器

目錄

Node.js 是什麼

Node.js 是一個基於 Chrome v8 引擎的 Javascript 執行環境,它使用了一個"事件驅動"且"非同步非阻塞 I/O" 的模型使其輕量且高效, Node.js 的包管理器 NPM 是全球最大的開源庫生態系統。

對其定義的補充說明:

  • Node.js 是一個執行環境,而不是 Javascript 類庫或者框架
  • Node.js 是基於 Chrome 瀏覽器的 V8 引擎開發的,該引擎是業界公認的高效能 js 引擎
  • Node.js 提供了事件驅動模型,可以將當前事件加入到事件佇列中輪詢
  • Node.js 提供了非同步非阻塞式 I/O 模型,它比傳統的同步阻塞式 I/O 模型具有更高的吞吐率
  • Node.js 的包管理器與 java 的 Maven 類似,但生態圈似乎更加龐大

安裝 node.js

wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-x64.tar.xz
tar -xvzf node-v10.15.0-linux-x64.tar.xz -C /usr/local/ --strip-components=1

Node.js 入門

先給一段程式碼

var fs = require('fs')

fs.readFile('/etc/hosts', function (err, data) {
  if (err) {
     throw err;
  }
  console.log(data.toString());
});

Node.js 會建立一個讀取檔案的事件,並立刻將該事件加入到事件佇列中,當前執行緒不會阻塞在這裡。理論上後續不管有多少執行緒都會進來併產生一系列事件,這些事件都會加入到同樣的事件佇列中,它們會在事件佇列中進行迴圈,一旦某個事件被觸發(比如讀取檔案成功),就會執行後面定義的回撥函式。

除了回撥函式這種非同步方式,它也提供了同步 API,程式碼如下

var fs = require('fs')

var data = fs.readFileSync('/etc/hosts')
console.log(data.toString());

Node.js 應用場景

Node.js 是針對實時 web 應用程式而開發的,非常適合為了滿足實時性較強且併發量較大的應用場景。

  1. I/O 密集型 web 應用

    應用程式分為兩大類

    • CPU 密集型應用
      • 對 CPU 要求較高,需要一個強大的計算過程
      • 如股票交易系統,資料分析系統等
    • I/O 密集型應用
      • 常常有頻繁的網路傳輸或磁碟儲存現象
      • 如高併發網站,實時 Web 系統等

    Express 是一個非常優秀的 web 框架

  2. Web 聊天室 Socket.IO

  3. 命令列工具

    可以寫一段 Node.js 程式,通過 NPM 的命令將其安裝到作業系統中,隨時在命令列控制檯輸入該命令執行。

    Commander.js

    基於 Node.js 的前端開發工具如下 Bower, Grunt, Gulp, Webpack, Yeoman

  4. HTTP 代理伺服器

Node.js 可以通過非同步的方式處理大量的兵法請求,它可以作為伺服器端應用程式的代理,起到如 Nginx, Apache 等 HTTP代理伺服器的作用。

常用的 HTTP 代理伺服器模組 node-http-proxy ,在實現微服務架構的服務閘道器是會用到該項技術。

npm 映象

淘寶提供了一個 NPM 映象,速度非常快。

npm install --registry=https://registry.npm.taobao.org

在安裝一個要打包到生產環境的安裝包時,你應該使用 npm install --save

如果你在安裝一個用於開發環境的安裝包(例如,linter, 測試庫等),你應該使用 npm install --save-dev。可在 npm 文件 中查詢更多資訊。

淘寶 npm 映象官網 http://npm.taobao.org/

使用 Node.js 搭建微服務閘道器

什麼是微服務架構

先來整體回顧下下微服務架構

微服務閘道器(Node.js) 是微服務架構中的核心元件,它是客戶端請求的門戶,是呼叫具體服務端的橋樑。它類似於 Facade 模式(門面模式),將底層複雜的細節進行了遮蔽,對外提供簡單且統一的呼叫方式,如 HTTP 方式。

微服務閘道器,也稱為服務閘道器(Service Gateway),或者 API 閘道器(API Gateway)。它們之間的關係如下面架構圖所示:

在上圖中,我們使用服務閘道器來建立 client 與 service1 之間的聯絡。當從 client 傳送請求時,請求首先進入 service gateway, 隨後 service gateway 就會將請求路由到具體的伺服器。在路由過程中,會涉及具體的路由演算法,最簡單的做法就是在 service gateway 中解析 client 請求中的路徑和請求頭,從而路由到具體的服務端。

為了確保服務具有較高的可用性,我們可部署多個相同的服務端,此時需要再 service gateway 中設定相關路由演算法,將請求隨機路由到具體的服務端,當然也可以對 client ip 地址進行 Hash 演算法,從而實現請求路由。

服務閘道器的路由過程我們稱為"反向代理"。和 Nginx ,Apache 類似。

反向代理的應用場景有

  1. 使靜態資源與動態資源分離
  2. 實現 AJAX 跨域訪問
  3. 搭建統一服務閘道器介面

使用 Node.js 實現反向代理

Node.js 搭建反向代理伺服器,需要下面 3 步

  1. 使用如下命令安裝 HTTP Proxy 模組

    npm install http-proxy
  2. 使用 HTTP Proxy 模組啟動代理伺服器,新建一個名為 app_proxy.js 的檔案

    var http = require('http');
    
    var httpProxy = require('http-proxy');
    
    var PORT = 1234;
    
    // 建立代理伺服器物件
    var proxy = httpProxy.createProxyServer();
    
    proxy.on('error', function (err, req, res) {
      res.end(); // 輸出空白響應資料
    });
    
    var app = http.createServer(function (req, res) {
      // 執行反向代理
      proxy.web(req, res, {
        target: 'http://localhost:8080' // 目標地址
      })
    })
    
    app.listen(PORT, function() {
      console.log('server is running at %d', PORT)
    })
  3. 啟動 app_proxy.js 應用程式

node app_proxy.js

執行後,就可以通過 "localhost:1234" 去訪問 "localhost:8080"。

除了 HTTP,該模組還支援 HTTPS 與 WebSocket 的反向代理。

可以使用 apache bench 對其效能做一個簡單的測試。模擬 1000 個使用者,每個使用者併發 100 個請求

ab -n 1000 -c 100 http://localhost:1234

Node.js 與 Nginx 相比效能不差,而且其擴充套件性遠高於 Nginx。我們可以動態指定被代理的目標地址,而 Nginx 中配置的目標地址卻是靜態的。這一點對實現服務發現功能及其重要,因為我們需要從 Service Registry 中獲取需要代理的微服務資訊,並執行反向代理操作,呼叫相應的微服務 REST API。

最後需要說明的是,服務閘道器不僅僅提供反向代理與服務發現特性,此外它還具備安全認證,效能監控,資料快取,請求分片,靜態響應等特性,我們可以根據實際情況擴充套件。

參考

  • 《架構探險—輕量級微服務架構》