使用 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 應用程式而開發的,非常適合為了滿足實時性較強且併發量較大的應用場景。
I/O 密集型 web 應用
應用程式分為兩大類
- CPU 密集型應用
- 對 CPU 要求較高,需要一個強大的計算過程
- 如股票交易系統,資料分析系統等
- I/O 密集型應用
- 常常有頻繁的網路傳輸或磁碟儲存現象
- 如高併發網站,實時 Web 系統等
Express 是一個非常優秀的 web 框架
- CPU 密集型應用
Web 聊天室 Socket.IO
命令列工具
可以寫一段 Node.js 程式,通過 NPM 的命令將其安裝到作業系統中,隨時在命令列控制檯輸入該命令執行。
Commander.js
基於 Node.js 的前端開發工具如下 Bower, Grunt, Gulp, Webpack, Yeoman
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 類似。
反向代理的應用場景有
- 使靜態資源與動態資源分離
- 實現 AJAX 跨域訪問
- 搭建統一服務閘道器介面
使用 Node.js 實現反向代理
Node.js 搭建反向代理伺服器,需要下面 3 步
使用如下命令安裝 HTTP Proxy 模組
npm install http-proxy
使用 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) })
啟動 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。
最後需要說明的是,服務閘道器不僅僅提供反向代理與服務發現特性,此外它還具備安全認證,效能監控,資料快取,請求分片,靜態響應等特性,我們可以根據實際情況擴充套件。
參考
- 《架構探險—輕量級微服務架構》