2019 是 serverless 风行的一年,它以一种全新的架构方式,成为云计算时代的一股革命性力量。本文讲述的 scf 云函数,正是腾讯云对 serverless 架构的具体实现。
SCF是什么
1.定义
先来看一下腾讯云上关于 SCF 和 Serverless 的官方定义:
腾讯云云函数(Serverless Cloud Function,SCF)是腾讯云为企业和开发者们提供的无服务器执行环境,帮助您在无需购买和管理服务器的情况下运行代码, 是实时文件处理和数据处理等场景下理想的计算平台。 您只需使用 SCF 平台支持的语言编写核心代码并设置代码运行的条件,即可在腾讯云基础设施上弹性、安全地运行代码。无服务器(Serverless)不是表示没有服务器,而表示当您在使用 Serverless 时,您无需关心底层资源,也无需登录服务器和优化服务器,只需关注最核心的代码片段,即可跳过复杂的、繁琐的基本工作。核心的代码片段完全由事件或者请求触发,平台根据请求自动平行调整服务资源。Serverless 拥有近乎无限的扩容能力,空闲时,不运行任何资源。代码运行无状态,可以轻易实现快速迭代、极速部署。
简言之,Serverless 是一套软件架构思想,在这套架构下,开发者可以无需考虑服务器资源,只专注在业务代码,而对于服务器的运维,完全由服务商负责。
而云函数(SCF),就是腾讯云对Serverless 的具体实现,它可以让我们做到快速部署和无运维(比如弹性扩缩容)。
2.SCF类型
腾讯云提供了三种类型的云函数:事件,HTTP 和服务。 (1) event scf
配合触发器使用,如定时触发器、COS触发器、CMQ触发器、Kafka触发器、API网关触发器 使用Event数据结构编写函数 打通云间产品,提供数据流转及文件处理能力
我们提交到腾讯云上的云函数,其实是死代码,只有当我们给这个函数绑定了触发器,并且由事件触发时,我们的函数才会被激活。一个事件类型云函数生命周期如下: 触发->启动一个实例->传参(event)->执行->返回结果->30min内不再调用则销毁 (2) http scf
提供原生Web开发体验,使用HTTP Request/Response数据结构编写函数,零学习成本 默认集成域名和SSL证书,方便业务调用和调试 快速搭建Web服务、支持Express、Koa等框架
http scf 可以算是特殊的 event scf,一方面是触发方式为网关触发,另一方面函数传参变为http 报文。 网关触发->启动一个实例->传参(http报文)->执行->返回结果->30min内不再调用则销毁 注:目前该类型的云函数还未开发,只能找腾讯云开白名单。
(3) service scf
通用框架无缝迁移,核心业务直接迁移Serverless架构 默认集成域名和SSL证书,方便业务调用和调试 支持Websocket、微服务、BFF等丰富场景
此类型的函数主要针对微服务,我没有这方面的经验,此次主要分享 event scf。
一个云函数的开发流程
1.开发者工具
对于云函数的开发,腾讯云支持三种开发者工具:Web IDE, Vscode 插件以及 SCF cli。 使用教程可查询文档:cloud.tencent.com/document/pr…
为了后续接入自动化构建工具,推荐使用 cli。
2.云函数调试
目前腾讯云控制台是不支持对云函数断点调试的,所以只能在本地进行断点调试或者在代码中打入 console。
3.Node.js事件循环
在云函数中运行 Node.js 代码时,同样支持异步事件。在入口函数中调用 callback 后,云函数后台会等待事件队列为空后才返回。当然,我们也可以通过关闭事件循环等待,来自行控制函数的返回时机。
官方demo:cloud.tencent.com/document/pr…
开发一个web应用
demo地址:github.com/Best921/scf…
确定项目结构
一个 web scf 项目,一般有两种结构:
1.整个应用部署成一个 scf。
2.以路由维度切分应用:每个 scf = 中间件+通用方法+自身逻辑
如果应用不是十分复杂的化,我其实建议把整个应用部署成一个云函数。一方面是缩小我们切换应用到 idc 和 tke 的成本,另一方面是切分完的应用其实还是一个 web 应用,整个 scf 的体积可能并不会缩减很多。
初始化
scf init --runtime nodejs8.9 --name scf-koa-demo
复制代码
index.js: 函数入口文件
template.yaml: 函数配置文件,可用于修改函数的环境变量,命名空间和超时等配置信息。
具体配置信息:cloud.tencent.com/document/pr…
初始化一个 koa 应用:
// app.js
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
const router = new Router();
app.use(bodyParser());
router.get('/', async (ctx) => {
ctx.body = 'hello zack';
});
router.get('*', async (ctx) => {
ctx.body = 'get 404';
});
router.post('*', async (ctx) => {
ctx.body = 'post 404';
});
app.use(router.routes());
app.use(getEventAndContext);
module.exports = app;
复制代码
接入中间件
由于我们的 web 应用被 scf 包裹,而 scf 拿到的参数是一个 event 结构的对象,我们需要配合中间件,用 event 构造 http 包,再扔给 web 应用。 常用的中间件有 severless plus,serverless-http等。
// index.js
'use strict';
const app = require('./app');
const serverlessplus = require('serverlessplus');
const proxy = serverlessplus.createProxy(app, { framework: 'koa' });
exports.main_handler = (event, context) => {
return proxy.serveRequest(event, context);
}
复制代码
// app.js
const Koa = require('koa');
const Router = require('koa-router');
const { getEventAndContext } = require('serverlessplus/middleware');
const bodyParser = require('koa-bodyparser');
...
复制代码
部署 scf
scf deploy -f
复制代码
配置 api 网关
新建网关服务->新建 api (路径)->绑定 scf ->发布
配置文档: cloud.tencent.com/document/pr…
这里需要注意的是,scf 和网关服务各自都有版本的概念,如果要切换某个网关服务下的路径所绑定的 scf 版本,则需要重新配置该 api 路径,然后发布一个新的网关服务版本。
SCF项目的工作流
1.环境区分
(1)业务代码:环境变量注入 根据环境设置多份 template.yaml 配置文件,注入各自所需的环境变量:
通过 process.env.xxx 读取:
(2)项目部署:命名空间 用命名空间在部署时区分正式环境和测试环境,根据环境设置多份 template.yaml 配置文件,在部署时读取对应的配置,将函数部署到相应的命名空间下。
2.版本管理
如果需要做版本回滚的话,可以切换整个网关服务的版本,或修改对应 api 下绑定的 scf,重发一个网关服务版本。
SCF运维
1.日志排查
在腾讯云控制台,可以查看部署的 scf 的执行日志:
但是,由于 scf 是无状态的,我们其实无法单纯通过 requestId 来查找特定用户的请求。目前的解决方案可能只能通过业务代码打入用户信息,在一定的时间范围内找到对应请求。
2.函数监控和告警
在控制台,可以查看部署的scf的监控信息:
也可以配置相应的告警策略:
压测
以下用 ab 对上文写的 koa demo 做压测:
1.执行:ab –n 100 –c 100
结果:Failed request:31
2.30min内执行:ab –n 100 –c 100
结果:Failed request:0
3.30min内执行:ab –n 200 –c 200
结果:Failed request:99
4.30min内执行:ab –n 200 –c 200
结果:Failed request:103
5.30min内执行:ab –n 300 –c 300
结果:Failed request:200
6.30min内执行:ab –n 400 –c 400
结果:Failed request:300
结论:
默认最大并发数为 100。
无实例保留时,请求失败率很高,而且请求处理时间更长(因为还有函数冷启动的时间: 1183ms-472ms=711ms)。
到函数执行日志查看失败原因,发现是资源限制,目前腾讯云还未给出解释。
腾讯云方面给出的冷启动解决方案:
- 找腾讯云设置最小保留实例
- 通过云函数的timer触发器写个预热脚本,每30min批量请求云函数,保证底层容器不被销毁
- 腾讯云底层有一套算法,能够根据用户以往的调用量,预测之后的可能并发量,提前创建好容器
SCF vs TKE
SCF | TKE | |
同 | 无运维,自动扩缩容 | |
付费方式 | 按调用次数付费 | 按时计费/按量计费 |
扩缩容周期 | 毫秒级 | 分钟级 |
生命周期 | 冷启动,使用完30min后销毁 | 服务起来后进程一直占用 |
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。