Serverless 实战 —— 快速开发一个分布式 Puppeteer 网页截图服务

本文涉及的产品
函数计算FC,每月15万CU 3个月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: Puppeteer 是什么? puppeteer 官网的介绍如下: Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol.

Puppeteer 是什么?

image.png

puppeteer 官网的介绍如下:

Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

通俗描述就是:Puppeteer 可以将 Chrome 或者 Chromium 以无界面的方式运行(当然也可以运行在有界面的服务器上),然后可以通过代码控制浏览器的行为,即使是非界面的模式运行,Chrome 或 Chromium 也可以在内存中正确渲染网页的内容。

那么 Puppeteer 能做什么呢?其实有很多地方都可以受用 Puppeteer,比如:

  • 生成网页截图或者 PDF
  • 抓取 SPA(Single-Page Application) 进行服务器渲染(SSR)
  • 高级爬虫,可以爬取大量异步渲染内容的网页
  • 模拟键盘输入、表单自动提交、登录网页等,实现 UI 自动化测试
  • 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题

本文选择截图场景作为演示。

如何快速部署一个分布式 Puppeteer Web 应用?

为了快速部署分布式 Puppeteer Web 应用,这里我们选择函数计算服务

函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费。函数计算更多信息参考

有了函数计算服务,我们这里目标是搭建一个分布式应用,但做的事情其实很简单,那就是写好业务代码,部署到函数计算,仅此而已。

使用函数计算后,我们的系统架构图如下:

搭建步骤步骤:

整体流程如下图所示:

其中,需要我们操作的只有 Fun Init、Fun Install 以及 Fun Deploy 命令,每个的步骤内容都会由这三个命令自动完成。

1. 工具安装

安装 Fun 工具:
建议直接从这里下载二进制可执行程序,解压后即可直接使用。下载地址

安装 Docker:
可以按照这里介绍的方法进行安装。

2. 初始化项目:

通过 Fun 工具,使用下面的命令可以快速初始化一个 Puppeteer Web 应用的脚手架:

fun init -n puppeteer-test http-trigger-node-puppeteer

其中 -n puppeteer-test 表示初始化项目的目录名称, http-trigger-node-puppeteer 表示要使用的模板名称,可以省略该名称,省略后,可以从终端提示的列表中自行选择需要的模板。

执行完毕后,可以看到如下的目录结构:

.
├── index.js
├── package.json
└── template.yml

相比较于传统的 puppeteer 应用,这里仅仅多了一个 template.yml 文件,用于描述函数计算的资源。

而 index.js 就是我们的业务代码了,可以按照 Puppeteer 官方帮助文档的要求书写自己的业务代码,这里不再重复阐述,核心代码如下:

const browser = await puppeteer.launch({
  headless: true,
  args: [
    '--no-sandbox',
    '--disable-setuid-sandbox',
  ]
});

const page = await browser.newPage();
await page.emulateTimezone('Asia/Shanghai');
await page.goto('https://www.baidu.com', {
  'waitUntil': 'networkidle2'
});

await page.screenshot({ path: '/tmp/example', fullPage: true, type: 'png' });

await browser.close();

package.json 内容如下:

{
  ... ...
  "dependencies": {
    "puppeteer": "^2.0.0"
  },
  ... ...
}

可以看到,在 package.json 中声明了 puppeteer 的依赖。这个也是我们使用 node 开发时的标准做法,并无特别之处。

3. 一键安装依赖

puppeteer 的安装,即使是在传统的 linux 机器上,也不是那么的轻松。因为 puppeteer 本身依赖了非常多的系统库,要安装哪些系统库、如何安装这些系统库成了一个比较头痛的问题。

好在函数计算命令行工具 Fun 已经集成了 Puppeteer 的解决方案,只要 package.json 中包含了 puppeteer 依赖,然后使用 fun install -d 即可一键安装所有系统依赖。

fun install -d

4. 本地运行、调试函数

Puppeteer 的本地运行、调试方法与这里介绍的完全一致,我们就不再重复介绍。我们这里只演示下运行效果:

