转载

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

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

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

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

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

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

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

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

整体架构

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

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

而动态化方案的整体架构如下图所示,分为三大系统: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。

前端展示系统

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

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

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

展示系统的伪代码

--1、加载Lua模块库 local template = require("resty.template") template.load = function(s) return s end   --2、动态获取模板 local myTemplate = "<html>{* title *}</html>" --3、动态获取数据 local data = {title = "iphone6s"}   --4、渲染模板 local func = template.compile(myTemplate) local content = func(data)   --5、通过ngx API输出内容 ngx.say(content)

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

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

控制系统

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

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

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

数据和模板动态化

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

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

多版本机制

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

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

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

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

异常问题

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

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

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

原文  http://jinnianshilongnian.iteye.com/blog/2289767
正文到此结束
Loading...