天天看點

有了 serverless,前端也可以快速開發一個 Puppeteer 網頁截圖服務Puppeteer 是什麼?

更多雲原生技術資訊可關注 阿裡巴巴雲原生技術圈

Puppeteer 是什麼?

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 能做什麼呢?

  • 生成網頁截圖或者 PDF
  • 抓取 SPA(Single-Page Application) 進行伺服器渲染(SSR)
  • 進階爬蟲,可以爬取大量異步渲染内容的網頁
  • 模拟鍵盤輸入、表單自動送出、登入網頁等,實作 UI 自動化測試
  • 捕獲站點的時間線,以便追蹤你的網站,幫助分析網站性能問題

本文選擇截圖場景作為示範。

廢話不多說了,我們直接給大家介紹下如何用函數計算産品來快速部署一個 Puppeteer Web 應用。

如何快速部署一個分布式 Puppeteer Web 應用?

為了快速部署分布式 Puppeteer Web 應用,本文以

函數計算服務

為例來做展示。

函數計算(Function Compute): 函數計算是一個事件驅動的服務,通過函數計算,使用者無需管理伺服器等運作情況,隻需編寫代碼并上傳。函數計算準備計算資源,并以彈性伸縮的方式運作使用者代碼,而使用者隻需根據實際代碼運作所消耗的資源進行付費。函數計算更多資訊 參考

有了函數計算服務,我們這裡目标是搭建一個分布式應用,但做的事情其實很簡單,那就是寫好業務代碼,部署到函數計算,僅此而已。

使用函數計算後,我們的系統架構圖如下:

有了 serverless,前端也可以快速開發一個 Puppeteer 網頁截圖服務Puppeteer 是什麼?

效果示範

可以直接通過以下連結檢視效果:

https://1911504709953557.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/puppeteer-test/html2png/?url=https://www.aliyun.com/product/fc

PS:第一次請求可能會有幾秒的冷啟動時間,通過使用

預留模式

可以完全去除冷啟動,這題超綱,下次再講。

搭建步驟步驟:

整體流程如下圖所示:

有了 serverless,前端也可以快速開發一個 Puppeteer 網頁截圖服務Puppeteer 是什麼?

其中,需要我們操作的隻有 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 的本地運作、調試方法與

這裡

介紹的完全一緻,我們就不再重複介紹。我們這裡隻示範下運作效果:

有了 serverless,前端也可以快速開發一個 Puppeteer 網頁截圖服務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 時,也選擇是,之後就不需要做其他的事情,等待函數部署成功即可。

有了 serverless,前端也可以快速開發一個 Puppeteer 網頁截圖服務Puppeteer 是什麼?

如果有其他的需求,比如想使用自己已經存在的 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
  3. 如果已經配置,則提示使用者選擇已經配置的 NAS 存儲函數依賴
  4. 如果沒有配置,則提示使用者是否使用 自動建立 NAS 配置
  5. 如果選擇了是,則幫助使用者自動配置 nas、vpc 資源。
  6. 如果選擇了否,則列出使用者目前 NAS 控制台上已經有的 NAS 資源,讓使用者選擇
  7. 無論上面使用哪種方式,最終都會在 template.yml 生成 NAS 以及 VPC 相關的配置
  8. 根據語言檢測,比如 node runtime,會将 node_modules 以及 .fun/root 目錄映射到 nas 目錄(通過 .nas.yml 實作)
  9. 自動執行 fun nas sync 幫使用者把本地的依賴上傳到 NAS 服務
  10. 自動執行 fun deploy,幫使用者把代碼上傳到函數計算
  11. 提示幫助資訊,對于 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 服務的方法。利用該方法,可以做到不需要關心如何安裝依賴、也不需要關系如何上傳依賴,順滑地完成部署。

部署完成後,即可享受函數計算帶來的優勢,即:

  • 無需采購和管理伺服器等基礎設施,隻需專注業務邏輯的開發,可以大幅縮短項目傳遞時間和人力成本
  • 提供日志查詢、性能監控、報警等功能快速排查故障
  • 免運維,毫秒級别彈性伸縮,快速實作底層擴容以應對峰值壓力,性能優異
  • 成本極具競争力
關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”

繼續閱讀