5. 一键部署应用

基本上所有的 FaaS 平台为了减小应用的冷启动,都会设置代码包的限制,函数计算也不例外。而 puppeteer 自身已经达到了 350M 左右,连同其系统依赖已经达到了 450M。如何将 450M 体积的函数部署到 FaaS 平台是一个比较头痛而且繁琐的问题。

函数计算的命令行工具 Fun 现在原生支持了这种大依赖部署(3.1.1 版本仅支持 node runtime)。不需要任何额外操作,仅仅执行 fun deploy:

$ fun deploy

fun 会自动完成依赖的部署。而当检测到打包的依赖超过了平台的限制时,会进入到配置向导,帮助用户自动化地配置。

我们这里推荐的路径是当提示是否由 Fun 自动帮助 NAS 管理是,输入 yes,然后提示提示是否使用 NasConfig: Auto 自动处理 NAS 时,也选择是,之后就不需要做其他的事情,等待函数部署成功即可。

如果有其他的需求,比如想使用自己已经存在的 NAS 服务,可以在提示使用 NasConfig: Auto 时,输入 no,这样就会进入到相应的流程。更详细的说明,请参考下面的 FAQ。

FAQ

在安装 puppeteer 时,Fun 都做了哪些事情?

puppeteer 本身是一个 npm 包,它的安装是非常简单的,通过 npm install 即可。这里的问题在于,puppeteer 依赖了 chromium,而 chromium 又依赖一些系统库。所以 npm install 后,还会触发下载 chromium 的操作。这里用户经常遇到的问题,主要是:

  1. 由于 chromium 的体积比较大,所以经常遇到网络问题导致下载失败。
  2. npm 仅仅只下载 chromium,chromium 依赖的系统库并不会自动安装。用户还需要自行查找缺失的依赖进行安装。

Fun 做的优化主要是:

  1. 通过检测网络环境,对于国内用户,会帮助配置淘宝 NPM 镜像实现加速下载的效果。
  2. 自动为用户安装 chromium 所缺失的依赖库。

Fun 是如何把大依赖部署到函数计算的?不是有代码包大小的限制吗?

基本上所有的 FaaS 为了优化函数冷启动,都会加入函数代码包大小的限制。函数计算也不例外。但是,Fun 通过内置 NAS(阿里云文件存储) 解决方案,可以一键帮用户创建、配置 NAS,并上传依赖到 NAS 上。而函数计算在运行时,可以自动从 NAS 读取到函数依赖。

为了帮助用户自动化地完成这些操作,Fun 内置了一个向导(3.1.1 版本仅支持 node,后续会支持更多,欢迎 github issue 提需求),在检测到代码体积大小超过平台限制时,会提示是否由 Fun 将其改造成 NAS 的方案,整个向导的逻辑如下:

  1. 询问是否使用 Fun 来自动化的配置 NAS 管理依赖?(如果回答是,则进入向导,回答否,则继续发布流程)
  2. 检测用户的 yml 中是否已经配置了 NAS
    1. 如果已经配置,则提示用户选择已经配置的 NAS 存储函数依赖
    2. 如果没有配置,则提示用户是否使用 NasConfig: Auto 自动创建 NAS 配置
      1. 如果选择了是,则帮助用户自动配置 nas、vpc 资源。
      2. 如果选择了否,则列出用户当前 NAS 控制台上已经有的 NAS 资源,让用户选择
    3. 无论上面使用哪种方式,最终都会在 template.yml 生成 NAS 以及 VPC 相关的配置
    4. 根据语言检测,比如 node runtime,会将 node_modules 以及 .fun/root 目录映射到 nas 目录(通过 .nas.yml 实现)
    5. 自动执行 fun nas sync 帮用户把本地的依赖上传到 NAS 服务
    6. 自动执行 fun deploy,帮用户把代码上传到函数计算
    7. 提示帮助信息,对于 HTTP Trigger 的,提示函数的 Endpoint,直接打开浏览器访问即可看到效果

是否可以指定 puppeteer 的版本?

