重構系統是一項很是具備挑戰性的事情。一般來講,在咱們的系統是第二個系統的時候才須要重構,即這個系統自己已經很臃腫。咱們花費了太量的時間在代碼間的邏輯,開發新的功能變得愈來愈慢。這不只僅可能只是由於咱們以前的架構沒有設計好,並且在咱們開發的過程當中沒有保持着原先設計時的一些原則。若是是這樣的狀況,那麼這就是一個複雜的過程。html
還有一種狀況是咱們發現了一種更符合咱們當前業務的框架。git
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黨。主要緣由還在於我能夠爲所欲爲地去修改網站的內容,修改網站的架構。好的CMS總的來講都有其架構圖,下圖彷佛是Drupal的模塊圖
通常來講,其底層都會有:
ORM
User Management
I18n / L10n
Templates
我一直在使用一個名爲Django的Python Web框架,它最初是被開發來用於管理勞倫斯出版集團旗下的一些以新聞內容爲主的網站的,便是CMS(內容管理系統)軟件。它是一個MTV框架——與多數的框架並無太大的區別。
層次 | 職責 |
---|---|
模型(Model),即數據存取層 | 處理與數據相關的全部事務:如何存取、如何驗證有效性、包含哪些行爲以及數據之間的關係等。 |
模板(Template),即表現層 | 處理與表現相關的決定: 如何在頁面或其餘類型文檔中進行顯示。 |
視圖(View),即業務邏輯層 | 存取模型及調取恰當模板的相關邏輯。模型與模板之間的橋樑。 |
從框架自己來上看它和別的系統沒有太大的區別。
可是若是咱們已經有多外模塊(即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):
Jekyll / OctoPress。Jekyll和OctoPress是最流行的靜態博客系統。
Hexo。Hexo是NodeJS編寫的靜態博客系統,其生成速度快,主題數量相對也比較豐富。是OctoPress的優秀替代者。
Sculpin。Sculpin是PHP的靜態站點系統。Hexo和Octopress專一於博客,而有時候咱們的需求不只僅是博客,而是有相似CMS的頁面生成需求。Sculpin是一個泛用途的靜態站點生成系統,在支持博客常見的分頁、分類tag等同時,也能較好地支持非博客的通常頁面生成。
Hugo。Hugo是GO語言編寫的靜態站點系統。其生成速度快,且在較好支持博客和非博客內容的同時提供了比較完備的主題系統。不管是本身寫主題仍是套用別人的主題都比較順手。
一般這一類的工具裏會有下面的內容:
模板
支持Markdown
元數據
如Hexo這樣的框架甚至提供了一鍵部署
的功能。
在咱們寫了相關的代碼以後,隨後要作的就是生成HTML。對於我的博客來講,這是一個很是不錯的系統,可是對於一些企業級的系統來講,咱們的要求就更高了。以下圖是Carrot採用的架構:
這與咱們在項目上的系統架構目前類似。做爲一個博主,一般來講咱們修改博客的主題的頻率會比較低, 多是半年一次。若是你常常修改博客的主題,你博客上的文章必定是至關的少。
上圖中的編輯者經過一個名爲Contentful CMS來建立他們的內容,接着生成RESTful API。而相似的事情,咱們也能夠用Wordpress + RESTful 插件來完成。若是作得好,那麼我想這個API也能夠直接給APP使用。
上圖中的開發者須要不斷地將修改的主題或者相似的東西PUSH到版本管理系統上,接着會有webhook監測到他們的變化,而後編譯出新的靜態頁面。
最後經過Netlify,他們編譯到了一塊兒,而後部署到生產環境。除了Netlify,你也能夠編寫生成腳本,而後用Bamboo、Go這類的CI工具進行編譯。
一般來講,生產環境可使用CDN,如CloudFront服務。與動態網站相比,靜態網站很容易直接部署到CDN,並能夠直接從離用戶近的本地緩存提供服務。除此,直接使用AWS S3的靜態網站託管也是一個很是不錯的選擇。
儘管咱們已經在項目上實施了基於Github的部份內容管理已經有些日子裏,可是因爲找不到一些相關的資料,便很差透露相關的細節。直到我看到了《An Incremental Approach to Content Management Using Git 1》,我才意識到這彷佛已是一個成熟的技術了。看樣子這項技術首先已經應用到了ThoughtWorks的官網上了。
文中提到了使用這種架構的幾個點:
快速地開始項目,而不是學習或者配置框架。
須要使用咱們信奉的原則,如TDD。而這是大部分CMS所不支持的。
基於服務的架構。
靈活的語言和工具
咱們是開發人員。
So,so,這些開發人員作了些什麼:
內容存儲爲靜態文件
不是全部的內容都是平等的
引入內容服務
使用Github。全部的content會提交到一個repo裏,同時在咱們push內容的時候,能夠實時更新這些內容。
容許內容經過內容服務更新
使用Github API
因而,有了一個名爲Hacienda的框架用於管理內容,並存儲爲JSON。這意味着什麼?
由於使用了Git,咱們能夠了解到一個文件內容的歷史版本,相比於WordPress來講更直觀,並且更容易 上手。
開發人員修改完他們的代碼後,就能夠直接提交,不會影響到Editor使用網站。Editor經過一個編輯器添加內容,在保存後,內容以JSON的形式出現直接提交代碼到Github上相應的代碼庫中。CI或者Builder監測到他們的辦法,就會生成新的靜態頁面。在這時候,咱們能夠選擇有一個預覽的平臺,而且能夠一鍵部署。那麼,事情彷佛就完成得差很少了。
若是咱們有APP,那麼咱們就可使用Content Servies來作這些事情。甚至能夠直接拿其搭建一個SPA。
若是咱們須要全文搜索功能,也變得很簡單。咱們已經不須要直接和數據庫交互,咱們能夠直接讀取JSON而且構建索引。這時候須要一個簡單的Web服務,並且這個服務仍是隻讀的。
在須要的時候,如手機APP,咱們能夠經過Content Servies來建立博客。
思考完這些後,我想到了一個符合學習的場景。
咱們構建的核心均可以基於Travis CI來完成,惟一存在風險的環節是咱們彷佛須要暴露咱們的Key。
參考文章: