溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何將 Web 框架遷移到 Serverless

發(fā)布時間:2021-12-01 15:52:18 來源:億速云 閱讀:134 作者:柒染 欄目:云計算

本篇文章給大家分享的是有關(guān)如何將 Web 框架遷移到 Serverless,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

Serverless 通常翻譯為「無服務(wù)架構(gòu)」,是一種軟件系統(tǒng)設(shè)計架構(gòu)思想和方法,并不是一個開發(fā)框架或者工具。他的出現(xiàn)是為了讓開發(fā)者更加關(guān)注業(yè)務(wù)的開發(fā),而將繁雜的運(yùn)維和部署交給云廠商。Serverless 由 Faas 和 Baas 組成,F(xiàn)aas 為開發(fā)者提供業(yè)務(wù)運(yùn)算環(huán)境,然后與 Baas 提供的數(shù)據(jù)和存儲服務(wù),進(jìn)行交互,從而提供與傳統(tǒng)服務(wù)一致的體驗。但是由于 Faas 是無狀態(tài)的,并且其運(yùn)行環(huán)境是有讀寫限制的,最重要的是它是基于事件觸發(fā)的。因此如果傳統(tǒng) Web 服務(wù)想遷移到 Serverless 上,是需要進(jìn)行相關(guān)改造和特殊處理的,為此遷移成本是必不可少的。下面將具體幫助大家剖析下,如何 Serverless 化傳統(tǒng)的 Web 服務(wù)。

傳統(tǒng) Web 服務(wù)特點(diǎn)

Web 服務(wù)定義:

Web 服務(wù)是一種 面向服務(wù)的架構(gòu) (SOA) 的技術(shù),通過標(biāo)準(zhǔn)的 Web 協(xié)議提供服務(wù),目的是保證不同平臺的應(yīng)用服務(wù)可以互操作。

日常生活中,接觸最多的就是基于 HTTP 協(xié)議的服務(wù),客戶端發(fā)起請求,服務(wù)端接受請求,進(jìn)行計算處理,然后返回響應(yīng),簡單示意圖如下:

如何將 Web 框架遷移到 Serverless

傳統(tǒng) Web 服務(wù)部署流程:通常需要將項目代碼部署到服務(wù)器上,啟動服務(wù)進(jìn)程,監(jiān)聽服務(wù)器的相關(guān)端口,然后等待客戶端請求,從而響應(yīng)返回處理結(jié)果。而這個服務(wù)進(jìn)程是常駐的,就算沒有客戶端請求,也會占用相應(yīng)服務(wù)器資源。

一般我們的服務(wù)是由高流量和低流量場景交替組成的,但是為了考慮高流量場景,我們需要提供較高的服務(wù)器配置和多臺服務(wù)進(jìn)行負(fù)載均衡。這就導(dǎo)致服務(wù)處在低流量場景時,會多出很多額外的閑置資源,但是購買的資源卻需要按照高流量場景進(jìn)行付費(fèi),這是非常不劃算的。

如果我們的服務(wù)能在高流量場景自動擴(kuò)容,低流量場景自動縮容,并且只在進(jìn)行計算處理響應(yīng)時,才進(jìn)行收費(fèi),而空閑時間不占用任何資源,就不需要收費(fèi)呢?

答案就是 Serverless。

Serverless 適用場景

上面已經(jīng)提到了 Serverless 的兩個核心特點(diǎn):按需使用和收費(fèi)自動擴(kuò)縮容。而且近幾年 Serverless 的應(yīng)用也越來越廣泛,但是它并不是銀彈,任何技術(shù)都是有它的適合場景和不適合場景。我們不能因為一項技術(shù)的火熱,而盲目的追捧。Serverless 是有它的局限性的,一般 Serverless 適合如下幾種場景:

  1. 異步的并發(fā),組件可獨(dú)立部署和擴(kuò)展

  2. 應(yīng)對突發(fā)或服務(wù)使用量不可預(yù)測

  3. 無狀態(tài),計算耗時較短服務(wù)

  4. 請求延時不敏感服務(wù)

  5. 需要快速開發(fā)迭代的業(yè)務(wù)

如果你的服務(wù)不滿足以上條件,筆者是不推薦遷移到 Serverless。

Web 框架如何遷移到 Serverless

如果你的服務(wù)是以上提到的任何話一個場景,那么就可以嘗試遷移到 Serverless 上。

