阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

如何定制化开发 Serverless Framework 的 Component ?

  • 2020-08-09
  • 本文字数:2642 字

    阅读完需:约 9 分钟

如何定制化开发Serverless Framework的Component ?

在使用 Serverless Framework 开发者工具时,无论是哪家云计算运营商与社区都会提供很多组件供我们选择。虽然这些组件可以在一定程度上解决绝大部分问题,但是在某些时候,我们还可能存在一些定制化需求,那么这个时候可能就需要我们自己来定制化开发 Component。

开发一个全局变量组件

Serverless Framework Plugin 是可以设置全局变量,在之后的一些引用中可以直接使用全局变量。但是在 Component 中没有全局变量的概念,这就导致一个问题:如果有多个函数,每个函数都有数据库的配置,难道是要把数据库的配置写多次吗?


有人说,不用写多次,我们完全可以使用.env来解决这个问题。例如,在每个函数中通过include引入某个未知的.env,将一些配置信息放到这里,就可以解决这个问题。


但是这会引发新的问题,如果有多个.env文件怎么处理?例如,有一个.env.test,还有一个.evn.dev,那么是要批量替换这个引入的文件,还是修改文件名?所以,在稍微复杂一点的环境中,还是需要一个全局变量来控制一些事情。


通过实现一个 Component 来解决全局变量问题,解决全局变量问题再与.env方案结合,我认为是在生产中获得更大便利的最优解:


  • 首先第一步,需要明确组件具体功能:


实现一个全局组件,用户可以配置全局信息,之后的项目可以以直接引用,如果有修改,直接修改全局变量的配置就好。


  • 接下来明确yaml的结构:


这个结构相对来说就很自由了,我的设想是:


GlobalComponent:  component: 'serverless-global'  inputs:    key: value
复制代码


其中,组件名称是serverless-global,组件的字段可以自定义,主要就是key-value形式。


  • 然后是针对功能和yaml定义动作,主要动作是,在程序执行时,将用户定义的key-value完整输出,这样用户就可以在其他组件中引用,例如:


GlobalComponent:  component: 'serverless-global'  inputs:    region: ap-beijing    ScfComponent_1:  component: '@serverless/tencent-scf'  inputs:    region: ${GlobalComponent.region}    ScfComponent_2:  component: '@serverless/tencent-scf'  inputs:    region: ${GlobalComponent.region}
复制代码


  • 最后就是项目的开发。


一个标准的 Serverless Component 格式是这样的:


// serverless.jsconst { Component } = require('@serverless/core')class MyComponent extends Component {  /*   * default (必须) : 执行命令 `$ serverless` 会运行此函数   */  async default(inputs = {}) {    return {}  }
/* * remove (可选) : 执行命令 `$ serverless remove` 会运行此函数, 如果在default中保存了状态,那么此处也必须要存在,否则会报错 */ async remove(inputs = {}) { return {} }
/* * others (可选):其他功能 */ async others(inputs = {}) { return {} }}module.exports = MyComponent
复制代码


对于 GlobalComponent 而言,是不是只需要把用户的输入内容(input),输出就好?


全局变量组件第一个版本的代码如下:


// serverless.jsconst { Component } = require('@serverless/core')class GlobalComponent extends Component { async default(inputs = {}) {   return inputs }}module.exports = GlobalComponent
复制代码


由于在实际生产中,全局变量组件可能会有一些额外用法,例如是否可以在全局变量组件中直接引入某些 Yaml 等操作?…



这种做法是比较常见的,因为可能存在多套配置,完全可以在这里进行不同配置文件的引入。


我们可以对上面的代码进行进一步完善:


// serverless.jsconst { Component } = require('@serverless/core')const yamljs = require('yamljs')
class GlobalComponent extends Component { async getOutput(inputs = {}, output) { const reg = /\${file\(.*?\)}/g for (const key in inputs) { const regResult = reg.exec(inputs[key]) if (regResult) { const inputPath = inputs[key].slice(7, -2) // const file = inputPath[0] == '/' ? inputPath : path.join(process.cwd(), inputPath) const yaml = yamljs.load(inputPath) const jsonStr = JSON.stringify(yaml) const jsonTemp = JSON.parse(jsonStr, null) if (jsonTemp) { output[key] = await this.getOutput(jsonTemp, {}) } } else { output[key] = inputs[key] } } return output }
async default(inputs = {}) { const output = {} await this.getOutput(inputs, output) return output }}
module.exports = GlobalComponent

复制代码


至此,我们就完成了一个全局变量组件的开发。


  • 当然除了上面说的这种简单组件,在开发过程中,我们还会有一些其它需要注意的点:


  1. Serverless Framework Component 是会生成一个缓存目录.serverless,这个缓存文件怎么来的?


this.state = {}await this.save()
复制代码


可以通过上面的方法,将需要缓存的内容放入{}中,进行缓存。


  • 如何引用其他组件?


const othersComponent = await this.load('@serverless/tencent-scf', 'scf-component');
复制代码


这其中有两个参数,一个是组件的名字:@serverless/tencent-scf,另一个是本次引用的名字:scf-component,本次引用的名字怎么理解?其实就是这样,在缓存目录会生成很多组件,例如:



这是部署一个 express 之后生成的缓存目录,这里面可以看到有文件叫这个名字:Template.express.TencentFramework.apigateway.ap-guangzhou-apigateway


针对这条记录而言,其引用层为:


tencent-express 组件->tencent-framework->tencent-apigateway-mutil-region->tencent-apigateway


那么每段含义:


Template: 此处是一个统一的开头


express: 这个组件在 Yaml 中的名字



TencentFramework: 在 tencent-express 引用了 tencent-framework 时候,给本次引用的名字(可以不填写,不填写会默认)


apigateway: 在 tencent-framework 引用了 tencent-apigateway-mutil-region 时,给它的本次引用的名字(可以不填写,不填写会默认)


ap-guangzhou-apigateway: 在 tencent-apigateway-mutil-region 引用了 tencent-apigateway 时,给它的本次引用的名字(可以不填写,不填写会默认)


这样做的目的是为了让我们在进行移除等操作时,可以更好的找到资源信息。

总结

正如文章开始所说,我们在做一个项目的时候,社区和官方提供给我们的能力基本是通用的,可能无法很好地满足定制化需求,那么这个时候,我们就可以通过文中的方法开发出自己的组件。


当然有些时候,官方或者社区没有提供某种组件,我们也可以开发,成为一个贡献者。


2020-08-09 23:351749

评论

发布
暂无评论
发现更多内容

分布式数据库TiDB在百融云创的探索与实践

TiDB 社区干货传送门

实践案例

回顾下Hackathon中的TiCheck

TiDB 社区干货传送门

实践案例

TiDB监控Prometheus磁盘内存问题

TiDB 社区干货传送门

故障排查/诊断

伴鱼数据库之MongoDB数据在线迁移到TiDB

TiDB 社区干货传送门

Dumpling 导出表内并发优化

TiDB 社区干货传送门

性能调优 TiDB 底层架构 备份 & 恢复

TiDB 社区专栏:让技术人员成为更好的读者/作家

TiDB 社区干货传送门

新版本/特性发布 新版本/特性解读

Ti-Click:通过浏览器快速搭建 TiDB 在线实验室 | Ti-可立刻团队访谈

TiDB 社区干货传送门

DM 分库分表 DDL “悲观协调” 模式介绍

TiDB 社区干货传送门

迁移 TiDB 底层架构

DBA之伤-truncate/drop

TiDB 社区干货传送门

关于TiDB数据脱敏的一些想法

TiDB 社区干货传送门

实践案例

TiDB学习之路

TiDB 社区干货传送门

实践案例

专栏技术文章发布指南&奖励

TiDB 社区干货传送门

社区活动

有关 TiDB 升级的二三事——教你如何快乐升级

TiDB 社区干货传送门

版本升级

x86和ARM混合部署下的两地三中心方案验证

TiDB 社区干货传送门

实践案例

TiDB如何修改alter-primary-key参数

TiDB 社区干货传送门

备份的 “算子下推”:TiDB BR 简介

TiDB 社区干货传送门

TiDB 底层架构 备份 & 恢复

在TiDB中实现一个关键字——Parser篇

TiDB 社区干货传送门

TiDB 底层架构

大量 SET autocommit 导致的 TiDB Server CPU 高案例

TiDB 社区干货传送门

故障排查/诊断

Flink 最佳实践之使用 Canal 同步 MySQL 数据至 TiDB

TiDB 社区干货传送门

使用DM迁移MySQL数据到TIDB小测试

TiDB 社区干货传送门

TIDB调优小结

TiDB 社区干货传送门

TiKV源码略读-Config

TiDB 社区干货传送门

关于我作为前端报名 TiDB Hackthon 2021 然后被毫无悬念地淘汰这档事

TiDB 社区干货传送门

TiDB架构浅析

TiDB 社区干货传送门

TiDB 底层架构

5分钟搞定 MySQL 到 TiDB 的数据同步

TiDB 社区干货传送门

实践案例

DM 分库分表 DDL “乐观协调”模式介绍

TiDB 社区干货传送门

迁移 TiDB 底层架构

TiDB4PG 之兼容 Gitlab

TiDB 社区干货传送门

使用 KubeSphere 快速部署 Chaos Mesh

TiDB 社区干货传送门

集群管理 安装 & 部署

发生即看见,一切可回溯 | TiDB 故障诊断与性能排查探讨

TiDB 社区干货传送门

监控 故障排查/诊断

带着问题读 TiDB 源码:Power BI Desktop 以 MySQL 驱动连接 TiDB 报错

TiDB 社区干货传送门

故障排查/诊断 TiDB 源码解读

PlacementRules in SQL 初试

TiDB 社区干货传送门

如何定制化开发Serverless Framework的Component ?_服务革新_刘宇_InfoQ精选文章