应用数据静态化架构高性能单页Web应用

Posted 21CTO

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了应用数据静态化架构高性能单页Web应用相关的知识,希望对你有一定的参考价值。

在电商网站中,单页Web是非常常见的一种形式,比如首页、频道页、广告页等都属于单页应用。而这种页面是由模板+数据组成。传统的构建方式一般通过静态化实现。而这种方式的灵活性并不是很好,比如页面模板部分变更了需要重新全部生成。因此最好能有一种实现方式是可以实时动态渲染,以支持模板的多变性。另外也要考虑好如下几个问题:

1、动态化模板渲染支持;

2、数据和模板的多版本化:生产版本、灰度版本和预发布版本;

3、版本回滚问题,假设当前发布的生产版本出问题了如何快速的回滚到上一个版本;

4、异常问题,假设渲染模板时遇到了异常情况(比如获取Redis出问题了),如何处理;

5、灰度发布问题,比如切20%量给灰度版本;

6、预发布问题,目的是在正式环境测试数据和模板的正确性。

 

整体架构

静态化页面的方案如下图所示:


直接将生成的静态页推送到相关服务器即可。使用这种方式要考虑文件操作的原子化问题(即从老版本切换到新版本如何做到文件操作原子化)。

 

而动态化方案的整体架构如下图所示,分为三大系统:CMS系统、控制系统和前端展示系统。

应用数据静态化架构高性能单页Web应用
 

CMS系统

1、在CMS系统可以配置页面的模板和数据;

1.1、模板动态在CMS系统中维护,即模板不是一个静态文件,而是存储在CMS中的一条数据,最终发布到“发布数据存储Redis”中,前端展示系统从Redis中获取该模板进行渲染,从而前端展示系统更换了模板也不需要重启,纯动态维护模板数据;

2、原始数据存储到“元数据存储mysql”中即可,比如频道页一般需要:前端访问的URL、分类、轮播图、商品楼层数据等;这些数据按照相应的维度存储在CMS系统中;

3、提供发布到“发布数据存储Redis”的控制,将CMS系统中的原始数据和模板数据组装成聚合数据(JSON存储)同步到“发布数据存储Redis”,以便前端展示系统获取进行展示;此处提供三个发布按钮:正式版本、灰度版本和预发布版本。

 

目前存在如下几个问题:

1、用户如访问http://channel.jd.com/fashion.html怎么定位到对应的聚合数据呢? 我们可以在CMS元数据中定义URL作为KEY,如果没有URL,则使用ID作为KEY,或者自动生成一个URL。

