Serverless 实战——使用 Rendertron 搭建 Headless Chrome 渲染解决方案
為什么需要 Rendertron?
傳統(tǒng)的 Web 頁(yè)面,通常是服務(wù)端渲染的,而隨著 SPA(Single-Page Application) 尤其是 React、Vue、Angular 為代表的前端框架的流行,越來(lái)越多的 Web App 使用的是客戶端渲染。
使用客戶端渲染有著諸多優(yōu)勢(shì),比如節(jié)省后端資源、局部刷新、前后端分離等等,但也帶來(lái)了一些挑戰(zhàn),比如本文要解決的 SEO 問(wèn)題。
對(duì)于服務(wù)端渲染的頁(yè)面,服務(wù)端可以直接將內(nèi)容通過(guò) HTML 的形式返回,搜索引擎爬蟲可以輕易的獲取頁(yè)面內(nèi)容,而對(duì)于客戶端渲染的應(yīng)用,客戶端必須執(zhí)行服務(wù)器返回的 Javascript 才能得到正確的網(wǎng)頁(yè)內(nèi)容。目前,除 Google、Bing 支持 Javascript 外(也會(huì)有一些限制),其他的大部分搜索引擎都不支持 Javascript,也就無(wú)法獲取正確的網(wǎng)頁(yè)內(nèi)容。
Google 推出的 Rendertron 就是為了解決這樣場(chǎng)景的一款工具。通過(guò)使用 Rendertron,SPA 也能夠被不支持執(zhí)行 Javascript 的搜索引擎爬取渲染后的內(nèi)容。其原理主要是通過(guò)使用 Headless Chrome 在內(nèi)存中執(zhí)行 Javascript,并在得到完整內(nèi)容后,將內(nèi)容返回給客戶端。
Rendertron 原理介紹
通常會(huì)將 Rendertron 部署為一個(gè)獨(dú)立的 HTTP 服務(wù),然后為 Web 應(yīng)用框架配置 Google 官方提供的中間件或者在反向代理上添加相應(yīng)路由規(guī)則,使得能夠在檢測(cè)到搜索引擎爬蟲的 UA 時(shí),可以將請(qǐng)求代理給 Rendertron 服務(wù)。
Rendertron 提供了兩個(gè)主要 API,分別是 Render 以及 Screenshot。其中 Render 用于渲染網(wǎng)站內(nèi)容,Screenshot 用于將網(wǎng)站內(nèi)容截圖。在 SEO 場(chǎng)景下使用的是 Render 接口。
舉例來(lái)說(shuō),當(dāng)客戶端請(qǐng)求我們的網(wǎng)站時(shí),我們搜線根據(jù)請(qǐng)求頭 User Agent 發(fā)現(xiàn)包含了 Baiduspider/2.0 關(guān)鍵字,可以認(rèn)定為當(dāng)前的客戶端是一個(gè)百度爬蟲,然后又在 UserAgent 中發(fā)現(xiàn) Mobile 關(guān)鍵字,可以認(rèn)定這個(gè)爬蟲是在做移動(dòng)端內(nèi)容的抓取。通過(guò)上面的判斷,就可以將這個(gè)請(qǐng)求代理 Rendertron 服務(wù)的 /render/https://www.aliyun.com/?mobile 路由,讓 Rendertron 幫助執(zhí)行網(wǎng)頁(yè)內(nèi)的 Javascript,并將最終內(nèi)容返回給搜索引擎爬蟲。
效果一覽
Google 官方提供了示例 https://render-tron.appspot.com/ ,可以直接體驗(yàn)效果。
我們也提供了部署在函數(shù)計(jì)算上的示例:http://renderton.mofangdegisn.cn
系統(tǒng)架構(gòu)
基于函數(shù)計(jì)算,我們的服務(wù)架構(gòu)如下:
性能測(cè)試
這里我們選擇阿里云的性能測(cè)試PTS服務(wù)進(jìn)行壓測(cè)。
測(cè)試配置如下:
我們配置了 100 并發(fā),測(cè)試 6 分鐘,每分鐘并發(fā)按照 20% 遞增的規(guī)則進(jìn)行壓測(cè)。
我們要測(cè)試的網(wǎng)址網(wǎng)站為:http://renderton.mofangdegisn.cn/render/https://www.example.com/
該網(wǎng)址表示讓 rendertron 請(qǐng)求 https://www.example.com/ 這個(gè)網(wǎng)站的內(nèi)容,并返回渲染結(jié)果。
測(cè)試概覽如下:
從上面的概覽可以看到,由于會(huì)發(fā)生從函數(shù)到 https://www.example.com/ 的網(wǎng)絡(luò)請(qǐng)求,所以最小延遲為 1106ms,99% 的請(qǐng)求可以在 2011ms 完成,90% 的請(qǐng)求可以在 1347ms 完成,75% 的請(qǐng)求可以在 1201ms 完成,50% 的請(qǐng)求可以在 1156ms 完成。我們是每分鐘按照 20% 的并發(fā)遞增,當(dāng)并發(fā)增加時(shí),函數(shù)計(jì)算會(huì)遇到冷啟動(dòng),冷啟動(dòng)最大時(shí)間為 32261ms(可以使用預(yù)熱、預(yù)留等方式可以緩解或完全免除冷啟動(dòng)的影響)。
在未優(yōu)化的場(chǎng)景下,我們的壓測(cè)結(jié)果也達(dá)到了 44.91 的 TPS,這對(duì)于大部分網(wǎng)站是絕對(duì)能夠滿足需求的。
壓測(cè)明細(xì)如下:
上面箭頭所指的位置表示并發(fā)突然增加,函數(shù)自動(dòng)擴(kuò)容時(shí)會(huì)遇到一些冷啟動(dòng),當(dāng)擴(kuò)容完畢,后續(xù)的請(qǐng)求就非常平穩(wěn)了。
部署步驟
將 Rendertron 部署到傳統(tǒng)的 ECS 或者物理機(jī)上作為生產(chǎn)服務(wù),并不是件容易的事。除了 Rendertron 本身需要一些安裝配置外,還需要考慮當(dāng)流量增加時(shí)如何擴(kuò)容,以及配置搭建反向代理或負(fù)載均衡等與之配套的服務(wù)。
下面,我們介紹下函數(shù)計(jì)算如何解決這些問(wèn)題的。
參考鏈接
1. clone 項(xiàng)目:
git clone https://github.com/GoogleChrome/rendertron.gitPS: 這里直接基于官方項(xiàng)目進(jìn)行改造,而不是提供一個(gè)示例模板,是為了演示如何平滑遷移 rendertron 到函數(shù)計(jì)算,同時(shí),在官方版本更新后,也可以盡快更新到最新版本。
2. 創(chuàng)建 template.yml 配置文件:
template.yml 是 Fun 默認(rèn)的描述文件,通過(guò)該描述文件描述的資源,可以通過(guò) fun deploy 一鍵在部署到云端。
比如,我們下面的模板聲明了一個(gè)名為 Rendertron 的服務(wù)以及名為 rendertron 的函數(shù)。
函數(shù)是函數(shù)計(jì)算系統(tǒng)調(diào)度和代碼執(zhí)行的基本單位,我們的 rendertron 項(xiàng)目就可以跑在函數(shù)里,而服務(wù)是管理函數(shù)計(jì)算資源管理的單位,一個(gè)服務(wù)可以包含多個(gè)函數(shù)。
對(duì)于初學(xué)者,可以直接將下面的模板放在項(xiàng)目根目錄下,并且命名為 template.yml。
ROSTemplateFormatVersion: '2015-09-01' Transform: 'Aliyun::Serverless-2018-04-03' Resources:Rendertron: # 聲明一個(gè)名為 Rendertron 的服務(wù)Type: 'Aliyun::Serverless::Service'Properties:Description: This is Rendertron servicerendertron: # 聲明一個(gè)名為 rendertron 的函數(shù)Type: 'Aliyun::Serverless::Function'Properties:Handler: index.handlerRuntime: custom # runtime,我們使用 customTimeout: 60MemorySize: 1024CodeUri: ./Events:httpTrigger: # 添加 http 觸發(fā)器Type: HTTPProperties:AuthType: ANONYMOUSMethods:- GET- POST- PUTrenderton.mofangdegisn.cn: # 添加自定義域名Type: 'Aliyun::Serverless::CustomDomain'Properties:Protocol: HTTPRouteConfig:routes:/*:ServiceName: RendertronFunctionName: rendertron3. 創(chuàng)建 bootstrap 文件
接下來(lái)在項(xiàng)目根目錄創(chuàng)建一個(gè)名為 bootstrap 的文件,這個(gè)文件告訴函數(shù)計(jì)算如何啟動(dòng) rendertron,文件內(nèi)容如下:
#!/usr/bin/env bash PORT=9000 HOST=0.0.0.0 npm run start4. 安裝依賴 & 編譯項(xiàng)目
直接使用 fun install -d 可以一鍵安裝依賴,相當(dāng)于官方文檔里的 npm install,只不過(guò),fun install -d 除了安裝 npm 依賴外,還可以檢測(cè)到 rendertron 包含的 puppeteer 依賴,并且會(huì)自動(dòng)安裝 puppeteer 所必須的 apt 依賴,更多細(xì)節(jié)可以參考這篇文章:
fun install -d接著使用官方介紹的 npm run build 編譯項(xiàng)目:
npm run build5. 本地運(yùn)行 rendertron
不需要修改原項(xiàng)目中的代碼,我們可以直接通過(guò) fun local start renderton.mofangdegisn.cn 在本地將函數(shù)啟動(dòng),然后通過(guò)瀏覽器訪問(wèn)。
fun local start renderton.mofangdegisn.cn演示效果如下:
6. 一鍵部署
當(dāng)本地運(yùn)行、調(diào)試確認(rèn)沒(méi)有問(wèn)題了,就可以考慮部署到線上了。在部署前,要先將 template.yml 中的域名替換為自己的。
這里簡(jiǎn)單介紹下步驟:假如自己 Aliyun 的 AccountId 為 12345,那么就將自己的域名(國(guó)內(nèi)集群需要備案)CNAME 到 12345.cn-shanghai.fc.aliyuncs.com,然后將自己的域名更新到 template.yml,執(zhí)行 fun deploy 即可。更多詳情可以參考這篇文檔。
最后使用 fun deploy 一鍵部署即可。
總結(jié)
使用 Rendertron + 函數(shù)計(jì)算可以快速搭建一個(gè)可以直接用于生產(chǎn)的 Headless Chrome 渲染解決方案,以便于幫助網(wǎng)站更好的進(jìn)行 SEO。
“阿里巴巴云原生關(guān)注微服務(wù)、Serverless、容器、Service Mesh 等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢(shì)、云原生大規(guī)模的落地實(shí)踐,做最懂云原生開發(fā)者的技術(shù)圈。”
總結(jié)
以上是生活随笔為你收集整理的Serverless 实战——使用 Rendertron 搭建 Headless Chrome 渲染解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Go 开发关键技术指南 | 为什么你要
- 下一篇: 阿里巴巴 Kubernetes 能力再获