H5开发在QQ钱包的应用实践

内容来源:2017年6月24日,腾讯前端高级工程师周明礼在“腾讯Web前端大会 TFC 2017 ”进行《QQ钱包h5应用开发实践》演讲分享。IT 大咖说(WeChat_ID:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:3071 | 5分钟阅读

观看嘉宾完整演讲视频及PPT,请点击:http://t.cn/EAAPbUx

摘要

移动互联网时代,提高网页性能是每个前端团队的目标。作为QQ钱包团队的前端工程师,我们是如何通过自研nodejs服务和利用service worker实现H5页面秒开?让我们来探讨一下QQ钱包H5应用的开发实践。

QQ钱包众多H5应用

2015年我们正式成立了钱包团队,从刚开始QQ钱包只有一个钱包入口,一直发展到今天,已经开发出了话费充值、卡券、积分、企鹅网吧、城市服务以及智慧校园等一系列服务。

QQ钱包H5应用开发挑战

接入层服务器压力大

QQ钱包H5应用日均pv在1000w以上,推广期pv可达上亿的级别,需要解决服务器性能优化问题。

移动网络环境复杂

为了提高用户的体验,需要尽快的吐出页面,安卓平台下一般要求为3秒,而在ios平台则是要求2秒以内,在某些业务场景下直接要求秒开。

交互场景复杂

移动端特别是安卓平台的web性能容易造成瓶颈,例如长列表渲染问题,图片内存占用问题,css3动画性能问题都需要去解决。

基于SERVICE WORKER的缓存管理方案

浏览器缓存

以卡券页面为例,整个页面总共会发出35个请求,其中有13个请求是数据上报,剩下的都是有效请求。而这些有效请求中,又有9个是JS的请求,有8个是IMG,还有一些其它的请求。

我们大概可以评估出一个页面可能有77%的静态资源。一般静态资源请求的变化比较少,我们不希望浏览器去重复下载一些相同的资源,所以我们就会采用到浏览器缓存来优化我们的页面。

我们一般通过配置一些http请求头去控制我们的缓存策略,然后通过版本号来更新我们的资源。

但在我看来,这样的流程存在着3个小问题。

缓存机制不足

更新不可靠。由于CDN的更新不是实时的,很多时候我们的资源已经发布到线上了,它的CDN还没有更新。

离线体验不佳。现在的浏览器缓存在离线体验上是不好的,明明已经缓存在本地了,但是断开网络打开页面之后还是会显示未连接到互联网。

不可定制化,例如无法增量更新。现在的浏览器缓存主要是通过配置,但如果需要实现一些自定义的策略是做不到的。

Service Worker

ServiceWorker是浏览器为了解决之前AppCache在管理离线缓存上的不足,而提供的在Web应用程序与服务器之间的代理层。

总的来说,Service Worker就是一段在浏览器后台自动运行的程序,负责协助浏览器,管理和响应所有从Web应用发出的请求,以达到更好的离线体验。

性能有所增强,比如预取并缓存用户可能需要的资源,比如页面中所需的静态资源文件;可以同步后台数据同步;响应来自其它源的资源请求;集中接收计算成本高的数据更新;后台服务钩子;自定义模板用于特定URL模式以及可以在客户端进行模块编译和依赖管理。

等待状态

到达installed态的Service Worker并不会直接进入activating态,如果浏览器中还有其他页面运行着该Service Worker的一个旧版本,那么新的Service Worker就会处于等待的状态,直到其他页面关闭。这主要是为了避免Service Worker中所使用到的资源被意外释放。

一旦其他相关页面都关闭了,就意味着旧的资源文件已经不再需要。这时候我们就可以执行下一步清理的工作。

Activate事件

Fetch事件

MoggyCache离线包管理

QQ钱包团队搭建了一套MoggyCache离线包管理系统。通过这套系统我们可以针对项目配置当前项目需要用到的静态资源。并且配置了离线包当前是否开启,或者是针对灰度用户进行开启。都可以配置到这个平台上,而且存储在内部的一个DB上。

MoggyCache工作原理

我们的node.js服务通过读取上述的配置动态生成了两个脚本,一个是install脚本,一个是worker脚本。

install脚本主要是读取离线包当前的一个开关以及它当前灰度用户的策略,来判断当前用户是否需要安装我们的离线包。

一旦判断出用户需要安装离线包,它就会通过注册的过程把worker脚本注册成当前页面的Service Worker。而这个worker就会把配置里的资源列表下发到worker脚本里面。Worker就会走一遍流程把这些资源加载并缓存在本地。

MoggyCache新增特性

以上过程仅仅是简化了我们的一些工作,还是没有解决问题。所以我们在这基础之上又新增了它的几个特性。

自动同步

我们每次配置一个项目的时候,会计算出所有资源的md5,并且存储在DB里面。然后我们的node.js服务就会读取到刚才的配置,把md5下发到刚才的Service Worker里面。

现在我们更新资源需要进行发布的时候,在发布系统上面添加了一个后置脚本,一旦资源发布,这个后置脚本就会触发离线包系统,去重新计算每一个资源的md5,并重新推送到Service Worker。

这时Service Worker就有了两个md5,一个是旧版本的md5,一个是当前最新的版本。通过对比这两个md5,我们就知道哪些资源已经过期了。当发现了过期的资源,Service Worker就会重新到服务器上拉取最新资源。整个过程是自动的,无需人工干预。这就解决了不可靠的问题。

增量更新

每当有新资源发布的时候,我们都会通过后置脚本的方式通知MoggyCache系统。它就会读取新的资源并进行计算,算出格式的增量包,然后把增量包存储在服务里面。

因为md5已经更新了,所以worker脚本就会重新发送请求到我们的服务。这时如果服务发现资源有可用的增量包,就会把这个增量包直接返回给Service Worker。Service Worker通过判断请求头就可以执行不同的策略。

接入层服务架构

在QQ钱包成立初期,我们使用的接入层架构是PHP + APACHE。当时PHP的版本非常成旧,我们需要开20台服务器才能完成所有请求的响应,而单机的QPS只有200。

从这些数据里可以看出性能还是不够好。再加上PHP用了腾讯内部编写的一些私有模块,各个模块之间又有不同的版本,导致它还有部署成本高,扩容困难,apache日志缺漏,web服务缺乏监控等一系列问题。

经过一段时间的考察,我们最终选择了NODEJS。

选择NODEJS的原因

性能优异:node.js采用的是基于libuv库的异步io方案,相比apache的多进程同步阻塞方案在性能上的提升明显的。

前端友好:前端熟悉js的语法,对node.js可以平滑过度,培养新同学更为简单容易。

社区成熟:成熟的社区和完善的技术文档,大量的成熟模块可以为业务使用。

选择自研框架的原因

应用场景:我们的MoggyServer服务,主要的使用场景是页面直出。

更加可控:自研的框架,更加可控,扩展性更加强,这些都是我们需要考虑的。

稳定和快速:社区里的框架大多会包含类似静态文件处理,json数据处理等额外的功能,这并不是我们想要的。

服务平滑重启

我们把服务器平滑重启的逻辑内置到框架里面。通过在发布系统上配置一个后置脚本来通知node.js的子进程有新的文件要发布,并在子进程接收到消息之后把这些消息通知发送给旧的子进程,它就会停止对外服务。

因为新的代码已经发布到线上,就可以用新的代码重新创建新的子进程。旧的子进程把原本还在服务的用户处理完后就会把自己注销掉,整个过程就能达到平滑的效果。

模版引擎优化

我们用积分将一个业务的页面进行10000次渲染,然后统计它所花费的时间。

这里我们主要是对ejs的模板嵌套语法做了精简,所以有了性能上的提升。

用传统的ejs渲染需要7500毫秒,而用tpl渲染只需要920毫秒。这就是我们做的模版引擎的优化。

MoggyServer线上数据

QQ钱包现在只运行了7台服务器,就完成了上千万级别的服务量。单机QPS从200已经提升到了900。2017年初,我们的总请求数峰值已经到达了1.69亿,申请了57台机器去支撑,但每台机器的CPU只用了30%。

直出页面加载

传统页面加载方案:从用户点击入口,native再去拉起webview,等待webview初始化完成后发送http请求去node服务拉取页面数据,最后对页面进行渲染。

SONIC优化方案

串行改并行

相对传统加载方案中,优化方案在native执行时候实例化webview,同时并行向sonic服务器发起请求,将此前的串行操作优化为并行,因此此处耗时由sum(webview,request)转变成max(webview,request),降低了客户端层面的耗时。

页面缓存

sonic支持对h5页面级进行本地缓存,将返回的页面分别拆分成数据层以及模版层层分开来缓存,生成本地缓存文件,且缓存时长为永久缓存,如果页面是没有任何变化,这时候会完全显示缓存的数据。

增量更新

对于页面更新的情况,sonic会去对比和计算客户端缓存中的页面的变更地方,封装成json数据结构返回给客户端进行页面更新以及缓存更新,这样可以大大减小了回包的大小,特别对于移动网络而言可以大幅度为用户节省了请求流量。

我的分享就到这里,谢谢大家!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容