您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關如何將 Web 框架遷移到 Serverless,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
Serverless 通常翻譯為「無服務架構」,是一種軟件系統設計架構思想和方法,并不是一個開發框架或者工具。他的出現是為了讓開發者更加關注業務的開發,而將繁雜的運維和部署交給云廠商。Serverless 由 Faas 和 Baas 組成,Faas 為開發者提供業務運算環境,然后與 Baas 提供的數據和存儲服務,進行交互,從而提供與傳統服務一致的體驗。但是由于 Faas 是無狀態的,并且其運行環境是有讀寫限制的,最重要的是它是基于事件觸發的。因此如果傳統 Web 服務想遷移到 Serverless 上,是需要進行相關改造和特殊處理的,為此遷移成本是必不可少的。下面將具體幫助大家剖析下,如何 Serverless 化傳統的 Web 服務。
Web 服務定義:
Web 服務是一種
面向服務的架構
(SOA) 的技術,通過標準的 Web 協議提供服務,目的是保證不同平臺的應用服務可以互操作。
日常生活中,接觸最多的就是基于 HTTP 協議的服務,客戶端發起請求,服務端接受請求,進行計算處理,然后返回響應,簡單示意圖如下:
傳統 Web 服務部署流程:通常需要將項目代碼部署到服務器上,啟動服務進程,監聽服務器的相關端口,然后等待客戶端請求,從而響應返回處理結果。而這個服務進程是常駐的,就算沒有客戶端請求,也會占用相應服務器資源。
一般我們的服務是由高流量和低流量場景交替組成的,但是為了考慮高流量場景,我們需要提供較高的服務器配置和多臺服務進行負載均衡。這就導致服務處在低流量場景時,會多出很多額外的閑置資源,但是購買的資源卻需要按照高流量場景進行付費,這是非常不劃算的。
如果我們的服務能在高流量場景自動擴容,低流量場景自動縮容,并且只在進行計算處理響應時,才進行收費,而空閑時間不占用任何資源,就不需要收費呢?
答案就是 Serverless
。
上面已經提到了 Serverless 的兩個核心特點:按需使用和收費
和 自動擴縮容
。而且近幾年 Serverless 的應用也越來越廣泛,但是它并不是銀彈,任何技術都是有它的適合場景和不適合場景。我們不能因為一項技術的火熱,而盲目的追捧。Serverless 是有它的局限性的,一般 Serverless 適合如下幾種場景:
異步的并發,組件可獨立部署和擴展
應對突發或服務使用量不可預測
無狀態,計算耗時較短服務
請求延時不敏感服務
需要快速開發迭代的業務
如果你的服務不滿足以上條件,筆者是不推薦遷移到 Serverless。
如果你的服務是以上提到的任何話一個場景,那么就可以嘗試遷移到 Serverless 上。
常見的 Serverless HTTP 服務結構圖如下:
那么我們如何將 Web 服務進行遷移呢?
我們知道 Faas (云函數)是基于事件觸發的,也就是云函數被觸發運行時,接收到的是一個 JSON 結構體
,它跟傳統 Web 請求時有區別的,這就是為什么需要額外的改造工作。而改造的工作就是圍繞如何將事件 JSON 結構體轉化成標準的 Web 請求
。
所以 Serverless 化 Web 服務的核心就是需要開發一個 適配層
,來幫我們將觸發事件轉化為標準的 Web 請求。
整個處理流程圖如下:
接下來將介紹如何為 Express 框架開發一個適配層。
首先我們先來看看一個標準的云函數結構:
module.exports.handler = (event, context) => { // do some culculation return res; };
在介紹如何開發一個 Express 的適配層前,我們先來熟悉下 Express 框架。
一個簡單的 Node.js Web 服務如下:
const http = require("http"); const server = http.createServer(function (req, res) { res.end("helloword"); }); server.listen(3000);
Express 就是基于 Node.js 的 Web 框架,而 Express 核心就是 通過中間件的方式,生成一個回調函數
,然后提供給 http.createServer()
方法使用。
Express 核心架構圖如下:
由此可知,我們可以將 Express 框架生成的回調函數,作為 http.createServer()
的參數,來創建可控的 HTTP Server,然后將云函數的 event
對象轉化成一個 request
對象,通過 http.request()
方法發起 HTTP 請求,獲取請求響應,返回給用戶,就可以實現我們想要的結果。
對于 Node.js 的 HTTP Server,可以通過調用 server.listen()
方法來啟動服務,listen()
方法支持多種參數類型,主要有兩種監聽方式 從一個TCP端口啟動監聽
和 從一個UNIX Socket套接字啟動監聽
。
server.listen(port[, hostname][, backlog][, callback])
:從一個TCP端口啟動監聽
server.listen(path, [callback])
:從一個UNIX Domain Socket啟動監聽
服務器創建后,我們可以像下面這樣啟動服務器:
// 從'127.0.0.1'和3000端口開始接收連接 server.listen(3000, '127.0.0.1', () => {}); // 從 UNIX 套接字所在路徑 path 上監聽連接 server.listen('path/to/socket', () => {})
無論是 TCP Socket
還是 Unix Domain Socket
,每個 Socket 都是唯一的。TCP Socket
通過 IP和端口
描述,而 Unix Domain Socket
通過 文件路徑
描述。
TCP 屬于傳輸層的協議,使用 TCP Socket 進行通訊時,需要經過傳輸層 TCP/IP 協議的解析。
而 Unix Domain Socket
可用于不同進程間的通訊和傳遞,使用 Unix Domain Socket
進行通訊時不需要經過傳輸層,也不需要使用 TCP/IP 協議
。所以,理論上講 Unix Domain Socket
具有更好的傳輸效率。
因此這里在設計啟動服務時,采用了 Unix Domain Socket
方式,以便減少函數執行時間,節約成本。
關于 Node.js 如何實現 IPC 通信,這里就不詳細介紹的,感興趣的小伙伴可以深入研究下,這里有個簡單的示例,nodejs-ipc
原理大概介紹清楚了,我們的核心實現代碼需要以下三步:
通過 Node.js HTTP Server 監聽 Unix Domain Socket,啟動服務
function createServer(requestListener, serverListenCallback) { const server = http.createServer(requestListener); server._socketPathSuffix = getRandomString(); server.on("listening", () => { server._isListening = true; if (serverListenCallback) serverListenCallback(); }); server .on("close", () => { server._isListening = false; }) .on("error", (error) => { // ... }); server.listen(`/tmp/server-${server._socketPathSuffix}.sock`) return server; }
將 Serverless Event 對象轉化為 Http 請求
function forwardRequestToNodeServer(server, event, context, resolver) { try { const requestOptions = mapApiGatewayEventToHttpRequest( event, context, getSocketPath(server._socketPathSuffix), ); // make http request to node server const req = http.request(requestOptions, (response) => forwardResponseToApiGateway(server, response, resolver), ); if (event.body) { const body = getEventBody(event); req.write(body); } req .on('error', (error) => // ... ) .end(); } catch (error) { // ... return server; } }
將 HTTP 響應轉化為 API 網關標準數據結構
function forwardResponseToApiGateway(server, response, resolver) { response .on("data", (chunk) => buf.push(chunk)) .on("end", () => { // ... resolver.succeed({ statusCode, body, headers, isBase64Encoded, }); }); }
最后函數的 handler 將異步請求返回就可以了。
如果不想手寫這些適配層代碼,可以直接使用 tencent-serverless-http 模塊。
它使用起來很簡單,創建我們的 Express 應用入口文件 sls.js
:
const express = require("express"); const app = express(); // Routes app.get(`/`, (req, res) => { res.send({ msg: `Hello Express`, }); }); module.exports = app;
然后創建云函數 sl_handler.js
文件:
const { createServer, proxy } = require("tencent-serverless-http"); const app = require("./app"); exports.handler = async (event, context) => { const server = createServer(app); const result = await proxy(server, event, context, "PROMISE").promise; };
接下來,將業務代碼和依賴模塊一起打包部署到云函數就可以了(記得指定 執行方法
為 sl_handler.handler
)。
除了 Express
框架,其他的 Node.js 框架也基本類似,只需要按照要求,exports
一個 HTTP Server
的回調函數就可以。
比如 Koa
,我們拿到初始化的 Koa
應用后,只需要將 app.callback()
作為 createServer()
方法的參數就可以了,如下:
const { createServer, proxy } = require("tencent-serverless-http"); const app = require("./app"); exports.handler = async (event, context) => { // 這里和 Express 略有區別 const server = createServer(app.callback()); const result = await proxy(server, event, context, "PROMISE").promise; };
對于非 Node.js 框架,比如 Python
的 Flask
框架,原理都是一樣的,核心只需要做到 將 Serverless Event 對象轉化為 Http 請求
,就可以了。由于筆者對其他語言不太熟悉,這里就不做深入介紹了,感興趣的小伙伴,可以到 Github 社區搜索下,已經有很多對應的解決方案了,或者自己嘗試手擼也是可以的。
讀到這里,相信你已經清楚,如何將自己的 Node.js 框架遷移到 Serverless 了。但是在這之前,我們都是手動處理的,而且每次都需要自己創建 handler.js
文件,還是不夠方便。
為此開源社區提供了一套優秀的解決方案 Serverless Component,通過組件,我們進行簡單的 yaml
文件配置后,就可以方便的將我們的框架代碼部署到云端。
比如上面提到的 Express
框架,就有對應的組件,我們只需要在項目根目錄下創建 serverless.yml
配置文件:
component: express name: expressDemo inputs: src: ./ region: ap-guangzhou runtime: Nodejs10.15 apigatewayConf: protocols: - https environment: release
然后全局安裝 serverless
命令 npm install serverless -g
之后,執行部署命令即可:
$ serverless deploy
耐心等待幾秒,我們的 Express 應用就成功部署到云端了。
注意:本文 Serverless 服務均基于 騰訊云
部署。
Serverless Express 組件不僅能幫我們快速部署 Express 應用,而且它還提供了 實時日志
和 云端調試
的能力。
只需要在項目目錄下執行 serverless dev
命令,serverless 命令行工具就會自動監聽項目業務代碼的更改,并且實時部署,同時我們可以通過打開 Chrome Devtools 來調試 Express 應用。
以上就是如何將 Web 框架遷移到 Serverless,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。