开发者学堂课程【Serverless 技术进阶:让Serverless应用开发更简单】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/995/detail/15073
让Serverless应用开发更简单
内容介绍:
一、Serverless Devs知识点讲解
二、Serverless Devs与CICD实战
三、常见开发问题与解惑
四、演示
一、Serverless Devs知识点讲解
1、Serverless Devs知识点讲解
一般情况下我们使用一个软件的时候我们需要做些什么,假如我们想使用钉钉这个软件或者下载淘宝这样的软件,通常情况下,第一步是下载这个软件,之后安装、账号配置,然后再进行上手实践。Serverless Devs工具也是这样的过程,它的第一步也是下载安装工具,然后进行账号配置,最后上手实践。
在工具安装时,因为Serverless Devs依赖的是Node.js,所以在下载安装之前要先安装Node.js环境。
密钥的配置,配置方案如下:
• 通过config进行配置,选择云厂商,添加密钥,之后还会让命名一个别名,这是因为要进行多密钥的管理或者是多账号的管理,所以提出了一个叫Alias的概念。
• 通过环境变量进行配置
密钥的使用流程:通过命令行指定密钥——Yaml指定——最后兜底(默认密钥)
Serverless Devs本身是通过Yaml进行资源描述的,例如部署网站应用,需要描述以下几个方面:第一是要把密钥部署在哪里,要有具体的描述,告诉用哪个密钥进行部署,包括部署时的一些属性等等。所以在yaml里我们可以看到很多内容,例如,部署当前业务需要哪些密钥、region信息等等.
一般情况下,一个Serverless Devs Yaml可以做哪些事情?
• 描述一个应用
大家可以认为一个完整的yaml描述的是当前ai model应用的完整信息
• 使用变量进行配置
具有变量内容,从环境变量取一个环境变量当做属性,除此之外,还可以通过外部文件引入的方式当其属性。
• 进行组件的编排
如果想将应用部署到线上,应该有两部分,一是website要部署上去,二是ai model部署上去。但是实际不一定按照这个顺序,在website里面有个url,它引用了ai model.output.url,它引用的是下面组件的输出结果,引用的可能会有url的属性。这时,Serverless Devs工具会先分析,之后会先部署下面的应用,部署之后得到结果,然后再部署上面的服务。所以一个Serverless Devs Yaml不仅可以描述一个应用,通过使用变量进行配置,还有一定的编排能力。
• 进行行为的描述
Serverless Devs Yaml与命令行工具搭配起来可以做:
•部署全量的服务
•单独部署某个服务
•跳过Action直接部署项目
edition: 1.8.8 # 命令行YAML
name: framework #项目名称
access: "default" # 密钥别名
services:
website-f: # 业务名
component: oss # 组件名称
props:#组件的属性值
region: cn-beijing
bucket: hello-world
website-b: # 业务名
component: fc # 组件名称
props:# 组件的属性值
region: cn-beijing
service:
name: hello-world
function:
name:hello-world-1
webs1te-c: w公
component: fc # 组件名称
props: # 组件的属性值
region: cn-beijing
service:
name: hello-world
function:
name: hello-world-2l
蓝色部分,表示的是,加载了红色部分提示的组件之后这个组件所需要的属性,一般情况下只有这个属性里面的东西和线上资源是相关的,例如: 业务名website-b里面的props中service/name是hello-world那么部署到线上的函数所处的服务名就是hello-world
以上是对Serverless Devs的基本解读
另外需要注意的是:
1.如果执行s+命令,意味着当前services下面的每个业务都做这个操作,例如s deploy,系统就会分别吧website-f、website-b、website-c等业务部署上线;如果执行s+业务名+命令,系统则会单独处理某个业务,例如s website-f deploy系统则会只部署website-f
2.Serverless Devs规定,一个Yaml表示一个应用,每个应用由多个业务/服务组成,每个服务可以是不同的云厂商提供的不同的云产品,例如左侧就是,framework应用有三个业务,分别是一个对象存储,两个函数
对Yaml灵活程度的总结
①灵活的变量引入:获取环境变量: ${env(环境变量)}
获取外部文档的变量: ${file(路径)}
获取全局变量:${vars.*}
获取其他项目的变量:${project.props.*}
获取其他项目的结果:${project.output.*}
获取当前配置的config变量: ${config(AccountlD)}
如果Yaml里不像配置密钥信息,但可能要把密钥信息放在环境变量里部署到线上,这时可以在环境变量里把密钥配置好,使用时通过config就可以将密钥信息引用过来。
获取当前模块的信息: $ {this.xx}
②有趣的Action加持:支持纯粹的Hook/钩子;支持组件的直接引用(比如component、plugin);·支持插件的使用;
③多用处的模板继承:避免重复配置,可以通过继承的形式获得其他的Yaml并进行修改升级;在多环境下,多项目管理的过程中有巨大意义。
一般情况下,开发环境和生产环境大部分配置都是一致的,例如说函数的超时时间,函数的触发器名字都是一样的,区别可能就是一个Service name,一个不同的VPC,可能就一两个内容变化,但是会导致一百多行的配置,如果两个配置不一样或者需要复制就会很麻烦,通过模板继承地能力可以大大解决负担。
2、Serverless Devs的快速使用的案例
初始化一个Python3的内容,快速的进行一些确定,之后会看到有一个引导,告诉我们已经完成了初始化以及可以做哪些事情
You could [cd/Users/jiangyu/demo/start-fc-http-pyt
hon3] and enjoy your serverless journey!
If you need help for this example,you can use [s -h] after you enter folder.
开启项目之后,可以直接进行一个deploy,快速开始一个Serverless Devs的一个项目,整个过程只有40秒钟,体现了Serverless从0到1的一个过程。
3、安全发布的过程
安全发布也是一个非常重要的内容,下面我们来具体讲述相关内容。
问题:如果我在我的本地将函数发布在线上,我的合作伙伴也发布这个函数,会把我的应用覆盖掉吗?
这个需要合作伙伴在发布的时候要有个非常标准及严格的过程,能告知本人应用是不是发生了变化。例如我在线上进行一些修改,修改一些配置,之后再进行部署,这个部署就和之前的部署不同,可以认为我在本地部署,有人通过控制台进行了更新,当我再次在本地部署时,效果是会给一个提醒,告诉我们memory size等发生变化。当然,也可以通过s plan的命令查看我们有哪些内容发生了变化,例如配置发生变化。也可以通过s deploy的命令进行快速部署,完成部署之后,可以刷新查看刚才的部署是否生效,而且在更新应用时会给予提醒。
问题:如果上次是本人用工具进行部署,这次又是本人在本地用工具进行部署,是不是本人要更新也会有提醒发生了变化?
通过计划发布时是可以看到变化的,但是通过s deploy的时候它不会提醒你,因为前后是自己操作的,系统会自动默认是你自己发的行为,以上就是安全发布的过程。
4、可观测性
If you need English case , you can refer to [s_en.yaml] file
例如我对s.yaml进行修改,增加Log config参数,再对其进行部署,因为Log config可能会配置许多东西,所以用auto进行填写,再重新部署一遍,部署完成之后,通过logs命令直接在本地进行日志的查看。
一般情况下,查看函数的日志要去控制台查看,打开一个网页,不断地刷新这个网页。如果不是一个函数要查,可能需要再不同的控制台直接来回切换,这就非常麻烦。如果有工具,通过工具我们就可以直接在本地查看日志,除了日志,还可以通过mattress命令查看当前函数有哪些指标信息,例如执行h-matrix之后,地址会反馈回来,通过地址就可以看到一些指标的信息。
5、Serverless Devs的其他功能
构建&部署 |
可观测性 |
调用&调试 |
发布&配置 |
其他功能 |
部署deploy |
指标查询metric |
本地调用local |
版本version |
硬盘挂载nas |
构建build |
日志查询logs |
函数触发invoke |
别名alias |
Fun项目迁移fun2s |
移除remove |
|
端云联调Proxied |
预留provision |
查看函数info |
计划变更plan |
|
实例登录instance |
按量资源ondemand |
资源同步symc |
|
|
内存&并发度探测eval |
层layer |
压测stress |
|
|
|
|
API调用api |
举例:在代码开发时会有代码的VPC环境,在本地如何能连到VPC环境进行调试,这时就需要用端云联调。
如果线上函数出问题,想要登录到函数里面进行调试,可以使用实例登录instance这样的命令进行调试。
在使用的时候,可能会设置一些依赖,在设置依赖时就可以用build命令。
二、Serverless Devs与CICD实战
Serverless Devs并没有做CICD的能力,指的是没有能力做一套CICD的平台。可以认为Serverless Devs有非常良好的被集成性,它可以很好地被市面上任何一个CICD的平台快速的集成,而整个集成的过程只有两步:(1)下载工具(2)配置工具
举个简单的例子:get up action
虽然我们没有能力做一套CICD的平台,但是可以和任何平台进行集成,这里需要声明一个东西:run:npm install、run:npm-g @serverless-devs/s,之后再配置工具内容,完成之后,就可以直接使用s命令来做s部署、s build等。
思考题:Actions是不是也可以认为是一种流水线,有了它可以更快速的和其他CICD平台集成
例子:假如大家想要在阿里云的云校上面做流水线的事情,大家可能是需要通过拖拽的方式在每个模块里写上流程。现在我们不用云校的流水线,要把它迁到GitHub Action上面,这就意味着所有流程要重新写,如果有Serverless Devs Actions的能力,就可以将流水线的流程编排到s.yaml上,然后可以直接通过deploy在不同的流水线快速的做集成。
除此之外,还有一些重要的点。
我们会有密钥信息,账号密码,不方便放在s.yaml的流水线上,这个时候可以将所有东西放进环境变量了,可以引用环境变量,相对来说内容可以发出去,s.yaml里的个人信息也没有暴露,相对是一种可靠的做法。
三、常见开发问题与解惑
第一个问题是Serverless架构下如何上传文件更合理?(大文件和小文件上传:各不相同)
在传统架构下,可以直接上传文件,但是在Serverless架构下有些问题,在主流的Serverless的平台,它们事件传递的接口一般情况下只有6兆大小,所以大家可以认为:上传一张图片,超过6兆,很有可能上传失败。那么,当要上传大文件的时候,是不是不支持上传?所以,在Serverless情况下,会分为两种情况,一个是大文件,一个是小文件。小文件就可以直接上传,一般情况下,大文件的上传要依靠对象存储,解决方案如下,在客户端发送一个上传请求,告诉函数要上传一张图片,函数这时会把数据记录到数据库里,但是会标记是待上传状态,然后会返回对象存储的信息,一个与签名的地址,之后返回给客户端,客户端通过上传地址直接把文件上传到对象存储,在对象存储接收文件之后,可以通过对象存储触发器异步触发一个函数,告诉这个函数这个文件上传完成了,可进行下部操作。这时文件就可进行图片压缩、函数理解等操作,然后将结果存到数据库,告诉数据库文件已经处理上传完成。所以,对于大文件的上传,在Serverless架构下要依靠对象存储完成。
核心点:第一个函数作预签名,预签名地址给客户端,客户端通过预签名地址把内容上传到对象存储,其他的所有点大家都可以做一些拓展。
第二个问题:Serverless架构下如何持久化文件?(不光持久化,还有权限问题)
举例:使用的框架会做一些缓存到当前的目录下,这在Serverless架构下是不可行的。通常情况下,Serverless架构只有/temp目录下是可写的,其他目录下不可写。如果我们想写一些缓存在目录里,放在/temp目录下相对更安全也更通用,其他的云厂商会让所有的目录都可写,但不是所有的目录都支持,只有部分运行时或者部分厂商才支持,所以在Serverless架构下进行持久化操作或者写缓存的操作,/temp是个不错的选择。
第三个问题:传统Web框架迁移?(真的不需要更改一行代码么)
如果是一个简单的Web框架确是可以实现快速迁移,甚至可以不该一行代码,但这只是特殊情况。一般情况下,传统Web框架比较难迁移到Serverless框架。例如,有的传统Web框架因为有定时任务、异步操作所以是它的特色,如果有这些内容,在Serverless架构下是不生效的,可能要借助Serverless架构的一些特殊的功能(比如说定时触发器功能、异步功能)才能生效,所以还是会有一些更改的成本。除此之外,原先的一些缓存需要持久化的,目录不可写不可以缓存,这时候就需要更改,连接数据库是不是在Serverless架构下,数据库连接是不是有问题。所以,要根据项目的真实情况判断是不是需要更改代码。
第四,应用结构非常重要(静态资源的分离,业务逻辑的合理拆分)
函数计算是不是要将业务打成函数部上去还是直接把业务整体部上去?
通常情况下,要根据业务的具体情况划分。
例子:当一个应用,有两个对外的接口,其中有一个接口的内存消耗在128 MB以下,另一个接口的内存消耗稳定在3000MB左右。这两个接口,平均每天会被触发10000次,并且时间消耗均在100ms。如果两个接口写到一个函数中,那么这个函数可能需要将内存设置在3072MB,同时在用户请求内存消耗较少的接口时,可能在冷启动的情况下难以得到较好的性能表现;如果两个接口分别写到两个函数中,则两个函数内存分别设置成128MB以及3072MB即可:
函数1 |
函数2内存 |
日消费 |
月消费 |
|
写到一个函数中 |
3072MB 20000次/日 |
|
66.38元 |
1991.4元 |
写到两个函数中 |
3072MB 10000次/日 |
128MB 10000次/日 |
34.59元 |
1037.7元 |
费用差 |
|
|
31.79元 |
953.7元 |
首先,静态资源最好放在对象存储上;第二点,后端的业务逻辑,一样的业务可以放在一起,一样内存消耗的可以放在一起。
第五,初始化一些东西?(实例复用有好有坏)
函数计算的实例会被复用,这时就会涉及一些的东西。
以Python语言为例,如果将初始化的方法放在入口函数之外,它可能会被执行一次,如果放在入口函数里面,每次调用都会执行。这时就涉及到实例复用是否要重新加载的问题,所以,大家就需要关注自身的业务逻辑。比如,将其写在外面,之后每次调用就直接复用,这样可以提高效率。如果你的业务逻辑前后有关联,不要将初始化方法写在入口函数外面。
四、演示
Serverless Registry,上面有很多与我们的应用,是一个开源、开放的平台。
今天要做的是掌上游戏机的应用。输入game搜索,点进fc-nes-game APP。
Fc-nes-game App
一款基于函数计算的红白机游戏
初始化项目:s int devsapp/fc-nes-game
进入项目:cd-fc-nes-game
部署项目:s deploy
项目修改来源:https://gitee.com/feiyu22/jsness
第一步初始化应用,找到命令行工具创建一个目录——mkdir
mygame && cd mygame
进入目录之后,通过s init fc-nes-game命令进行初始化操作,之
后会让命名一个文件夹,确定,会下载一些东西,点击default,选
择使用默认密钥
Please input your project name (init dir) fc-nes-game
file decompression completed
please select credential alias default
welcome to the fc-nes-game application
This application requires to open these services:
FC : https: /lfc.console.aliyun.com/
This application can help you quickly deploy the
fc-nes-game project.
The application uses FC component:
https://github.com/devsapp/fc
The application homepage:
https://github.com/devsapp/fc-nes-game
出现如下字句:You could [cd
/Users/jiangyu/Desktop/mygame/
fc-nes-game] and enjoy your serverless journey!
进入目录,查看s.yaml里的内容:这个yaml是资源描述文件,使用的密钥是default密钥
Name:myFCGame # 项目名称
Access:default
services:
myFcGame: #服务名称
component:devsapp/fc #组件名称
props:组件的属性值
region: cn-shanghai
service:
name: my-fc-game-service
description: 'this is a fc game
function:
name:my-fc-game-function
description: 'this is a fc game
runtime:python3
codeUri: ./
handler: index.app
memorysize: 128
timeout: 60
environmentVariables:
game: 'fighter_f8000'
#此处可以选择:fighter_f8000 / Alter_Ego / croom
triggers:
-name: httpTrigger
type: http
config:
authType: anonymous
methods :
-GET
customDomains:
- domainName: auto
protocol: HTTP
routeConfigs:
- path: /*
methods:
-GET
蓝色框架里的触发器,http触发器;绑定的是自定义域名,因为想让系统自动分配域名,所以写的是auto。以上是初识化内容
进入项目之后就可以进行部署
第二步,点击文档s deploy文档,直接进行部署,部署之后会给一个自定义的域名:
domain:
http://my-fc-game-function.my-fc-game-service.1583208943291465.cn-shanghai.fc.devsapp.net
myFCGame :
region: cn- shanghai
service:
name: my-fc-game-service
function:
name : my-fc-game-func tion
runtime : python3
handler: index. App
memorySize: 128
timeout: 60
url:
system_ url:
https://my-fc-gfunction-my-fc -g-service- swfghiqrgm . cn
shanghai . fcapp . run
custom_ domain:
domain: http: / /my-fc-game - function . my- fc-game - service .1583208943291465 cn- shanghai .fc . devsapp .net
triggers :
type: http
name: httpTrigger
点击自定义域名会得到二维码,扫描之后会得到小游戏机。
游戏内容要自行添加,里面有一个src的目录,src目录下有个叫roms,进入roms,里面有个redme.md的文件。
文件内容是:请自行在此处添加游戏,然后再index.html的91行进行添加。输入index.html后:
'ui'; $( ' #emulator' ) . JSNESUI({
"小游戏": 【
['请自行百度下载小游戏‘,'小游戏放在roms目录下,并在此处填写路径']
除了小游戏机之外,Serverless Registry里面还有许多案例,比如人工智能专题,里面有:
Stsrt-pytorch
PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序。
Image-prediction-app
基于ImageAI框架的目标检测
PaddleOCR
PaddleOCR是百度开源的PaddlePaddle项目,基于PassleOCR,可以快速实现通用OCR能力
Ai-keywords
基于TF-IDF与Textrank的中文文本关键词提取应用
比如说:PaddleOCR
只需要点击s int PaddleOCR
? Please input your project name (init dir) PaddleOCR
r file decompression completed
项目帮助https ://github. com/ duol abmeng6/ padd1ehub ppocr
创建应用所在的地区
?地域cn-shenzhen
服务名称,只能包含字母、数字、下划线和中划线。不能以数字、中划线开头。长度在1-128 之间
?服务名PaddleOCR
函数名称,只能包含字母、数字、下划线和中划线。不能以数字、中划线开头。长度在1-64之间
[? 函数名PaddleOCR
内存规格,单位为MB, 默认为2048 MB
?内存规格2048
? please select credential alias default
进入项目输入sdeploy部署项目出现domain即可为api识别的api地址
例如: http://asc. ccc
. XXXx . cn- shenzhen. fc . devsapp . net/predict/ocr_ system
Thanks for using Serverless-Devs
You could [cd /Users/ j iangyu/ Desktop/ mygame/ fc-nes-game/Paddle0CR] and enjoy your serverless journey!
If you need help for this example, you can use [s -h] after you enter folder.
Document . Star: https://github : com/ Serverless -Devs/Serverless -Devs
More applications:
https://registry .serverless-devs
. com
这里有一键部署功能,大家可以通过一键部署功能直接跳到控制台使用,这里我们可以看一下其他的功能,例如刚刚部署的小游戏机的应用,现在要删除它,remove,就可以快速删除。
出现以下代码就表示小游戏已经删除:
Are you sure you want to delete these resources? Yes
Delete trigger my-fc- game- service/my- fc -game function/httpTrigger success .
Delete function my-fc-game-service/ my-fc game -function success .
Delete service my-fc-game- service success
Delete domain my-fc-game-function . my-fc-game- service .
1583208943291465. cn-shanghai . fc . devsapp.net success
End of method: remove
基于Serverless部署PaddleOCR图文识别
说明:
本应用基于Serveress Devs进行部署,可通过Serverdess应用中心一键体验。
本应用的教程基于Serverless 架构部署通用文字识别PaddleOCR
接口文档:
地址:
http://paddleocr . paddleocr
. 1583208943291465. cn- shenzhen. fc. devsapp .net/predict/ocr. System
参数:
Headers :
Content type: application/json
Body:
{" images" :["图片Base64后的字符串"]}
案例:
import requests
import bose64
tef getResult(imagePath):
with open(imagePath, 'rb') as f:
data=f.read()
image = str(base64. b64encodeCdata),encoding='utf-8')
data = '{"images":["" + image + "]}'
txt = requests.post("http://paddleocr . paddleocr .15832
08943291465. cn- shenzhen. fc . devsapp .net/predict/ocr. syste m",data-dato
headers-{'Content-Type': 'application/json'})
return txt . content . deCode("utf-8")
print(getResult(“./test.png”))
如果生产方式中不能接受响应慢,大家可以通过实例预留的方法进行使用。
Serverless Registry里的应用大家可以自行在此体验操作。