闲鱼源码页面SSR最佳实践

简介: 今朝我又快又稳

作者:闲鱼技术——凌均

背景

「让每一个用户在最短的时间内看到页面上重要的内容」一直以来都是前端工程师们精益求精的方向。对于一个H5的源码页面,我们已经有了很多缩短首屏渲染时间的方法,比如数据预取,离线缓存。但在目前看来,由于数据预取和离线缓存都依赖客户端的能力,很多时候会给我们带来一些限制。比如用于增长业务的外投拉新页面,我们并不能知晓第三方APP是否具备这样的能力。再比如使用离线缓存能力,我们受制于命中率高低,以及缓存对APP性能带来的负面影响这样的问题。

服务端渲染,让最重要的内容和用户之前,只需要请求HTML DOC的时间,并且不依赖于客户端的能力,可以大大缩短用户看到页面首屏内容的时间。

方案要点

目前主流前端框架比如React,都已经提供了支持SSR的API,我们可以只用几行代码便将一段原本执行在客户端的绘制UI的逻辑转化为可以在Node层直出HTML的功能。在此基础之上,一个SSR技术方案应该同时做到以下几点要求:

  • 页面首屏有效绘制(FMP)时间变短:从webview发出页面url请求,到用户看到首屏有效内容的时间真实变短。

  • 应用稳定性高,运维成本低:保证由Node应用提供前端页面,尽可能跟已经非常成熟的「CDN缓存前端静态资源 + Java服务提供首屏数据」有相近的稳定性。并且Node服务一旦出现不可用的情况,页面能够自动降级到稳定的CSR(当下H5页面都在用的客户端渲染)模式,而不需要工程师手动执行降级。


  • 低研发成本:采用SSR以后,前端工程师仍然只需要关心业务功能的实现,而无需为满足稳定性要求增加额外开发成本。

本文将重点介绍闲鱼的SSR方案围绕这三个要点进行了怎样的设计。

技术架构

先来看下闲鱼目前SSR架构整体的设计,再来单独聚焦每一个功能点的实现。

image.png
如图,架构设计分别考虑了用户正常访问的SSR链路(红色结点),以及SSR应用不可用时自动降级到的CSR链路(蓝色结点)。用CSR链路作为SSR失败时的降级兜底方案,是保证SSR方案稳定性的关键点。

SSR链路

基于serverless的node应用


随着阿里Serverless生态建设的不断完善,前端同学开发Node应用,已经不需要像面对传统Node应用一样,花费太多时间来运维Node应用。我们可以凭借「函数即服务」的FaaS能力,聚焦于Node应用本身功能的实现。


为了实现SSR功能我们需要在Node层实现两个服务:

  • 数据聚合。一个前端页面首屏需要的数据,可能来自于多个服务端(Java)的接口。我们在Node层实现一个Service,该Service调用首屏依赖的所有服务端接口,将其汇聚为一个接口,输出全部首屏数据。这种由Node层实现数据胶水的设计,同时可以降低前端与服务端开发协作的成本。前端只需要得到服务端原子功能级别的数据,便可以根据UI的需要按照自己方便的方式定义最终输出的数据结构。

  • 直出HTML页面(HTTP服务)。当用户访问某个URL时,Node应用获取页面构建产物,同时调用上条提到的首屏数据接口,将返回的数据用于生成页面的DOM树。


SSR应用网关


当需要发布某一个前端应用,或者当某一个应用不可用时,我们肯定不希望影响到其他的应用。所以我们在业务维度,将跟某个特定业务相关联的前端功能作为独立的Node应用单独维护。那么,为什么我们还需要一个公共的网关为应用提供服务,而不是每一个应用单独向用户提供服务呢?


原因是每一个对用户开放的HTTP服务,都必须接入集团的「统一接入」机制。统一接入承载了转发、负载均衡、安全认证等多种必不可少的功能。接入的整个流程,包括应用架构的评审、域名的配置、其他安全机制的确认等等需要1~2个工作日。而由于我们不断会有新的业务、新的项目,为每一个新应用都走一遍统一接入是要消耗大量人力成本且没有必要的。因而我们在所有Node应用之上,架设网关应用,利用Nginx根据访问path的不同,将用户的请求分发到不同的应用上。网关本身作为CDN回源的源站。

