天天看點

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

為什麼需要 Rendertron?

傳統的 Web 頁面,通常是服務端渲染的,而随着 SPA(Single-Page Application) 尤其是 React、Vue、Angular 為代表的前端架構的流行,越來越多的 Web App 使用的是用戶端渲染。

使用用戶端渲染有着諸多優勢,比如節省後端資源、局部重新整理、前後端分離等等,但也帶來了一些挑戰,比如本文要解決的 SEO 問題。

對于服務端渲染的頁面,服務端可以直接将内容通過 HTML 的形式傳回,搜尋引擎爬蟲可以輕易的擷取頁面内容,而對于用戶端渲染的應用,用戶端必須執行伺服器傳回的 Javascript 才能得到正确的網頁内容。目前,除 Google、Bing 支援 Javascript 外(也會有一些限制),其他的大部分搜尋引擎都不支援 Javascript,也就無法擷取正确的網頁内容。

Google 推出的

Rendertron

就是為了解決這樣場景的一款工具。通過使用 Rendertron,SPA 也能夠被不支援執行 Javascript 的搜尋引擎爬取渲染後的内容。其原理主要是通過使用 Headless Chrome 在記憶體中執行 Javascript,并在得到完整内容後,将内容傳回給用戶端。

Rendertron 原理介紹

通常會将 Rendertron 部署為一個獨立的 HTTP 服務,然後為 Web 應用架構配置 Google 官方提供的

中間件

或者在反向代理上添加相應路由規則,使得能夠在檢測到搜尋引擎爬蟲的

UA

時,可以将請求代理給 Rendertron 服務。

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

Rendertron 提供了兩個主要 API,分别是 Render 以及 Screenshot。其中 Render 用于渲染網站内容,Screenshot 用于将網站内容截圖。在 SEO 場景下使用的是 Render 接口。

舉例來說,當用戶端請求我們的網站時,我們搜線根據請求頭 User Agent 發現包含了

Baiduspider/2.0

關鍵字,可以認定為目前的用戶端是一個百度爬蟲,然後又在 UserAgent 中發現 Mobile 關鍵字,可以認定這個爬蟲是在做移動端内容的抓取。通過上面的判斷,就可以将這個請求代理 Rendertron 服務的

/render/https://www.aliyun.com/?mobile

路由,讓 Rendertron 幫助執行網頁内的 Javascript,并将最終内容傳回給搜尋引擎爬蟲。

效果一覽

Google 官方提供了示例

https://render-tron.appspot.com/

,可以直接體驗效果。

我們也提供了部署在函數計算上的示例:

http://renderton.mofangdegisn.cn
Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

系統架構

基于函數計算,我們的服務架構如下:

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

性能測試

這裡我們選擇阿裡雲的

性能測試PTS

服務進行壓測。

測試配置如下:

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

我們配置了 100 并發,測試 6 分鐘,每分鐘并發按照 20% 遞增的規則進行壓測。

我們要測試的網址網站為:

http://renderton.mofangdegisn.cn/render/https://www.example.com/

該網址表示讓 rendertron 請求

https://www.example.com/

這個網站的内容,并傳回渲染結果。

測試概覽如下:

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

從上面的概覽可以看到,由于會發生從函數到

的網絡請求,是以最小延遲為 1106ms,99% 的請求可以在 2011ms 完成,90% 的請求可以在 1347ms 完成,75% 的請求可以在 1201ms 完成,50% 的請求可以在 1156ms 完成。我們是每分鐘按照 20% 的并發遞增,當并發增加時,函數計算會遇到冷啟動,冷啟動最大時間為 32261ms(可以使用預熱、

預留

等方式可以緩解或完全免除冷啟動的影響)。

在未優化的場景下,我們的壓測結果也達到了 44.91 的 TPS,這對于大部分網站是絕對能夠滿足需求的。

壓測明細如下:

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

上面箭頭所指的位置表示并發突然增加,函數自動擴容時會遇到一些冷啟動,當擴容完畢,後續的請求就非常平穩了。

部署步驟

