阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

如何定制化开发 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:351747

评论

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

训练营第一周作业

Mr冰凉

架构师 - 入学篇

X﹏X

极客大学架构师训练营

食堂就餐系统设计

Glowry

极客大学架构师训练营

架构师训练营-week1-学习总结

晓-Michelle

极客大学架构师训练营

架构师训练营 第一周 作业

CR

极客大学架构师训练营

2020-06-06-食堂就餐卡系统设计

路易斯李李李

第一周学习总结

15359861984

食堂就餐卡系统

chenzt

极客时间架构师训练营 - week1 - 作业1

jjn0703

极客大学架构师训练营

架构师训练营-week1-作业-食堂就餐卡系统架构设计

晓-Michelle

极客大学架构师训练营

第一周作业 食堂就餐卡系统uml图

战峰

第一周总结

chenzt

食堂就餐卡系统设计

陌生人

食堂就餐卡系统

SuperLab

食堂就餐卡系统设计文档

15359861984

架构师训练营 - 第一周作业二

teslə

食堂就餐卡系统设计

王新涵

架构师训练营第一周作业-王韬

W_T

极客大学架构师训练营 作业

架构师训练营第一次作业

曾祥斌

【总结】架构师如何做架构

魔曦

架构 架构师 极客大学架构师训练营

食堂就餐卡系统设计

Geek_5d0795

系统设计 极客大学架构师训练营 就餐卡

食堂就餐卡系统设计

娄江国

极客大学架构师训练营

架构师训练营0期第1周-总结+作业

林毋梦

极客大学架构师训练营

架构师如何做架构(第一周总结)

mh

架构

Week 01-作业一:食堂就餐卡系统设计

dean

假如黑夜来临

zhoo299

随笔 随笔杂谈

week01小结

Geek_196d0f

架构师训练营0期第一周学习总结

王新涵

训练营第一章笔记

Mr冰凉

食堂就餐卡系统设计

极客大学架构师训练营 食堂就餐卡系统设计

架构师训练营- 第一周 - 学习总结

stardust20

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