可以的,只需要修改 package.json 中的 puppeteer 的版本,重新安装即可。

函数计算实例中的时区采用的 UTC,是否有办法改为北京时间?

某些网页的显示效果是和时区挂钩的,时区不同,可能会导致显示的内容有差异。使用本文介绍的方法,可以非常容易的使用 puppeteer 的最新版本,而在 puppeteer 的最新版本 2.0 提供了一个新的 API page.emulateTimezone(timezoneId) , 可以非常容易的修改时区。

如果 Puppeteer 后续版本更新后,依赖更多的系统依赖,本文介绍的方法还适用吗?

Fun 内置了 .so 缺失检测机制,当在本地调试运行时,会智能地根据报错识别出缺失的依赖库,然后精准地给出安装命令,可以做到一键安装。

如果添加了新的依赖,如何更新?

如果添加了新的依赖,比如 node_modules 目录添加了新的依赖库,只需要重新执行 fun nas sync 进行同步即可。
如果修改了代码,只需要使用 fun deploy 重新部署即可。由于大依赖和代码通过 NAS 进行了分离,依赖通常不需要频繁变化,所以调用的频率比较低,而 fun deploy 的由于没有了大依赖,部署速度也会非常的快。

除了本文介绍的方法还有哪些方法可以一键安装 puppeteer?

Fun 提供了非常多的依赖安装方式,除了本文介绍的将依赖直接声明在 package.json 中,然后通过 fun install -d 的方式安装外,还有很多其他方法,他们均有各自适用的场景:

  1. 命令式安装。比如 fun install -f functionName -p npm puppeteer。这种安装方式的好处是即使对 fun 不了解的用户也可以傻瓜式的使用。
  2. 声明式安装。这种安装方式的好处是提供了类 Dockerfile 的体验,Dockerfile 的大部分指令在这里都是可以直接使用的。通过这种方式声明的依赖,可以通过直接提交到版本仓库。他人拉取代码后,也可以一键安装所有依赖。
  3. 交互环境安装。这种安装方式的好处是提供了类似传统物理机的安装体验。在交互环境中,大部分 linux 命令都是可以使用的,而且可以不断试错。

总结

本文介绍了一种比较简单易行地从零开始搭建分布式 Puppeteer Web 服务的方法。利用该方法,可以做到不需要关心如何安装依赖、也不需要关系如何上传依赖,顺滑地完成部署。

部署完成后,即可享受函数计算带来的优势,即:

  • 无需采购和管理服务器等基础设施,只需专注业务逻辑的开发,可以大幅缩短项目交付时间和人力成本
  • 提供日志查询、性能监控、报警等功能快速排查故障
  • 免运维,毫秒级别弹性伸缩,快速实现底层扩容以应对峰值压力,性能优异
  • 成本极具竞争力
相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
2月前
|
数据管理 API 调度
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
HarmonyOS Next 是华为新一代操作系统,专注于分布式技术的深度应用与生态融合。本文通过技术特点、应用场景及实战案例,全面解析其核心技术架构与开发流程。重点介绍分布式软总线2.0、数据管理、任务调度等升级特性,并提供基于 ArkTS 的原生开发支持。通过开发跨设备协同音乐播放应用,展示分布式能力的实际应用,涵盖项目配置、主界面设计、分布式服务实现及部署调试步骤。此外,深入分析分布式数据同步原理、任务调度优化及常见问题解决方案,帮助开发者掌握 HarmonyOS Next 的核心技术和实战技巧。
241 76
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
|
4月前
|
存储 Serverless 数据库
科普文:云计算服务类型IaaS, PaaS, SaaS, BaaS, Faas说明
本文介绍了云计算服务的几种主要类型,包括IaaS(基础设施即服务)、PaaS(平台即服务)、SaaS(软件即服务)、BaaS(后端即服务)和FaaS(函数即服务)。每种服务模式提供了不同的服务层次和功能,从基础设施的提供到应用的开发和运行,再到软件的交付使用,满足了企业和个人用户在不同场景下的需求。文章详细阐述了每种服务模式的特点、优势和缺点,并列举了相应的示例。云计算服务的发展始于21世纪初,随着互联网技术的普及,这些服务模式不断演进,为企业和个人带来了高效、灵活的解决方案。然而,使用这些服务时也需要注意服务的稳定性、数据安全性和成本等问题。
2545 4
|
21天前
|
存储 缓存 Java
Java中的分布式缓存与Memcached集成实战
通过在Java项目中集成Memcached,可以显著提升系统的性能和响应速度。合理的缓存策略、分布式架构设计和异常处理机制是实现高效缓存的关键。希望本文提供的实战示例和优化建议能够帮助开发者更好地应用Memcached,实现高性能的分布式缓存解决方案。
36 9
|
2月前
|
物联网 调度 vr&ar
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
鸿蒙技术分享:HarmonyOS Next 深度解析 随着万物互联时代的到来,华为发布的 HarmonyOS Next 在技术架构和生态体验上实现了重大升级。本文从技术架构、生态优势和开发实践三方面深入探讨其特点,并通过跨设备笔记应用实战案例,展示其强大的分布式能力和多设备协作功能。核心亮点包括新一代微内核架构、统一开发语言 ArkTS 和多模态交互支持。开发者可借助 DevEco Studio 4.0 快速上手,体验高效、灵活的开发过程。 239个字符
236 13
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
|
2月前
|
NoSQL Java Redis
秒杀抢购场景下实战JVM级别锁与分布式锁
在电商系统中,秒杀抢购活动是一种常见的营销手段。它通过设定极低的价格和有限的商品数量,吸引大量用户在特定时间点抢购,从而迅速增加销量、提升品牌曝光度和用户活跃度。然而,这种活动也对系统的性能和稳定性提出了极高的要求。特别是在秒杀开始的瞬间,系统需要处理海量的并发请求,同时确保数据的准确性和一致性。 为了解决这些问题,系统开发者们引入了锁机制。锁机制是一种用于控制对共享资源的并发访问的技术,它能够确保在同一时间只有一个进程或线程能够操作某个资源,从而避免数据不一致或冲突。在秒杀抢购场景下,锁机制显得尤为重要,它能够保证商品库存的扣减操作是原子性的,避免出现超卖或数据不一致的情况。
78 10
|
3月前
|
监控 Serverless 云计算
探索Serverless架构:开发实践与优化策略
本文深入探讨了Serverless架构的核心概念、开发实践及优化策略。Serverless让开发者无需管理服务器即可运行代码,具有成本效益、高可扩展性和提升开发效率等优势。文章还详细介绍了函数设计、安全性、监控及性能和成本优化的最佳实践。
|
3月前
|
弹性计算 人工智能 自然语言处理
魔搭社区与函数计算:高效部署开源大模型的文本生成服务体验
在数字化时代,人工智能技术迅速发展,开源大模型成为重要成果。魔搭社区(ModelScope)作为开源大模型的聚集地,结合阿里云函数计算,提供了一种高效、便捷的部署方式。通过按需付费和弹性伸缩,开发者可以快速部署和使用大模型,享受云计算的便利。本文介绍了魔搭社区与函数计算的结合使用体验,包括环境准备、部署应用、体验使用和资源清理等步骤,并提出了改进建议。
|
4月前
|
机器学习/深度学习 监控 物联网
函数即服务(FaaS)
函数即服务(FaaS)
174 6
|
3月前
|
监控 安全 Serverless
"揭秘D2终端大会热点技术:Serverless架构最佳实践全解析,让你的开发效率翻倍,迈向技术新高峰!"
【10月更文挑战第23天】D2终端大会汇聚了众多前沿技术,其中Serverless架构备受瞩目。它让开发者无需关注服务器管理,专注于业务逻辑,提高开发效率。本文介绍了选择合适平台、设计合理函数架构、优化性能及安全监控的最佳实践,助力开发者充分挖掘Serverless潜力,推动技术发展。
130 1
|
4月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?

相关产品

  • 函数计算