Serverless 中文社区采访

1,504 阅读8分钟

1、请您向读者做一下自我介绍。

蒋林源,就职于腾讯在线教育,腾讯高级前端工程师,IMWeb 团队成员,腾讯企鹅辅导 SSR 应用负责人,在多端、Node、复杂 Web 应用性能优化方面拥有丰富的实践经验。


2、请简要的介绍一下您所在的团队(比如技术栈、负责的业务、前后端分工?不用涉及细节)

  • IMWeb 团队隶属腾讯公司,是国内最专业的前端团队之一。
  • 我们专注前端领域多年,负责过 QQ 资料、QQ 注册、QQ 群等亿级业务。
  • 目前聚焦于在线教育领域,精心打磨 腾讯课堂、企鹅辅导及ABCmouse三大产品。

3、基于什么背景和问题,使您的团队考虑采用SSR的技术方案?


团队在传统的 Web 应用方向其实有很多技术方面的尝试,包括传统离线包、PWA 离线应用等,但是每个技术栈都有其优点与缺点,目前团队的技术方案对比如下:
image.png
从上述表格可以看到,SSR 在首屏渲染以及 SEO 等方面都有不错的表现,这也是团队想在 SSR 技术方面深挖的初衷。

4、您的团队使用SSR技术方案时,有没有进行一些调研?基于什么考虑让你们决定选择现在的方案。


主要从两个方面来考虑:
一、SSR 应用的性能
我们知道类 React 的应用的 SSR 的本质为在服务端调用 React 的 renderToString 方法将 React 组件渲染成 HTML 字符串,那么对于复杂的 SSR 应用来说,可能存在大量的 CPU 密集型计算,这并不是 Node 所擅长的领域,那么如何优化这方面的性能问题也是我们所关注的重点。
同时因为离线包的环境依赖性(依赖 App),那么在传统的 Web 环境内是否可以有一套完整的解决方案来缓存相关的页面,从而提高首屏的性能,也是关注点之一。

二、SSR 的运维成本
对于大多数前端工程师来说,在服务的运维方面都可能有时并不那么得心应手,所以在服务的可用性方面,也是在做技术选型时所考虑的重点方向之一。

根据以上两个方面,可以把我们的考虑因素总结为以下两个点:

image.png

5、能否从技术角度进行分享,目前在您团队中使用的SSR方案是什么样的?基于什么样的架构,有哪些模块?

先从整体来了解下团队 SSR 技术的架构图:
image.png

接下来我们从以下几个方面来详细讲解下团队现有方案。

代码组织

我们在 PC/H5 项目中均采用了同构的模式来构建 SSR 应用。
image.png

在同构的模式下面,业务开发者更关注与业务的功能本身,而不用太过关心运行时的问题,但是也要注意以下几个问题:
1、传统浏览器中的常量使用,比如 windowdocument 等。
2、http 数据请求库必须同时支持服务端和客户端。
3、合理使用 React 应用的生命周期。
4、通过注入环境变量来区分当前运行时环境。

性能优化

① 接口动静分离

我们知道页面的渲染一般要依赖于后端的相关数据,数据这里可以拆分为两个部分:动态数据静态数据
静态数据指的是页面中不经常变更的数据,比如企鹅辅导产品产品的课程标题、课程描述等;
动态数据指的是页面种与用户登录态相关的数据,比如课程是否已经购买、当前课程的折扣等。

对接口做动静分离的意义在于,我们可以利用静态数据的时延性敏感度低的特性做缓存,在服务端利用静态数据渲染页面,之后在服务端利用动态数据做二次渲染,主要逻辑如下:
image.png

我们利用 Redis 对静态数据渲染出来的页面做缓存,这样不仅可以加快 SSR 的渲染时间,同时可以提高单机的 QPS(renderToString 在一定意义上为 CPU 密集型操作)。

② 浏览器中利用 PWA 做离线缓存

image.png
同时在客户端中,我们可以利用 PWA 来做离线缓存,缓存静态数据直出的 HTML 页面,从而进一步的提高了直出页面的首屏性能。

运行上下文

因为后端应用的运维复杂性、维护成本较高等问题,这里我们使用了 Serverless(腾讯云 SCF) 来做直出应用的部署。
得益于 Serverless 架构模式的天然优势,我们不用在关心服务的运维、服务的扩容等问题,这也是我们为什么选择其的重要原因。
image.png
如上图所示,我们 SSR 应用本质为一个 Node 应用,但是 SCF 的调用本质为一个 Event 事件,那么如何去兼容这两种模式呢?这里我们对自研 Node 框架(imserver)做了一层 Serverless 的封装,在入口做了 Event 到 Koa Request Context 的兼容。
image.png

6、SSR的技术方案,最终落地过程是否顺畅,是否遇到了一些问题,是如何解决的?

① 云函数拆分

我们业务中有多个页面是通过 SSR 来实现的,采用了 SCF 来做 SSR 之后,就会遇到一个问题:是合并到一个云函数中(业务级),还是拆分为多个云函数(页面级)。
答案肯定是页面级会比较好,主要的优点如下:
1、云函数互相独立,假设页面 A 云函数 挂掉,并不会影响到业务 B 的云函数。
2、云函数包的大小会降低,因为 SCF 的冷启动过程,代码的包的大小对函数的冷启动时间也有一定的影响。
image.png
这里我们基于当前的项目做了云函数的自动化构建,通过 .scfssr.json 的配置文件自动生成相应的云函数,对现有的开发是没有任何影响的,只是在构建的时候生成多个云函数,这样既降低了应用的维护成本,又降级了应用的开发成本。
同时得益于云函数的构建过程,我们可以对单个云函数的代码做瘦身,通过对 package.json 中的依赖分析,剔除一些云函数容器中已经内置的工具包,以及对云函数所依赖的第三方包做相应的引入分析,去重冗余。

② 云函数发布优化

image.png
上图为我们设计的基于 SCF 的多云函数直出方案逻辑,可以看到当我们有版本更新的时候,其实发布流程还是比较复杂的,步骤也是相当繁琐:
image.png
那么如何去优化云函数的发布流程呢?这里我们基于腾讯云所提供的 Node SDK 做了一键发布 SCF 的工具:
image.png
一个完整的 SCF SSR 应用生命周期如下:
image.png

7、目前的SSR方案推动了您所在团队哪些协作模式或分工的优化?

利用基于 SCF 的 SSR 方案,节省了不少的服务运维成本,得益于腾讯云的日志系统,所有的单个 SSR 应用请求在日志平台都有完整的链路,定位问题与处理问题的速度都有了质的提升。

8、从您的视角,目前的SSR方案是否还需要一些改进支出?

因为 Serverless 的架构模式会存在冷启动时间较长的问题,虽然腾讯云 SCF 在这方面已经做了很多的技术优化,比如预启动容器等,但是我们在业务方面也可以尝试优化,我们在接入层做了服务的降级优化:
image.png
后续的优化方案可以从灰度、多维降级等方面来做改进。

9、请给其他还没做SSR的团队几条建议。

如果想追求更好的用户体验,建议针对核心业务做 SSR 优化,搭配 Serverless 来做服务的部署于运维,有了 Serverless 的丰富配套,我们可以不用像以前一样关心机器的运维和扩容,可以大大的提高团队生产力。
同时,有了 SSR 之后,也建议大家可以完善自己业务的 devops 流程,将整个研发链路打通,从开发到测试再到部署都可以高效进行。
最后也推荐大家使用业务接入层来做服务降级,提高 SSR 应用的可用性。

欢迎关注我们: