Repractise架构篇一: CMS的重构与演进

重构系统是一项很是具备挑战性的事情。一般来讲,在咱们的系统是第二个系统的时候才须要重构,即这个系统自己已经很臃肿。咱们花费了太量的时间在代码间的逻辑,开发新的功能变得愈来愈慢。这不只仅可能只是由于咱们以前的架构没有设计好,并且在咱们开发的过程当中没有保持着原先设计时的一些原则。若是是这样的状况,那么这就是一个复杂的过程。html

还有一种状况是咱们发现了一种更符合咱们当前业务的框架。git

动态CMS

CMS简介

CMS是Content Management System的缩写,意为"内容管理系统".它能够作不少的事情,可是总的来讲就是Page和Blog——即咱们要建立一些页面能够用于写一些About US、Contact Me,以及持续更新的博客或者新闻,以及其余子系统——一般更新不活跃。经过对这些博客或者新闻进行分类,咱们就能够有不一样的信息内容,以下图:github

不一样分类的内容

CMS是政府和企业都须要的系统,他们有不少的信息须要公开,而且须要对其组织进行宣传。在我有限的CMS交付经验里(大学时期),通常第一次交付CMS的时候,已经建立了大部分页面。有时候这些页面可能直接存储在数据库中,后来发现这不是一个好的方案,因而不少页面变成了静态页面。随后,在CMS的生命周期里就是更新内容。web

于是,CMS中起其主导的东西仍是Content,即内容。而内容是一些持续可变的东西。这也就是为何WordPress这么流行于CMS界,它是一个博客系统,可是多数时候咱们只须要更新内容。除此不得不说起的一个CMS框架是Drupal,二者一对比会发现Drupal比较强大。一般来讲,强大的一个负做用就是——复杂。数据库

WordPress和Drupal这一类的系统都属于发布系统,而其后台能够称为编辑系统。django

通常来讲CMS有下面的特色:segmentfault

  • 支持多用户。api

  • 角色控制-内容管理。如InfoQ的编辑后台就会有这样的机制,社区编辑负责建立内容,而审核发布则是另外的人作的。缓存

  • 插件管理。如WordPress和Drupal在这一方面就很强大,基本能够知足平常的须要。架构

  • 快捷简便地存储内容。简单地来讲就是所见即所得编辑器,可是对于开发者来讲,Markdown彷佛是好的选择。

  • 预发布。这是一个很重要的特性,特别是若是你的系统后台没有相对应的预览机制。

  • 子系统。因为这属于定制化的系统,并不方便进行总结。

  • ...

CMS一直就是这样一个紧耦合的系统。

CMS架构与Django

提及来,我一直是一个CMS党。主要缘由还在于我能够为所欲为地去修改网站的内容,修改网站的架构。好的CMS总的来讲都有其架构图,下图彷佛是Drupal的模块图

Drupal 框架

通常来讲,其底层都会有:

  • ORM

  • User Management

  • I18n / L10n

  • Templates

我一直在使用一个名为Django的Python Web框架,它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,便是CMS(内容管理系统)软件。它是一个MTV框架——与多数的框架并无太大的区别。

层次 职责
模型(Model),即数据存取层 处理与数据相关的全部事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
模板(Template),即表现层 处理与表现相关的决定: 如何在页面或其余类型文档中进行显示。
视图(View),即业务逻辑层 存取模型及调取恰当模板的相关逻辑。模型与模板之间的桥梁。

从框架自己来上看它和别的系统没有太大的区别。

Django Architecture

可是若是咱们已经有多外模块(即Django中app的概念),那么系统的架构就有所不一样了。

Django App架构

这就是为什么我喜欢用这个CMS的缘由了,个人每一个子系统都以APP的形式提供服务——博客是一个app,sitemap是一个app,api是一个app。系统直接解耦为相似于混合服务的架构,即不像微服务同样多语言化,又不会有宏应用的紧耦合问题。

编辑-发布分离

咱们的编辑和发布系统在某种意义上紧耦合在一块儿了,当用户访问量特别大的时候,这样会让咱们的应用变得特定慢。有时候编辑甚至发布不了新的东西,以下图引示:

发布-编辑

或者你认识出了上图是源自Martin Folwer的编辑-发布分离

编辑-发布分离是几年前解耦复杂系统游来开来带来的一个成果。今天这个彷佛已经很常见了,编辑的时候是在后台进行的,等到发布的时候已经变成了一个静态的HTML。

已经有足够多的CMS支持这样的特性,运行起来彷佛特别不错,固然这样的系统也会有缓存的问题。有了APP这后,这个趋势就更加明显了——人们须要提供一个API。究竟是在现有的系统里提供一个新的API,仍是建立一个新的API。

这时候,我更愿意选择后者——毕竟紧耦合一个系统总会在后期带来足够多的麻烦。并且基于数据库构建一个只读的RESTful API并非一个复杂的过程,并且也危险。这时候的瓶颈就是数据库,可是彷佛数据库都是多数系统的瓶颈。人们想出了各类各样的技术来解决这个瓶颈。

因而以前我试着用Node.js + RESTify将个人博客重构成了一个SPA,固然这个时候CMS还在运行着。出于SEO的缘由我并无在最后采用这个方案,由于我网站的主要流量来源是Google和是百度。可是我在另外的网站里混合了SPA与MPA,其中的性能与应用是至关的,除了第一次加载页面的时候会带来一些延时。

除了Node.js + RESTify,也试了试Python + Falcon(一个高性能的RESTful框架)。这个API理论上也应该能够给APP直接使用,而且能够直接拿来生成静态页面。

编辑-发布-开发分离:静态站点生成

如React同样解决DOM性能的问题就是跳过DOM这个坑,要跳过动态网站的性能问题就是让网站变成静态。

愈来愈多的开发人员开始在使用Github Pages做为他们的博客,这是一个颇有意思的转变。主要的缘由是这是免费的,而且基本上能够保证24x7小时是可用的——当且仅当Github发现故障的时候才会不可访问。

在这一类静态站点生成器(Github)里面,比较流行的有下面的内容(数据来源: http://segmentfault.com/a/1190000002476681):

  1. Jekyll / OctoPress。Jekyll和OctoPress是最流行的静态博客系统。

  2. Hexo。Hexo是NodeJS编写的静态博客系统,其生成速度快,主题数量相对也比较丰富。是OctoPress的优秀替代者。

  3. Sculpin。Sculpin是PHP的静态站点系统。Hexo和Octopress专一于博客,而有时候咱们的需求不只仅是博客,而是有相似CMS的页面生成需求。Sculpin是一个泛用途的静态站点生成系统,在支持博客常见的分页、分类tag等同时,也能较好地支持非博客的通常页面生成。

  4. Hugo。Hugo是GO语言编写的静态站点系统。其生成速度快,且在较好支持博客和非博客内容的同时提供了比较完备的主题系统。不管是本身写主题仍是套用别人的主题都比较顺手。

一般这一类的工具里会有下面的内容:

  1. 模板

  2. 支持Markdown

  3. 元数据

如Hexo这样的框架甚至提供了一键部署的功能。

在咱们写了相关的代码以后,随后要作的就是生成HTML。对于我的博客来讲,这是一个很是不错的系统,可是对于一些企业级的系统来讲,咱们的要求就更高了。以下图是Carrot采用的架构:

Editor Develoepr

这与咱们在项目上的系统架构目前类似。做为一个博主,一般来讲咱们修改博客的主题的频率会比较低, 多是半年一次。若是你常常修改博客的主题,你博客上的文章必定是至关的少。

上图中的编辑者经过一个名为Contentful CMS来建立他们的内容,接着生成RESTful API。而相似的事情,咱们也能够用Wordpress + RESTful 插件来完成。若是作得好,那么我想这个API也能够直接给APP使用。

上图中的开发者须要不断地将修改的主题或者相似的东西PUSH到版本管理系统上,接着会有webhook监测到他们的变化,而后编译出新的静态页面。

最后经过Netlify,他们编译到了一块儿,而后部署到生产环境。除了Netlify,你也能够编写生成脚本,而后用Bamboo、Go这类的CI工具进行编译。

一般来讲,生产环境可使用CDN,如CloudFront服务。与动态网站相比,静态网站很容易直接部署到CDN,并能够直接从离用户近的本地缓存提供服务。除此,直接使用AWS S3的静态网站托管也是一个很是不错的选择。

基于Github的编辑-发布-开发分离

尽管咱们已经在项目上实施了基于Github的部份内容管理已经有些日子里,可是因为找不到一些相关的资料,便很差透露相关的细节。直到我看到了《An Incremental Approach to Content Management Using Git 1》,我才意识到这彷佛已是一个成熟的技术了。看样子这项技术首先已经应用到了ThoughtWorks的官网上了。

文中提到了使用这种架构的几个点:

  1. 快速地开始项目,而不是学习或者配置框架。

  2. 须要使用咱们信奉的原则,如TDD。而这是大部分CMS所不支持的。

  3. 基于服务的架构。

  4. 灵活的语言和工具

  5. 咱们是开发人员。

So,so,这些开发人员作了些什么:

  1. 内容存储为静态文件

  2. 不是全部的内容都是平等的

  3. 引入内容服务

  4. 使用Github。全部的content会提交到一个repo里,同时在咱们push内容的时候,能够实时更新这些内容。

  5. 容许内容经过内容服务更新

  6. 使用Github API

因而,有了一个名为Hacienda的框架用于管理内容,并存储为JSON。这意味着什么?

基于Github的编辑-发布-开发分离

由于使用了Git,咱们能够了解到一个文件内容的历史版本,相比于WordPress来讲更直观,并且更容易 上手。

开发人员修改完他们的代码后,就能够直接提交,不会影响到Editor使用网站。Editor经过一个编辑器添加内容,在保存后,内容以JSON的形式出现直接提交代码到Github上相应的代码库中。CI或者Builder监测到他们的办法,就会生成新的静态页面。在这时候,咱们能够选择有一个预览的平台,而且能够一键部署。那么,事情彷佛就完成得差很少了。

若是咱们有APP,那么咱们就可使用Content Servies来作这些事情。甚至能够直接拿其搭建一个SPA。

若是咱们须要全文搜索功能,也变得很简单。咱们已经不须要直接和数据库交互,咱们能够直接读取JSON而且构建索引。这时候须要一个简单的Web服务,并且这个服务仍是只读的。

在须要的时候,如手机APP,咱们能够经过Content Servies来建立博客。

Repractise

思考完这些后,我想到了一个符合学习的场景。

基于Travis CI的编辑-发布-开发分离

咱们构建的核心均可以基于Travis CI来完成,惟一存在风险的环节是咱们彷佛须要暴露咱们的Key。

其余

原文: Repractise架构篇一: CMS的重构与演进

参考文章:

  1. 静态网站生成器将会成为下一个大热门

  2. EditingPublishingSeparation

  3. An Incremental Approach to Content Management Using Git 1

  4. Part 2: Implementing Content Management and Publication Using Git

相关文章
相关标签/搜索