将 Rendertron 部署到傳統的 ECS 或者實體機上作為生産服務,并不是件容易的事。除了 Rendertron 本身需要一些安裝配置外,還需要考慮當流量增加時如何擴容,以及配置搭建反向代理或負載均衡等與之配套的服務。

下面,我們介紹下函數計算如何解決這些問題的。

參考連結

  1. Fun 安裝教程 可以直接在這裡下載下傳二進制版本的 Fun,解壓後即可使用。
  2. Docker 安裝教程 :本地安裝依賴需要借助于 docker,可以直接在這裡下載下傳 Docker 。

1. clone 項目:

git clone https://github.com/GoogleChrome/rendertron.git           

PS: 這裡直接基于官方項目進行改造,而不是提供一個示例模闆,是為了示範如何平滑遷移 rendertron 到函數計算,同時,在官方版本更新後,也可以盡快更新到最新版本。

2. 建立 template.yml 配置檔案:

template.yml 是 Fun 預設的

描述檔案

,通過該描述檔案描述的資源,可以通過 fun deploy 一鍵在部署到雲端。

比如,我們下面的模闆聲明了一個名為 Rendertron 的服務以及名為 rendertron 的函數。

函數

是函數計算系統排程和代碼執行的基本機關,我們的 rendertron 項目就可以跑在函數裡,而

服務

是管理函數計算資源管理的機關,一個服務可以包含多個函數。

對于初學者,可以直接将下面的模闆放在項目根目錄下,并且命名為 template.yml。

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  Rendertron: # 聲明一個名為 Rendertron 的服務
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: This is Rendertron service
    rendertron: # 聲明一個名為 rendertron 的函數
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: index.handler
        Runtime: custom # runtime,我們使用 custom
        Timeout: 60
        MemorySize: 1024
        CodeUri: ./
      Events:
        httpTrigger: # 添加 http 觸發器
          Type: HTTP
          Properties:
            AuthType: ANONYMOUS
            Methods:
              - GET
              - POST
              - PUT
           
  renderton.mofangdegisn.cn: # 添加自定義域名
    Type: 'Aliyun::Serverless::CustomDomain'
    Properties:
      Protocol: HTTP
      RouteConfig:
        routes:
          /*:
            ServiceName: Rendertron
            FunctionName: rendertron           

3. 建立 bootstrap 檔案

接下來在項目根目錄建立一個名為

bootstrap

的檔案,這個檔案告訴函數計算如何啟動 rendertron,檔案内容如下:

#!/usr/bin/env bash
PORT=9000 HOST=0.0.0.0 npm run start           

4. 安裝依賴 & 編譯項目

直接使用

fun install -d

可以一鍵安裝依賴,相當于官方文檔裡的 npm install,隻不過,

fun install -d

除了安裝 npm 依賴外,還可以檢測到 rendertron 包含的 puppeteer 依賴,并且會自動安裝 puppeteer 所必須的 apt 依賴,更多細節可以參考

這篇文章

fun install -d           

接着使用官方介紹的

npm run build

編譯項目:

npm run build           

5. 本地運作 rendertron

不需要修改原項目中的代碼,我們可以直接通過 fun local start renderton.mofangdegisn.cn 在本地将函數啟動,然後通過浏覽器通路。

fun local start renderton.mofangdegisn.cn           

示範效果如下:

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

6. 一鍵部署

當本地運作、調試确認沒有問題了,就可以考慮部署到線上了。在部署前,要先将 template.yml 中的域名替換為自己的。

這裡簡單介紹下步驟:假如自己 Aliyun 的 AccountId 為 12345,那麼就将自己的域名(國内叢集需要備案)CNAME 到 12345.cn-shanghai.fc.aliyuncs.com,然後将自己的域名更新到 template.yml,執行 fun deploy 即可。更多詳情可以參考

這篇文檔

最後使用 fun deploy 一鍵部署即可。

Serverless 實戰——使用 Rendertron 搭建 Headless Chrome 渲染解決方案

總結

使用 Rendertron + 函數計算可以快速搭建一個可以直接用于生産的 Headless Chrome 渲染解決方案,以便于幫助網站更好的進行 SEO。

阿裡巴巴雲原生 關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”

繼續閱讀