Malagu 框架对 Serverless 场景常用的云服务接口做了一层抽象,比如对象存储服务,在 Malagu 框架的 @malagu/cloud 组件中抽象了一个云厂商无关的接口: ObjectStorageService 。我们在真实应用中操作对象存储服务使用框架提供的接口即可,不需要关心接口不同云厂商的实现细节。虽然不用云厂商对象存储服务的 Open API 大同小异,但是如果我们需要用到了某个云厂商对象存储服务特定的接口,其他的云厂商是没有的,这时,我们可以使用 ObjectStorageService 接口的 getRawCloudService 方法,获得原生的云服务接口。

在使用 Malagu 实现无头浏览器应用的时候,发现 Puppeteer 的二进制文件过大,超过了 50 MB。很多 Serverless 平台限制在 50 MB 以内,就是某些平台支持超过 50 MB 以上的代码包,也不推荐将二进制打包到代码包中,如果这样,每次部署的时候将会很长。推荐使用对象存储服务 + FaaS 服务来实现。将二进制文件上传到对象存储,函数实例启动的时候,通过内网从对象存储中下载二进制文件到 /tmp 目录。由于内网下载速度很快,大约 1 秒左右可以下载好。

Malagu 框架提供了一个组件 @malagu/puppeteer 组件,帮助我们快速开发无头浏览器应用。其中最关键的是注入并使用以下服务接口:

  1. @Controller()
  2. export class PuppeteerController {
  3. @Autowired(BrowserProvider)
  4. protected readonly browserProvider: BrowserProvider;
  5. }

相关配置:

  1. targets:
  2. - backend
  3. malagu:
  4. cloud:
  5. region: cn-hangzhou # 指定存放 headless 相关二进制的 oss 的地域,建议与应用部署的地域一致,一致可以省略配置
  6. credentials: # 如果函数配置了角色权限,且拥有访问以下 bucket 的读权限,就不需要配置 AK 信息了
  7. accessKeyId: xxxxxxxxxxxxxxxxxxxxxxxx # 指定能够访问存放 headless 相关二进制 accessKeyId,至少具有读该 Object 的权限
  8. accessKeySecret: xxxxxxxxxxxxxxxxxxxxxx
  9. puppeteer:
  10. bucket: headless-lib # 指定存放 headless 相关二进制的 oss 的 Bucket 名称 headless-lib
  11. object: headless-lib.tar.gz # 指定存放 headless 相关二进制的 oss 的 objeck 名称,默认 headless-lib.tar.gz

快速开始

Malagu 框架提供了命令行模板,我们可以通过 malagu init 命令快速创建一个无头浏览器应用项目。选择如下模板:

  1. test malagu init
  2. ___
  3. /'\_/`\ /\_ \
  4. /\ \ __ \//\ \ __ __ __ __
  5. \ \ \__\ \ /'__`\ \ \ \ /'__`\ /'_ `\/\ \/\ \
  6. \ \ \_/\ \/\ \L\.\_ \_\ \_/\ \L\.\_/\ \L\ \ \ \_\ \
  7. \ \_\\ \_\ \__/.\_\/\____\ \__/.\_\ \____ \ \____/
  8. \/_/ \/_/\/__/\/_/\/____/\/__/\/_/\/___L\ \/___/
  9. /\____/
  10. @malagu/cli@1.9.0 \_/__/
  11. ? Select a template to init
  12. backend-app Official
  13. sample-app Official
  14. database-app Official
  15. admin-app Official
  16. microservice Official
  17. ❯ puppeteer Official
  18. multi-component Official
  19. mycli Official
  20. site Official

示例代码

在线打开示例代码
image.png

裁剪过的二进制文件

headless-lib.tar.gz 不支持 video 播放
headless-lib.tar.gz 支持 video 播放

支持 Video 播放的构建脚本

  1. # build headless chrome on sbox
  2. # https://github.com/adieuadieu/serverless-chrome/blob/master/chrome/README.md
  3. # sudo su
  4. apt-get install flex bison libcogl-pango-dev gperf
  5. cd ~
  6. git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
  7. echo "export PATH=$PATH:$HOME/depot_tools" >> ~/.bash_profile
  8. source ~/.bash_profile
  9. mkdir Chromium
  10. cd Chromium
  11. fetch --no-history chromium
  12. cd src
  13. # use /tmp instead of /dev/shm
  14. # https://groups.google.com/a/chromium.org/forum/#!msg/headless-dev/qqbZVZ2IwEw/CPInd55OBgAJ
  15. sed -i -e "s/use_dev_shm = true;/use_dev_shm = false;/g" base/files/file_util_posix.cc
  16. mkdir -p out/Headless
  17. echo 'import("//build/args/headless.gn")' > out/Headless/args.gn
  18. echo 'is_debug = false' >> out/Headless/args.gn
  19. echo 'symbol_level = 0' >> out/Headless/args.gn
  20. echo 'is_component_build = false' >> out/Headless/args.gn
  21. echo 'remove_webcore_debug_symbols = true' >> out/Headless/args.gn
  22. echo 'enable_nacl = false' >> out/Headless/args.gn
  23. # 以下两个配置开启对 Video 播放
  24. # echo 'proprietary_codecs = true' >> out/Headless/args.gn
  25. # echo 'ffmpeg_branding = "Chrome"' >> out/Headless/args.gn
  26. gn gen out/Headless
  27. ninja -C out/Headless headless_shell
  28. cd out/Headless
  29. strip headless_shell
  30. mkdir /home/fc
  31. tar -zcvf /home/fc/headless_shell.tar.gz headless_shell