2、多版本如何存储呢? 使用Redis的Hash结构存储即可,KEY为URL(比如http://channel.jd.com/fashion.html),字段按照维度存储:正式版本使用当前时间戳存储(这样前端系统可以根据时间戳排序然后获取最新的版本)、预发布版本使用“predeploy”作为字段,灰度版本使用“abVersion”作为字段即可,这样就区分开了多版本。

3、灰度版本如何控制呢?这个通过控制系统的开关来控制如何灰度;

4、如何访问预发布版本呢?比如在URL参数总带上predeploy=true,另外可以限定只有内网可以访问或者访问时带上访问密码,比如pwd=absdfedwqdqw。

5、模板变更的历史数据校验问题?比如模板变更了,但是使用历史数据渲染该模板会出现问题,即模板要兼容历史数据的;此处的方案不存在这个问题,因为每次存储时是当时的模板快照,即数据快照和模板快照推送到“发布数据存储Redis”中。

 

前端展示系统

1、获取当前URL,使用URL作为KEY首先从本机“发布数据存储Redis”获取数据;

2、如果没有数据或者异常则从主“发布数据存储Redis”获取;

3、如果主“发布数据存储Redis”也发生了异常,那么会直接调用CMS系统暴露的API直接从元数据存储Mysql中获取数据进行处理。

 

展示系统的伪代码

Java代码  

  1. --1、加载Lua模块库  

  2. local template = require("resty.template")  

  3. template.load = function(s) return s end  

  4.    

  5. --2、动态获取模板  

  6. local myTemplate = "<html>{* title *}</html>"  

  7. --3、动态获取数据  

  8. local data = {title = "iphone6s"}  

  9.    

  10. --4、渲染模板  

  11. local func = template.compile(myTemplate)  

  12. local content = func(data)  

  13.    

  14. --5、通过ngx API输出内容  

  15. ngx.say(content)  

即模板和数据都是动态获取的,然后使用动态获取的模板和数据进行渲染。

 

此处假设最新版本的模板或数据有问题怎么办?这个可以从流程上避免:1、首先进行预发布版本发布,测试人员验证没问题后;2、接着发布灰度版本,在灰度时自动去掉CDN功能(即不设置页面的缓存时间),发布验证OK;3、发布正式版本即可;正式版本发布的5分钟内是不设置页面缓存的,这样就可以防止发版时遇到问题,但是问题版本已经在CDN上给全部用户造成问题。当然这个流程很麻烦,可以按照自己的场景进行简化。

 

控制系统

控制系统用于版本降级和灰度发布的,当然可以把这个功能放在CMS系统中实现。

版本降级:假设当前线上的版本遇到问题了,想要快速切换回上一个版本,可以使用控制系统实现,选中其中一个历史版本然后通知给前端展示系统即可,使用URL和当前版本的字段即可,这样前端展示系统就可以自动切换到选中的那个版本;当问题修复后,再删除该降级配置即切换回最新版本。

灰度发布:在控制系统控制哪些URL需要灰度发布和灰度发布的比例,同版本降级类似将相关的数据推送到前端展示系统即可,当不想灰度发布时删除相关数据即可。

 

数据和模板动态化

我们将数据和模板都进行动态化存储,这样可以在CMS进行数据和模板的变更;实现了前端和后端开发人员的分离;前端开发人员进行CMS数据配置和模板开发,而后端开发人员只进行系统的维护。另外因为模板的动态化存储,每次发布新的模板不需要老重启前端展示系统,后端开发人员更好地得到了解放。

 

模板和数据可以是一对多的关系,即一个模板可以被多个数据使用。假设模板发生变更后,我们可以批量推送模板关联的数据,首先进行预发布版本的发布,测试人员进行验证,验证没问题即可发布正式版本。

 

多版本机制

我们将数据和模板分为多版本后,可以实现:

预发布版本:更容易让测试人员在实际环境进行验证;

灰度版本:只需要简单的开关控制,就可以进行A/B测试;

正式版本:存储多个历史正式版本,假设最新的正式版本出现问题,可以非常快速的切换回之前的版本。

 

异常问题

其中一个担心就是本机从“发布数据存储Redis”和主“发布数据存储Redis”都挂了,那么我们直接调用CMS系统暴露的HTTP服务直接从元数据存储Mysql获取数据。

 

另外一个担心是数据和模板获取到了,但是渲染模板出错了,比如遇到500、503;解决方案是:使用上一个版本的数据进行渲染。

 

另外还一种问题是数据和模板都没问题,但是因为一些疏忽,渲染出来的页面错乱了或者有些区域出现了空白;对于这种问题没有很好的解决方案;可以根据自己的场景定义异常扫描库,扫描当前版本有异常就发警告给相关人员,并自动降级到上一个版本。


来源:开涛的博客


 关于21CTO平台 

21CTO是中国互联网第一技术学习与服务平台。为CTO、技术总监,技术专家,架构师、技术经理,研发工程师等提供学习成长,工作机会、个人增值等高价值服务。

欢迎您注册为21CTO会员,成为专栏作者,有机会加入专家讲师与技术顾问团队等。


以上是关于应用数据静态化架构高性能单页Web应用的主要内容,如果未能解决你的问题,请参考以下文章

可扩展的web单页应用程序架构

页面静态化缓存应用(OpenResty+nginx_srcache+redis)

为啥在编排的容器化架构中,我们需要一个 Web 服务器和一个应用服务器?

网站架构

性能优化+架构迭代升级 Go读书社区web开发与架构优化(完整)微心:NoBug1024

软考 系统架构设计师案例分析⑥ Web应用系统架构设计