常見的 Serverless HTTP 服務(wù)結(jié)構(gòu)圖如下:

如何將 Web 框架遷移到 Serverless

那么我們?nèi)绾螌?Web 服務(wù)進(jìn)行遷移呢?

我們知道 Faas (云函數(shù))是基于事件觸發(fā)的,也就是云函數(shù)被觸發(fā)運(yùn)行時,接收到的是一個 JSON 結(jié)構(gòu)體,它跟傳統(tǒng) Web 請求時有區(qū)別的,這就是為什么需要額外的改造工作。而改造的工作就是圍繞如何將事件 JSON 結(jié)構(gòu)體轉(zhuǎn)化成標(biāo)準(zhǔn)的 Web 請求。

所以 Serverless 化 Web 服務(wù)的核心就是需要開發(fā)一個 適配層,來幫我們將觸發(fā)事件轉(zhuǎn)化為標(biāo)準(zhǔn)的 Web 請求。

整個處理流程圖如下:

如何將 Web 框架遷移到 Serverless

接下來將介紹如何為 Express 框架開發(fā)一個適配層。

Serverless Express 適配層開發(fā)

實(shí)現(xiàn)原理

首先我們先來看看一個標(biāo)準(zhǔn)的云函數(shù)結(jié)構(gòu):

module.exports.handler = (event, context) => {
  // do some culculation
  return res;
};

在介紹如何開發(fā)一個 Express 的適配層前,我們先來熟悉下 Express 框架。

一個簡單的 Node.js Web 服務(wù)如下:

const http = require("http");
const server = http.createServer(function (req, res) {
  res.end("helloword");
});
server.listen(3000);

Express 就是基于 Node.js 的 Web 框架,而 Express 核心就是 通過中間件的方式,生成一個回調(diào)函數(shù),然后提供給 http.createServer() 方法使用。

Express 核心架構(gòu)圖如下:

如何將 Web 框架遷移到 Serverless

由此可知,我們可以將 Express 框架生成的回調(diào)函數(shù),作為 http.createServer() 的參數(shù),來創(chuàng)建可控的 HTTP Server,然后將云函數(shù)的 event 對象轉(zhuǎn)化成一個 request 對象,通過 http.request() 方法發(fā)起 HTTP 請求,獲取請求響應(yīng),返回給用戶,就可以實(shí)現(xiàn)我們想要的結(jié)果。

Node.js Server 的監(jiān)聽方式選擇

對于 Node.js 的 HTTP Server,可以通過調(diào)用 server.listen() 方法來啟動服務(wù),listen() 方法支持多種參數(shù)類型,主要有兩種監(jiān)聽方式 從一個TCP端口啟動監(jiān)聽從一個UNIX Socket套接字啟動監(jiān)聽。

  • server.listen(port[, hostname][, backlog][, callback]):從一個TCP端口啟動監(jiān)聽

  • server.listen(path, [callback]):從一個UNIX Domain Socket啟動監(jiān)聽

服務(wù)器創(chuàng)建后,我們可以像下面這樣啟動服務(wù)器:

// 從'127.0.0.1'和3000端口開始接收連接
server.listen(3000, '127.0.0.1', () => {});
// 從 UNIX 套接字所在路徑 path 上監(jiān)聽連接
server.listen('path/to/socket', () => {})

無論是 TCP Socket 還是 Unix Domain Socket,每個 Socket 都是唯一的。TCP Socket 通過 IP和端口 描述,而 Unix Domain Socket 通過 文件路徑 描述。

TCP 屬于傳輸層的協(xié)議,使用 TCP Socket 進(jìn)行通訊時,需要經(jīng)過傳輸層 TCP/IP 協(xié)議的解析。

Unix Domain Socket 可用于不同進(jìn)程間的通訊和傳遞,使用 Unix Domain Socket 進(jìn)行通訊時不需要經(jīng)過傳輸層,也不需要使用 TCP/IP 協(xié)議。所以,理論上講 Unix Domain Socket 具有更好的傳輸效率。

因此這里在設(shè)計啟動服務(wù)時,采用了 Unix Domain Socket 方式,以便減少函數(shù)執(zhí)行時間,節(jié)約成本。

關(guān)于 Node.js 如何實(shí)現(xiàn) IPC 通信,這里就不詳細(xì)介紹的,感興趣的小伙伴可以深入研究下,這里有個簡單的示例,nodejs-ipc

