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后销毁 服务起来后进程一直占用

Zack921
0 声望1 粉丝

一个前端。