CDN边缘节点


CDN可以将源站上的资源缓存到距离客户端最近的CDN节点上。当用户访问该静态资源时,直接从缓存中获取,避免通过较长的链路回源,提高访问效率。这个过程被称为「CDN加速」。
除了资源加速之外,阿里云的CDN节点还提供了基于Serverless的边缘计算能力,简单来说,就是除了缓存静态文件,CDN还可以作为JavaScript脚本的运行环境。这让Node服务的稳定性还没有达到业务的要求时,前端工程师可以通过在CDN节点上部署JavaScript代码,让CDN节点完成一定的功能。CDN边缘程序、边缘缓存和源站的链路如下图。

image.png


对于SSR来说,CDN边缘程序实现的功能非常简单:当获取SSR页面成功时(status 200),将直出的页面返回给用户,否则访问降级页面CSR的地址,保证用户永远能够看到正确的页面。我们将CDN缓存周期设置为5分钟。缓存生效时,用户访问链路为上图紫色部分所示,缓存失效时,为红色链路。


自此,我们就解释了开始时3个问题的前2个:怎么保障Node应用稳定性,以及怎么进行页面降级。


CSR链路


CSR降级链路虽然不经常被用户覆盖到,但对于整个方案来说仍然很重要。用户访问CSR页面时,首先从air源站获取到html页面(此时页面中没有任何首屏内容),然后执行html页面中引入的JS脚本,调用获取首屏数据的mtop接口(阿里弹外异步请求数据获取接口)进行页面渲染。因而对于CSR链路的实现,我们只需要关心两件事情:

  • 静态资源文件需要构建并推送到air。
  • 需要有在Web端可以被调用的Ajax接口(在阿里一般被称为mtop接口)。


对于第一点,我们可以在应用构建和发布的时候,直接将只有layout内容的HTML模板发布。对于第二点,我们可以复用SSR链路时开发的首屏数据接口,直接将其对接集团对外的网关,无需二次开发,如下图所示。


image.png




由此可以让整个链路全部由前端同学完成,无需像传统CSR页面开发那样由服务端同学提供mtop接口。




实现SSR链路和CSR链路之后,我们已经满足了3个关键要素中的前2个:


FMP时间缩短


SSR链路中,用户访问到首屏有效内容的时间为:

  • CDN缓存命中时:HTML页面 RT。
  • CDN缓存未命中时:Node服务直出页面执行时间 + HTML页面RT


CSR链路中,用户访问到首屏内容的时间为:

  • HTML页面RT + JS文件下载&执行时间 + 首屏mtop接口 RT + 首屏内容DOM内容生成时间




线上数据为:
image.png


稳定性高、运维成本低:
**
应用之间的研发、发布及运行的隔离,使得每个研发同学不需要担心自己应用的稳定性会受其他应用的影响;CDN对请求的缓存,使得即使缓存时间只有1分钟,Node应用也只在每60s才被CDN回源一次,大大降低了流量高峰时对Node服务稳定性的考验;以及CDN边缘程序的自动降级逻辑,使得SSR链路失败时,应用自动降级为CSR模式,不影响用户对页面的访问,不需要研发同学手动运维。


应用结构


我们在应用结构的设计上,尽可能降低了前端同学研发的成本。当CSR降级链路与请求转发的功能全部发布之后,每次前端新增一个新的项目,前端开发同学只需要根据应用模板开发相应的业务功能,无需关心稳定性保障链路。并且只需要开发一份前端源码,便可以构建出用于不同场景的产物。我们的应用结构设计如下图所示:


image.png


Node层接口在发布时会被部署到Serverless服务市场。网关的对接等功能均可以通过配置的方式直接完成。


后续


