阿里云serverless踏坑之旅

本文总结了使用阿里云severless(以下简称“serverless”)开发时碰到的一些问题以及解决思路,非入门教程,所以建议对Serverless有一定了解或者使用之后再阅读。

开发工具怎么选?

由于serverless,提供了4种工具来进行开发。可以分成两类,一类是命令行工具: fclifuncraft。funcraft是一个工具集合,功能比fcli要丰富很多(不知道fcli相对于funcraft有什么优势,更小更轻量?),文档也全面很多。但在命令行中调试代码是件痛苦的事情,所以funcraft官方文档的调试示例都是推荐使用VSCode插件(以下简称“插件”)。VSCode插件依赖的就是funcraft。

另一类是图形界面工具:Web IDEVSCode插件。两个工具看起来功能差不多,Web IDE使用起来似乎更方便,但是作者还是推荐使用VSCode插件,原因很简单,serverless并不支持版本回退功能,所以代码必须同步到git仓库,而Web IDE是不支持git相关操作的,即使支持,把授权信息放在远程也不安全,即使不放在远程,每次同步代码都要输入账号密码也比较麻烦。

结论:推荐使用插件,虽然它有些bug,文档也不完善。但已能满足开发调试以及代码管理功能。接下的内容我们也以插件作为工具进行分析。

如何修改本地配置信息?

使用插件的时候需要先绑定账号,选择对应的区域。包括两个函数计算(function compute)和函数流程(function flow),函数流程开发中暂时没用到,这里讲一讲使用函数计算时的注意事项。
函数计算功能分两块:本地服务/函数(LOCAL RESOURCES)和远程服务/函数(REMOTE RESOURCES)。
远程服务/函数比较鸡肋,只能能列出当前区域的所有服务和函数,不能修改配置、查看日志等,只有事件类函数可以调用执行,HTTP函数不行。
本地服务/函数会找到当前工作目录下template.yml文件,然后根据配置信息列出服务/函数。
通过插件创建serverless项目的时候默认会按照“服务名/函数名”的方式创建,这个可以在template.yml修改,对应属性为CodeUri

结论:通过serverless项目根目录下的template.yml文件,然后部署对应的服务/函数,可以修改服务和函数的部分配置信息。

插件是如何实现本地调试的?

本地开发调试需要安装Docker,开发调试的时候插件会拉取一个“aliyunfc”开头的Docker镜像,通过镜像启动一个容器作为开发环境,在这个容器中部署代码并执行。
这个容器并不会在运行/调试的时候创建,只会在函数被调用的时候创建和启动,同时它只是一个临时运行环境,程序退出后即被销毁。
所以我们在运行时遇到问题时也可以直接进入容器进行排查。
进行本地开发调试的时候会通过VSCode的终端来执行对应的命令,但终端显示的信息并不全,所以有时候如果你点击了调试或运行按钮控制台没有输出有效信息需要耐心等一等,很可能后台正在执行命令
结论:建议学习Docker基础知识,方便排查和解决插件使用过程中的问题。

如何管理依赖?

serverless对于依赖管理这一块非常不智能,部署的时候需要手动上传,不能根据配置文件自动安装。
如果要强行实现自动安装也是可行的。
首先通过子进程把代码以及模块配置文件复制到/tmp(只有这个目录有写权限),然后调用对应的模块安装命令进行安装,最后在/tmp目录下通过子进程的方式调用执行。
会增加一些代码量(比较折腾),适合动手能力强、时间充裕的工程师。

官方提倡的方式还是将本地代码及依赖一起打包上传。这就容易出问题了~
大多数开发的时候会选择通过配置文件的方式来维护依赖模块,一方面是出于节省存储空间考虑,很重要的另一个原因就是考虑系统平台的兼容性问题。
有些模块支持多种系统,但各系统执行的代码文件又不同。
serverless远程运行环境是linux,如果碰巧开发工程师使用的是非linux系统,而模块也支持多系统,那么就有些麻烦了,因为本地开发和远程部署的模块不一致。
所以这也是我在团队强推通过Docker容器进行开发和部署,以及在编写《了不起的JavaScript工程师》)着重介绍Docker的一个重要原因。

对于Python项目的第三方模块需要一些手动操作。
目前我的做法是通过Python -m venv xx命令在容器中创建一个虚拟环境,通过pip freeze命令导出模块,再将模块复制到项目根目录下的modules/目录,同时在代码中通过sys.path添加该目录。
结论:为了保证本地/远程模块的一致性,建议在Docker容器中进行安装,但由于代码目录是只读权限,所以需要手动复制模块。

下载速度慢怎么办?

使用代理是常规的选择,网上资料很多,针对不同语言的代理环境不一样,这里不多介绍了。
重点介绍另一种思路。
在使用serverless做持续集成的时候碰到一个问题,就是每次从GitHub上拉取代码的时候速度很慢,导致函数运行超时。
后来咨询客服得知是网络防火墙(你懂的,就是那个最大的防火墙)的原因,将函数部署区域改为香港问题解决。
结论:对于防火墙导致的网络问题可以尝试切换区域解决。

如何固定公网IP?

两种实现方式:

  1. 反向代理。这个需要借助额外的机器实现,虽然比较简单,但这种方式很不“serverless”。
  2. NAT网关。这是阿里云提供的一个服务,使用的时候需要关闭函数的“公网访问”配置,改为“专有网络”访问,选择已创建的NAT网关。官方给出的示例还要结合EIP,配置比较麻烦,同时需要额外收费。
    结论:两种实现方式各有优缺点,请自行斟酌。

作者信息:朱德龙人和未来高级前端工程师