代碼實(shí)現(xiàn)

原理大概介紹清楚了,我們的核心實(shí)現(xiàn)代碼需要以下三步:

  1. 通過 Node.js HTTP Server 監(jiān)聽 Unix Domain Socket,啟動服務(wù)

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;
}
  1. 將 Serverless Event 對象轉(zhuǎn)化為 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;
  }
}
  1. 將 HTTP 響應(yīng)轉(zhuǎn)化為 API 網(wǎng)關(guān)標(biāo)準(zhǔn)數(shù)據(jù)結(jié)構(gòu)

function forwardResponseToApiGateway(server, response, resolver) {
  response
    .on("data", (chunk) => buf.push(chunk))
    .on("end", () => {
      // ...
      resolver.succeed({
        statusCode,
        body,
        headers,
        isBase64Encoded,
      });
    });
}

最后函數(shù)的 handler 將異步請求返回就可以了。

借助 tencent-serverless-http 庫實(shí)現(xiàn)

如果不想手寫這些適配層代碼,可以直接使用 tencent-serverless-http 模塊。

它使用起來很簡單,創(chuàng)建我們的 Express 應(yīng)用入口文件 sls.js

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

// Routes
app.get(`/`, (req, res) => {
  res.send({
    msg: `Hello Express`,
  });
});

module.exports = app;

然后創(chuàng)建云函數(shù) 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;
};

接下來,將業(yè)務(wù)代碼和依賴模塊一起打包部署到云函數(shù)就可以了(記得指定 執(zhí)行方法sl_handler.handler )。

其他 Node.js 框架

除了 Express 框架,其他的 Node.js 框架也基本類似,只需要按照要求,exports 一個 HTTP Server 的回調(diào)函數(shù)就可以。

比如 Koa,我們拿到初始化的 Koa 應(yīng)用后,只需要將 app.callback() 作為 createServer() 方法的參數(shù)就可以了,如下:

const { createServer, proxy } = require("tencent-serverless-http");
const app = require("./app");

exports.handler = async (event, context) => {
  // 這里和 Express 略有區(qū)別
  const server = createServer(app.callback());
  const result = await proxy(server, event, context, "PROMISE").promise;
};

其他語言框架

對于非 Node.js 框架,比如 PythonFlask 框架,原理都是一樣的,核心只需要做到 將 Serverless Event 對象轉(zhuǎn)化為 Http 請求,就可以了。由于筆者對其他語言不太熟悉,這里就不做深入介紹了,感興趣的小伙伴,可以到 Github 社區(qū)搜索下,已經(jīng)有很多對應(yīng)的解決方案了,或者自己嘗試手?jǐn)]也是可以的。

使用 Serverless Components 快速部署 Web 框架

讀到這里,相信你已經(jīng)清楚,如何將自己的 Node.js 框架遷移到 Serverless 了。但是在這之前,我們都是手動處理的,而且每次都需要自己創(chuàng)建 handler.js 文件,還是不夠方便。

為此開源社區(qū)提供了一套優(yōu)秀的解決方案 Serverless Component,通過組件,我們進(jìn)行簡單的 yaml 文件配置后,就可以方便的將我們的框架代碼部署到云端。

比如上面提到的 Express 框架,就有對應(yīng)的組件,我們只需要在項目根目錄下創(chuàng)建 serverless.yml 配置文件:

component: express
name: expressDemo

inputs:
  src: ./
  region: ap-guangzhou
  runtime: Nodejs10.15
  apigatewayConf:
    protocols:
      - https
    environment: release

然后全局安裝 serverless 命令 npm install serverless -g 之后,執(zhí)行部署命令即可:

$ serverless deploy

耐心等待幾秒,我們的 Express 應(yīng)用就成功部署到云端了。

注意:本文 Serverless 服務(wù)均基于 騰訊云 部署。

Serverless Express 組件不僅能幫我們快速部署 Express 應(yīng)用,而且它還提供了 實(shí)時日志云端調(diào)試 的能力。

只需要在項目目錄下執(zhí)行 serverless dev 命令,serverless 命令行工具就會自動監(jiān)聽項目業(yè)務(wù)代碼的更改,并且實(shí)時部署,同時我們可以通過打開 Chrome Devtools 來調(diào)試 Express 應(yīng)用。


以上就是如何將 Web 框架遷移到 Serverless,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI