Serverless 通常翻译为「无服务架构」,是一种软件系统设计架构思维和办法,并不是一个开发框架或者工具。他的呈现是为了让开发者更加关注业务的开发,而将繁冗的运维和部署交给云厂商。Serverless 由 Faas 和 Baas 组成,Faas 为开发者提供业务运算环境,而后与 Baas 提供的数据和存储服务,进行交互,从而提供与传统服务统一的体验。然而因为 Faas 是无状态的,并且其运行环境是有读写限度的,最重要的是它是基于事件触发的。因而如果传统 Web 服务想迁徙到 Serverless 上,是须要进行相干革新和非凡解决的,为此迁徙老本是必不可少的。本文将具体帮忙大家分析下,如何 Serverless 化传统的 Web 服务。
读完本文将理解到:
- 传统 Web 服务特点
- Serverless 实用场景
- Web 框架如何迁徙到 Serverless
- 应用 Serverless Components 疾速部署 Web 框架
传统 Web 服务特点
Web 服务定义:
Web 服务是一种
面向服务的架构
(SOA) 的技术,通过规范的 Web 协定提供服务,目标是保障不同平台的应用服务能够互操作。
日常生活中,接触最多的就是基于 HTTP 协定的服务,客户端发动申请,服务端承受申请,进行计算解决,而后返回响应,简略示意图如下:
传统 Web 服务部署流程:通常须要将我的项目代码部署到服务器上,启动服务过程,监听服务器的相干端口,而后期待客户端申请,从而响应返回处理结果。而这个服务过程是常驻的,就算没有客户端申请,也会占用相应服务器资源。
个别咱们的服务是由高流量和低流量场景交替组成的,然而为了思考高流量场景,咱们须要提供较高的服务器配置和多台服务进行负载平衡。这就导致服务处在低流量场景时,会多出很多额定的闲置资源,然而购买的资源却须要依照高流量场景进行付费,这是十分不划算的。
如果咱们的服务能在高流量场景主动扩容,低流量场景主动缩容,并且只在进行计算解决响应时,才进行免费,而闲暇工夫不占用任何资源,就不须要免费呢?
答案就是 Serverless
。
Serverless 实用场景
下面曾经提到了 Serverless 的两个外围特点:按需应用和免费
和 主动扩缩容
。而且近几年 Serverless 的利用也越来越宽泛,然而它并不是银弹,任何技术都是有它的适宜场景和不适宜场景。咱们不能因为一项技术的炽热,而自觉的追捧。Serverless 是有它的局限性的,个别 Serverless 适宜如下几种场景:
- 异步的并发,组件可独立部署和扩大
- 应答突发或服务使用量不可预测
- 无状态,计算耗时较短服务
- 申请延时不敏感服务
- 须要疾速开发迭代的业务
如果你的服务不满足以上条件,笔者是不举荐迁徙到 Serverless。
Web 框架如何迁徙到 Serverless
如果你的服务是以上提到的任何话一个场景,那么就能够尝试迁徙到 Serverless 上。
常见的 Serverless HTTP 服务结构图如下:
那么咱们如何将 Web 服务进行迁徙呢?
咱们晓得 Faas(云函数)是基于事件触发的,也就是云函数被触发运行时,接管到的是一个 JSON 构造体
,它跟传统 Web 申请时有区别的,这就是为什么须要额定的革新工作。而革新的工作就是围绕 如何将事件 JSON 构造体转化成规范的 Web 申请
。
所以 Serverless 化 Web 服务的外围就是须要开发一个 适配层
,来帮咱们将触发事件转化为规范的 Web 申请。
整个解决流程图如下:
接下来将介绍如何为 Express 框架开发一个适配层。
Serverless 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 Server 的监听形式抉择
对于 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 库实现
如果不想手写这些适配层代码,能够间接应用 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
)。
其余 Node.js 框架
除了 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 社区搜寻下,曾经有很多对应的解决方案了,或者本人尝试手撸也是能够的。
应用 Serverless Components 疾速部署 Web 框架
读到这里,置信你曾经分明,如何将本人的 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 利用就胜利部署到云端了。更多详细信息,请参考 Express 官网文档
留神:本文 Serverless 服务均基于
腾讯云
部署。
Serverless Express 组件不仅能帮咱们疾速部署 Express 利用,而且它还提供了 实时日志
和 云端调试
的能力。
只须要在我的项目目录下执行 serverless dev
命令,serverless 命令行工具就会主动监听我的项目业务代码的更改,并且实时部署,同时咱们能够通过关上 Chrome Devtools 来调试 Express 利用。
对于云端调试,腾讯云 Serverless Framework 正式发布公告 中有具体的介绍,并且有视频演示。
而且除了 Express 组件,还反对:Koa.js,Egg.js,Next.js,Nuxt.js…..
发现更多组件
最初
当然 Serverless 化 Web 服务并没有本文介绍的那么简略,比方文件读写,服务日志存储,Cookie/Session
存储等 …… 理论开发中,咱们还会面临各种未知的坑,然而比起艰难,Serverless 带给咱们的收益是值得去尝试的。当然传统 Web 服务真的适宜迁徙到 Serverless 架构上,也是值得咱们去思考的问题,毕竟现有的 Web 框架都是面向传统 Web 服务开发实现的(举荐浏览 利与弊 - 传统框架要不要部署在 Serverless 架构上)。然而笔者置信,很快就会呈现一个专门为 Serverless 而生的 Web 框架,能够帮忙咱们更好地基于 Serverless 开发利用 ~
One More Thing
3 秒你能做什么?喝一口水,看一封邮件,还是 —— 部署一个残缺的 Serverless 利用?
复制链接至 PC 浏览器拜访:https://serverless.cloud.tenc…
3 秒极速部署,立刻体验史上最快的 Serverless HTTP 实战开发!
传送门:
- GitHub: github.com/serverless
- 官网:serverless.com
欢送拜访:Serverless 中文网,您能够在 最佳实际 里体验更多对于 Serverless 利用的开发!
举荐浏览:《Serverless 架构:从原理、设计到我的项目实战》