可灰度、可监控、可回滚是前端应用稳定性保障的三要素,SSR应用也不例外。目前闲鱼的SSR应用已经实现了可回滚与可监控,接下来我们将为它设计可靠性强、操作方便的灰度方案。










相关文章
|
运维 Kubernetes 安全
|
存储 JavaScript 前端开发
盘点主流 Flutter 状态管理库2024
状态管理是每个应用不可缺少的,本文将会盘点下主流的状态管理包。
752 2
盘点主流 Flutter 状态管理库2024
|
前端开发 应用服务中间件 nginx
Next.js 创建项目到服务器部署(目录结构介绍、项目结构Demo、开发细节注意)
Next.js 创建项目到服务器部署(目录结构介绍、项目结构Demo、开发细节注意)
1834 0
|
7月前
|
存储 关系型数据库 数据库
附部署代码|云数据库RDS 全托管 Supabase服务:小白轻松搞定开发AI应用
本文通过一个 Agentic RAG 应用的完整构建流程,展示了如何借助 RDS Supabase 快速搭建具备知识处理与智能决策能力的 AI 应用,展示从数据准备到应用部署的全流程,相较于传统开发模式效率大幅提升。
附部署代码|云数据库RDS 全托管 Supabase服务:小白轻松搞定开发AI应用
|
前端开发 Go 网络安全
Go语言:xterm.js-websocket Web终端堡垒机
1.前言 因为公司业务需要在自己的私有云服务器上添加添加WebSsh终端,同时提供输入命令审计功能. 从google上可以了解到xterm.js是一个非常出色的web终端库,包括VSCode很多成熟的产品都使用这个前端库.
7440 0
|
9月前
|
人工智能 安全 数据处理
CodeBuddy实现pdf批量加密
通过 CodeBuddy 实现 PDF 批量加密小工具,有效解决了当前 PDF 加密存在的痛点,为用户提供了一种高效、便捷、低成本的 PDF 加密解决方案。在未来,随着数据安全需求的不断提升,相信 CodeBuddy 将在更多数据处理场景中发挥重要作用,助力用户轻松应对各类信息安全挑战。
227 8
|
弹性计算 小程序 关系型数据库
阿里云虚拟主机配置版本选择,共享独享、基础、标准、高级和豪华选择攻略
阿里云虚拟主机提供共享与独享版本,后者包括基础、标准、高级和豪华四种配置。选择依据为网站访问量及图片数量。独享型主机具备独立CPU、内存和带宽,利于SEO。基础版适合个人展示,标准版适用于企业官网,高级版适合博客论坛,豪华版则针对多媒体展示网站。然而,考虑到性价比,云服务器可能是更优选择,其不仅限于网站搭建,还支持多种应用场景,如小程序、App和游戏服务器等。
|
XML Java 数据格式
Spring IOC的源码解析
【4月更文挑战第17天】Spring IOC(控制反转)的核心功能是通过依赖注入(DI)来管理对象的创建和它们之间的依赖关系。要深入理解Spring IOC的工作原理,我们可以从其源码分析入手,特别是关注如何创建和管理Bean以及依赖注入的实现
229 1
|
网络协议 网络性能优化 网络虚拟化
【亮剑】介绍了华为三层交换机的配置命令,包括基本配置(系统启动、接口配置、基础设置)、路由协议(OSPF、BGP)配置和高级功能(VLAN、ACL、QoS)配置
【4月更文挑战第30天】本文介绍了华为三层交换机的配置命令,包括基本配置(系统启动、接口配置、基础设置)、路由协议(OSPF、BGP)配置和高级功能(VLAN、ACL、QoS)配置。通过这些命令,网络工程师可以有效地管理设备、优化网络性能并解决网络问题。熟练掌握这些命令对于提升网络运行效率至关重要。
1230 2
|
关系型数据库 MySQL 数据库
数据的正确性和完整性:解析MySQL中的一致性
一致性是数据库事务的四个ACID特性之一,包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。在数据库管理中,一致性确保了事务的执行能够维持数据库的正确性和完整性。
2053 0