Serverless Devs 2.0 开箱测评:Serverless 开发最佳实践
简介: 当下,Serverless 概念很火,很多同学被 Serverless 的优势吸引过来,比如它的弹性伸缩,免运维,高可用,资费少。但真正使用起来去落地的时候发现问题很多,大型项目如何组织函数,性能优化怎么做,怎么做Serverless调试,数据库,共享会话怎么加等等。上周,Serverless Devs 2.0 正式版全新发布。Serverless Devs 2.0 在平台能力、应用模板以及开发者套件方面能力提升。本文以 Serverless Devs 的应用中心(web 版)为案例,来看开箱实践方案。
当下,Serverless 概念很火,很多同学被 Serverless 的优势吸引过来,比如它的弹性伸缩,免运维,高可用,资费少。但真正使用起来去落地的时候发现问题很多,大型项目如何组织函数,性能优化怎么做,怎么做Serverless调试,数据库,共享会话怎么加等等。上周,Serverless Devs 2.0 正式版全新发布。Serverless Devs 2.0 在平台能力、应用模板以及开发者套件方面能力提升。接下来,以 Serverless Devs 的应用中心(web 版)为案例,来看开箱实践方案。
Serverless 函数代码组织
如果想充分利用 Serverless 的能力函数是最佳方案,可以最大程度减少冷启动时间,践行用完即走的理念,保障用户体验的同时,最大程度减少成本,不过对于中大型项目而言,以单函数的方式组织代码,在维护上无疑是一个巨大挑战,可能一个应用会有数百个函数,维护成本极高也极易出错。
最好的方式是用框架的方式组织代码,以函数的方式部署执行。框架组织代码需要做业务的划分,比如电商包含商品,订单,用户等服务,都放到一个框架里面并通过函数去部署执行的话明显太大了。最好就是像微服务一样,独立业务的接口可以在同一个函数中,每一个业务有自己的独立域名,再通过内部路由访问具体的业务服务。
这样做可以最大限度的利用函数能力,并且维护得来相对容易一些。
我们把 Serverless Hub 的应用市场作为一类场景,进行了统一划分,具体的函数调用如下实现(完整的代码目录 git)
const { http } = require('@serverless-devs/dk');
const { searchApp, getAppDetail, getSpecialDetail, getSpecialApp, getCategorys, getTags } = require('./services');
http
.get("/appCenter/getSpecial", async (ctx) => {
const data = await getSpecialApp(ctx);
ctx.body = data;
})
.post("/appCenter/getSpecialDetail", async (ctx, next) => {
const data = await getSpecialDetail(ctx);
ctx.body = data;
})
.post("/appCenter/getAppDetail", async (ctx) => {
const data = await getAppDetail(ctx);
ctx.body = data;
})
.get("/appCenter/getCategory", async (ctx) => {
const data = await getCategorys();
ctx.body = data;
})
.get("/appCenter/getTags", async (ctx) => {
const data = await getTags();
ctx.body = data;
})
.post("/appCenter/getApps", async (ctx) => {
const data = await searchApp(ctx);
ctx.body = data;
})
.get("/", async (ctx, next) => {
let result = "Hello ServerlessDevs";
ctx.body = result;
})
http.app.use(http.routes());
exports.handler = http();
代码使用了 Serverless Devs 提供的 @serverless-devs/dk ,我们对标准的前端框架进行了核心封装,比如 express,koa 等,你可以继续使用习惯的 web 框架进行开发工作,最后通过 s 工具进行函数部署。s.yaml 的配置如下:
edition: 1.0.0 # 命令行YAML规范版本,遵循语义化版本(Semantic Versioning)规范
name: fc-http-demo # 项目名称
access: default # 秘钥别名
vars:
services:
serverlesshub:
component: devsapp/fc # 组件名称
props:
region: cn-hangzhou
service:
name: myserverlesstest
description: demo for fc-http component
internetAccess: true
function:
name: myhub
description: this is a test
runtime: nodejs12
codeUri: ./code
handler: index.handler
memorySize: 128
timeout: 10
triggers:
- name: httpTrigger
type: http
config:
authType: anonymous
methods:
- GET
- POST
customDomains:
- domainName: auto
protocol: HTTP
routeConfigs:
- path: /*
# 函数计算FC组件文档参考地址:https://github.com/devsapp/fc
如果你想再增加一个服务业务,可以水平扩展一个新的服务配置,并且可以用同样的代码包去实现。
性能优化
通常 Serverless 应用的最大耗时都在 冷启动时间上,就以阿里云 FC 为例,如果我们的应用以容器的方式进行部署,冷启动时间会比较长可能是 1 分钟或者更多,即使采用镜像加速也仅能缩短到几十秒以内,所以如果项目不是特别大(AI 类应用的包大小可能会达到 G 级别),都建议以 原生runtime 的方式去做。拿我们上面的 serverless hub 为例就是最终运行到 nodejs12 runtime,冷启动时间 1~2s
热启动则缩短到150ms

对于这类非高频访问的站点而言还是比较适合的,另外你可以根据需要在具体的某个时间点通过添加预留的方式保持高性能的访问效果。
当然,冷启动这块需要云厂商的进一步优化把他做到极致,最终才能真正让 Serverless 完美。
端云调试
调试始终是 Serverless 应用的最棘手的部分,我们开发的应用是在本地,部署的应用是在线上。并且线上的环境跟本地开发环境有着巨大的差异,通常我们只能通过在线打印输出,然后还得通过日志平台查看日志判断问题,再回来本地修改代码,一来一回耗时非常巨大,而且效果也不好。Serverless Devs 提供了自己的解决方案,我们巧妙的设计了一个在线的辅助函数,辅助函数完整复刻线上代码,然后通过本地跟辅助函数建设通道实现本地的代码调试效果
基于这样的能力我们再来看看具体怎么在 Serverless Hub 实施的, 本次演示使用的是Serverless Desktop, 大家可以尝试跟着我的操作步骤进行使用:
1、新建一个Serverless 应用,并把它部署到线上
我们可以通过 Serverless Desktop 的应用市场搜索 xxx 应用模板,然后加载到本地,然后通过可视化配置部分修改相应的服务和函数内容,进行部署。
2、进入工作空间->应用管理->应用详情->端云调试
按照提示准备好前置条件,比如安装docker demon 指定调试端口,启动资源准备,这个时候会创建辅助函数,同时构建 vscode 的 debug 文件。
启动好之后,使用 vscode 打开工程目录,查看debug配置文件.vscode/launch.json
以这个启动 debug 模式
3、发起调用
切换到"本地调试配置"面板,点击"发起调用"
可以发现 vscode 触发调试
调试结束回到 Serverless Desktop 页面,我们可以看到输出效果:
这里我们发起调用是向这个服务的根目录发起,如果我们想向其他的路由地址发起调用该怎么操作呢?我们可以复制发起调用后输出的基础地址。
然后贴到 postman, 再往后拼接上我们的测试路由地址,比如,想访问"/appCenter/getSpecial",可以拼接成"<基础地址>/appCenter/getSpecial"然后"Send"这个请求。


通过这样的方式我们可以深入细节知道每一行代码的调用问题到底出在哪里,极大的提高了我们的开发效率。
4、清空环境
调试结束后不要忘了清楚调试环境,包括关闭本地的容器地址,以及清理线上的函数。
综上我们完成了一次完整的调试过程。
数据库使用
Serverless 一大特色就是他的计费模式:按需按量计费。在数据库存储层面,阿里云推出 Serverless 分布式数据库 Tablestore,和函数计算 FC 是最佳拍档。
1、前提
- 请先到 tablestore 控制台,开通服务
- 使用主账号创建按量付费的实例
- 在实例管理页面获取访问地址以及实例名
2、Initializer 函数
首先让我们先认识下 initializer 函数,initializer 函数能够保证统一实例成功并且仅成功执行一次。这个特性非常适合我们的数据库初始化连接。
const TableStore = require('tablestore');
let internal; // 先定义一个全局变量
exports.initializer = (context, callback) => {
try {
const endpoint = process.env.tablestore_endpoint; // tablestore的连接地址
const instanceName = process.env.tablestore_instanceName;// tablestore实例名
const tableClient = new TableStore.Client({
accessKeyId: context.credentials.accessKeyId,
accessKeySecret: context.credentials.accessKeySecret,
stsToken: context.credentials.securityToken,
endpoint,
instancename: instanceName,
});
internal = { tableClient, TableStore };
callback();
} catch (err) {
callback(err.message);
}
}
3、handler函数
数据库建立连接后,我们就可以在 handler 函数中处理业务逻辑。
const { http } = require('@serverless-devs/dk');
http
// 创建表
.post("/table", async (ctx, next) => {
const { tableName } = ctx.request.body;
const { tableClient } = ctx.req.requestContext.internal;
const params = {
tableMeta: {
tableName,
primaryKey: [
{
name: 'id',
type: 'INTEGER',
},
],
},
reservedThroughput: {
capacityUnit: {
read: 0,
write: 0,
},
},
tableOptions: {
timeToLive: -1, // 数据的过期时间, 单位秒, -1代表永不过期. 假如设置过期时间为一年, 即为 365 * 24 * 3600.
maxVersions: 1, // 保存的最大版本数, 设置为1即代表每列上最多保存一个版本(保存最新的版本).
},
streamSpecification: {
enableStream: true, //开启Stream
expirationTime: 24, //Stream的过期时间,单位是小时,最长为168,设置完以后不能修改
},
};
await tableClient.createTable(params);
ctx.body = {
success: true,
message: `${tableName}表已创建成功`,
}
})
exports.handler = (req, res, context) => {
context.internal = internal;
http()(req, res, context);
};
3、快速体验
1. Serverless Devs 提供 tablestore 组件, 通过一行命令快速体验
$ s init dk-tablestore
2. 本地调试
$ cd code
$ npm install
$ npm run serve
3. 一键部署到函数计算 FC
回到项目根目录(s.yaml平级),执行命令
$ s deploy
原文链接
本文为阿里云原创内容,未经允许不得转载。
Serverless Devs 2.0 开箱测评:Serverless 开发最佳实践的更多相关文章
- [转]Android开发最佳实践
——欢迎转载,请注明出处 http://blog.csdn.net/asce1885 ,未经本人同意请勿用于商业用途,谢谢—— 原文链接:https://github.com/futurice/and ...
- Hadoop MapReduce开发最佳实践(上篇)
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- Web前端开发最佳实践(9):CSS代码太太乱,重复代码太多?你需要精简CSS代码
前言 提高网站整体加载速度的一个重要手段就是提高代码文件的网络传输速度.之前提到过,所有的代码文件都应该是经过压缩了的,这可提高网络传输速度,提高性能.除了压缩代码之外,精简代码也是一种减小代码文件大 ...
- Web前端开发最佳实践(7):使用合理的技术方案来构建小图标
大家都对网站上使用的小图标肯定都不陌生,这些小图标作为网站内容的点缀,增加了网站的美观度,提高了用户体验,可是你有没有看过在这些网站中使用的图标都是用什么技术实现的?虽然大部分网站还是使用普通的图片实 ...
- Android开发最佳实践
Android开发最佳实践 摘要 ●使用 Gradle 和它推荐的工程结构 ●把密码和敏感数据放在gradle.properties ●不要自己写 HTTP 客户端,使用Volley或OkHttp库 ...
- Web前端开发最佳实践(5):正确闭合HTML标签,停止使用不标准的标签和属性
正确闭合HTML标签 HTML元素的内容模型定义了元素的结构,表明元素可以包含哪些内容以及元素可以有哪些属性.元素可以包含的内容包括其他元素和字符,但是也有一些元素是空元素,即不能包含任何内容,这些元 ...
- Fur 是 .NET 5 平台下企业应用开发最佳实践框架。
Fur 是 .NET 5 平台下企业应用开发最佳实践框架. 立即尝鲜 Fur 是基于最新的 .NET 5 RC2 构建,目的是为了尽早体验新功能,对即将到来的 .NET 5 正式版做出最快的响应. 所 ...
- MongoDB开发最佳实践
MongoDB开发最佳实践 连接到MongoDB · 关于驱动程序:总是选择与所用之MongoDB相兼容的驱动程序.这可以很容易地从驱动兼容对照表中查到: · 如果使用第三方框架(如Spring Da ...
- web前端开发最佳实践笔记
一.文章开篇 由于最近也比较忙,一方面是忙着公司的事情,另外一方面也是忙着看书和学习,所以没有时间来和大家一起分享知识,现在好了,终于回归博客园的大家庭了,今天我打算来分享一下关于<web前端开 ...
- 【读书笔记】iOS-微信公众平台开发最佳实践
一,微信是由腾讯公司广州研发中心产品团队开发,该团队经理张小龙被称为“微信之父”,公司总裁马化腾确定该产品名称为“微信”. 二,常见问题及解决方案. 1,请求URL超时. 这种情况一般是由于服务器网速 ...
随机推荐
- 打造餐饮+元宇宙新体验!实时云渲染赋能DQverse未来世界
随着元宇宙的迅猛发展,实体餐饮产业与虚拟元宇宙之间的交汇愈发频繁.诸如海底捞.奈雪的茶.星巴克.王老吉.肯德基等知名餐饮品牌纷纷加大对元宇宙领域的投资与布局. 图源网络 最初只是线上虚拟餐厅的概念,如 ...
- App磁盘沙盒工具实践
目录介绍 01.磁盘沙盒的概述 1.1 项目背景说明 1.2 沙盒作用 1.3 设计目标 02.Android存储概念 2.1 存储划分介绍 2.2 机身内部存储 2.3 机身外部存储 2.4 SD卡 ...
- 记录--手写vm.$mount方法
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.概述 在我们开发中,经常要用到Vue.extend创建出Vue的子类来构造函数,通过new 得到子类的实例,然后通过$mount挂载到 ...
- 记录--微信小程序获取用户信息的最新方法记录
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 微信小程序获取用户信息的几种方式 以下三种方式都无法获取到用户的openID 1. 开放组件获取用户信息<open-data> ...
- verilog之基本结构
verilog语法的基本结构 1.verilog的定义 verilog,一种硬件描述语言,致力于提高数字电路,尤其是大规模数字电路的描述规范.从描述就可以看出,这个语言和C不同,不是高级语言.但是,这 ...
- echarts 中国地图tooltip实现提示框
point: 鼠标位置,如 [20, 40]. params: 同 formatter 的参数相同. dom: tooltip 的 dom 对象. rect: 只有鼠标在图形上时有效,是一个用x, y ...
- ET介绍——强大的MongoBson库
强大的MongoBson库 后端开发,统计了一下大概有这些场景需要用到序列化: 对象通过序列化反序列化clone 服务端数据库存储数据,二进制 分布式服务端,多进程间的消息,二进制 后端日志,文本格式 ...
- #单调队列#JZOJ 1753 锻炼身体
题目 一个\(n*m\)的矩阵,有些格子不能经过,有\(k\)个时段, 要么停留某个格子,要么沿时段规定的方向移动,问最多能够移动多少次 \(n,m,k\leq 200\) 分析 题目已经提示了\(O ...
- Makefile 常用命令详解
在软件开发中,Makefile是一种非常常用的自动化工具.Makefile文件包含了一系列规则,用于编译.打包.测试等操作,可以帮助我们自动化这些操作,提高项目的管理和编译效率.本文将介绍Makefi ...
- SQL 中的运算符与别名:使用示例和语法详解
SQL中的IN运算符 IN运算符允许您在WHERE子句中指定多个值,它是多个OR条件的简写. 示例:获取您自己的SQL Server 返回所有来自'Germany'.'France'或'UK'的客户: ...