无头浏览器性能对比与Puppeteer的优化文档

工作中我们经常使用脚本绘图,比如通过脚本绘制饼图、折线图、树状图等。每种编程语言都有对应的图形库,像Python的Matplotlib,PHP的GD2。但在实际使用过程中,这些图形库使用起来并不方便。一是编码量大,二是图形渲染效果不理想,三是调试不方便。

如上图是由PHP调用GD2扩展绘制而成,绘制这样一幅图需要写好几千行代码,最后的产出(效果)也并不理想。虽然能看,但离 “美感“ 还有很大差距。仔细看会发现曲线、弧形、圆角都有锯齿感。

一. 遇到的问题

平时工作中肯定需要产出报表或者邮件,邮件中少不了各种可视化的图形。简单的有饼图、折线图,复杂的有南丁格尔玫瑰、箱型图、雷达图等。使用PHP和Python来做的话投入和产出不成正比。最好的报表效果类似滴滴公司每月发布的 交通报告,截取了某一页效果如下

这种报告非常友好,通过可视化的图形直观的表达了主题,图片种类多且清晰美观。通过观察,我发现滴滴这种报告并非人工截图粘贴而成,大部分内容不需要人工参与直接程序生成(每座城市的月报都是一个模版)。高德提供的交通报告也类似 https://report.amap.com/download_city.do。所以我希望找到一种能减少编码工作量,绘制高清、美观图片的方法,为生成高大上的报表打好地基。

二. 探索Headless

做前端开发和Web测试的同学对 Headless(无头浏览器)都不会陌生,无头浏览器是没有用户图形界面的浏览器,可以直接运行在服务端,向客户端提供服务接口。无头浏览器提供了对于网页的自动控制,这种控制所依赖的环境和现代 web 浏览器类似,然而却是通过命令行界面或者网络通讯实施。它们是良好的网页测试工具,提供了和普通 web 浏览器同样的功能,包括渲染 HTML、页面布局、颜色以及字体,同时也提供了 JavaScript 和 AJAX 的加载和执行,这是其它测试工具通常做不到的。Google 在 2009 年的时候声称,使用无头浏览器可以帮助他们的搜索引擎在网站中定位那些使用 AJAX 技术加载的内容。

官方解释很抽象,效果图如下:
demo1

URL参数解释

仔细看URL能看到URL中有option等参数,option就是常见的json格式,比较通用。还能在线调试 Demo在线调试

URL中的参数就是在线调试工具中的代码,在开发过程中我们可以先在线调试,调试到满足需求后再调用接口渲染, 渲染时间在500ms左右。在实际使用中无论多复杂的图形都可以在1秒内返回结果,通过ab压测,平均QPS在23,在生成报告这种应用场景下完全够用。

三. 服务对比

很多服务提供Headless支持,常见的有Puppeteer、Phantomjs、Nightmare、Firefox headless,哪个工具更好用也是各大社区争论的话题,不好评价。在实际项目中我分别使用了Phantomjs和Puppeteer,从搭建环境、封装服务、服务稳定性三方面来说Puppeteer都优于Phantomjs。每种服务在使用过程中都会遇到各种问题,但总能通过摸索慢慢解决,由于操作方式不同,踩的坑也会不一样,就会导致主观上大家对同一个服务评价有差异,这里我推荐在CentOS上使用Puppeteer(出于个人主观的评价)。

同类服务中渲染速度最快的是 Google Charts

1
2
3
https://chart.googleapis.com/chart?cht=rs&chs=400x400&chd=s:voJATd9v,MW9BA9&chco=FF0000,FF9900&chls=2.0,4.0,0.0|2.0,4.0,0.0&chxt=x&chxl=0:|0|45|90|135|180|225|270|315&chxr=0,0.0,360.0&chg=25.0,25.0,4.0,4.0&chm=B,FF000080,0,1.0,5.0|B,FF990080,1,1.0,5.0|h,0000FF,0,1.0,4.0|V,00FF00,0,4.0,5.0

end(结束标记,方便复制)

Google Chart

Google Charts渲染速度快,但缺点较多。

  1. 需要使用特定DSL调用,学习成本比较高。
  2. 网络因素,不翻墙无法访问。
  3. 支持的图形种类比较少。
  4. 官方已经不推荐使用。

虽然不推荐使用Google Charts,但这种渲染图形的方式值得学习,Google Charts的渲染速度能达到100ms,也是我追求的。正是看到此服务,我才想到利用Headless绘图,并不断的优化速度,最终达到500ms左右。下面是实际使用效果:

  1. 中文和渐变色渲染效果

    服务器端使用的中文字体为思源黑体,是AdobeGoogle所领导开发的开源字体 ,在CentOS上可以直接通过yum安装,渲染效果也不错。如果想使用其他字体,可以根据自己的喜好定义。

  2. 除了支持Echarts 还支持D3、HighCharts、D2等图形库,下面是HighCharts的渲染效果

同样可以通过修改URL中的参数,实现想要的效果,在线调试地址https://jshare.com.cn/demos/hhhhDW

综上对比,使用Puppeteer搭建服务端绘图服务,在稳定性,扩展性,渲染速度方面都有很好的效果。

四. API封装与优化

选定Puppeteer之后,我就一直在优化绘图服务的速度。经过不断努力,截图服务的速度基本优化到极限了500ms左右。最后开始编写稳定的API接口,对外提供服务。

  1. 服务端架构介绍

服务端架构

​ 服务器端架构使用的都是常用配置,通过PM2生成多个Node实例,Chrome Headless本身支持多实例(理论 上在资源足够多的情况下我们可以打开无数个Chrome浏览器)。Chrome Headless的执行是同步的,Node服务本身是异步的,所以多个实例并不能支持更大的并发,只是可以利用多核CPU。这里PM2生成4个实例和生成一个实例的差异并不大。接口的瓶颈在于 Chrome Headless 的执行速度与内存、CPU等资源的消耗情况。

  1. Chrome Headless版本选择

    在tlinux上chromium有多个版本可以选择,经过我的测试,最优的版本是:

    1
    2
    $ yum install chromium-headless
    $ /usr/lib64/chromium-browser/headless_shell (调用路径)
  2. 主要优化点

    • 浏览器每次调用后一定要关闭。否则一个page页面发生错误,整个服务都会卡死。
    • 浏览器打开时会默认有一个page页面,直接利用该页面能减少1/3左右的内存消耗。

五. 其他尝试

  1. 爬取SPA应用,并生成预渲染内容(即“SSR” 服务端渲染)
  2. 自动化表单提交、UI测试、键盘输入等
  3. 自动化测试Web页面,捕获站点的时间线等信息,帮助分析网站性能问题
  4. 服务稳定后申请一个域名(用的人多的话)。

七. 写在最后

有很多Web测试工具都是基于Headless完成,Puppeteer的性能算是最好的,应用前景非常广,值得深入学习。详细优化教程请看 Puppeteer性能优化与执行速度提升