張 浩
河南人民廣播電臺,河南鄭州 450003
內容發布系統是比較常見的網站管理類系統,具備一定規模的網站后臺都存在對應的內容發布系統,但有的內容發布系統管理的站點能支持每日百萬級別的訪問量,有的卻只能支持到幾萬用戶的訪問,如此懸殊的差別正是后臺發布系統不同的設計思路所造成的,本文討論的重點正是如何構建高性能高負載的后臺內容發布系統。高性能主要體現在響應時間較短、并發數較大、吞吐容量較大三個指標,為了說明如何接近指標,本文將從數據庫設計、應用內數據緩存、前端設計和模版、內容發布、內容分發網絡這五個層面逐一討論。
內容發布系統的功能大都具備人員權限管理、欄目管理、文檔管理、模版管理等功能,功能豐富的發布系統還包含用戶管理、留言評論管理、瀏覽量統計等功能。但能把每個功能都做的比較深入的系統卻屈指可數,本文主要圍繞欄目、文檔、模版這三個功能來著重說明如何做到高性能。
在技術選型上,考慮到編譯型JAVA語言具備天生的高性能和穩定性,本文采用JavaEE體系構建系統。系統以Mac OS系統作為開發平臺,用開源MySQL實現數據存儲,以Freemarker做為模版引擎。
此課題來源于某單位門戶網站,在發布系統的支撐下,網站頁面瀏覽量日均13萬至20萬之間,100多位新聞編輯人員同時操作,日均發稿量上千篇,能做到操作流暢,任務不排隊,響應迅速。
采用關系型數據庫MySQL作為后臺數據存儲,在設計數據實體表時,遵從數據庫設計范式的基礎上,功能上的滿足系統需求是第一要素,響應迅速便是第二要素,這在大型系統中非常重要,下面說明如何滿足第二要素。
部署主從數據庫的含義是至少采用兩臺數據庫(Master-Slave),分別負責寫和讀,主數據庫在內容變化后能同步到從數據庫上,且采用異步復制的方法,提升系統的吞吐量。
開啟并配置了查詢緩存后,數據庫執行SQL查詢會把SQL和對應的結果存在數據庫緩存里,如果數據不做改動,在下次執行查詢SQL時,會直接取出緩存里對應的數據,而跳過SQL解析和查詢階段。結合讀寫分離,在只負責讀的Slave端配置查詢緩存能提高數據響應時間。
以內容發布系統的文檔為例,文檔的標題內容等具有相對的穩定性,而文檔發布之后每一次用戶訪問其訪問量數字就要增加,所以訪問量這個數字相對變化,在設計時我們需把相對穩定的字段和相對變化的字段分別儲存到不同的表。
數據被寫進數據庫時,由于每一行記錄之間并沒有特定的排列順序,所以行與行的順序就是隨機無序的,在查詢沒有索引的數據表時,往往會對數據表做全掃描以篩選出目標數據。如果針對查詢字段做了索引,就類似對字典做了排序目錄,就能快速的定位到數據。在內容發布系統中,分析哪些字段經常被用作為查詢條件,有針對性的建立索引能提升查詢速度。
字段類型盡可能反映真實的數據含義,滿足功能外字段應該盡可能的短。比如能用int字段的就不要用bigint,比如發布系統中的文檔表,category代表文檔類型,可選的值有:0圖文、1圖集、2拼條、3引用、4URL、5投票、6調查、7單頁,他們的長度不超過兩位,在定義這個字段時就選取了TINYINT類型并設置其長度為1。
對于讀取頻繁和修改頻繁的數據,在應用程序內部為其建立緩存能有效緩解IO的開銷。
遵從不重復發明輪子的現代軟件開發哲學,應考量優秀的開源實現,從中選取適合項目的緩存框架。
發布系統的欄目數據、人員和權限數據是在每個功能模塊都會被頻繁用到的數據,所以我們在應用程序內部為其建立了緩存,甚至部分業務邏輯的計算結果也建立了緩存,本案例采用EHCache。
JAVA語言里,聲明對象會為其分配內存地址,會調用本身以及父類的構造函數,頻繁和數量巨大的創建對象會引發垃圾回收機制,對系統帶來性能問題。在開發設計中應考慮使用如下技術節省對象的開銷。
1)使用單例模式,使得整個系統中此對象只有一個。
2)合理聲明集合容量,在聲明List、Map等對象的時候,根據實際存放數據量對其集合容量作出限制,做到避免過度申請和頻繁擴容。
3)使用靜態類變量,保障數據全局唯一。
4)謹慎對待循環語句的內容,避免在循環語句里創建字符串、進行自動拆箱封箱等操作。
WEB前端的響應時間是影響用戶體驗非常重要的因素,即便后臺做的很棒,瀏覽器渲染內容即頁面加載時間過長也不能算上高性能。頁面加載整個過程經過DNS解析、TCP鏈接、HTTP重定向、HTML內容加載、瀏覽器渲染逐步完成,其中每個步驟都會拖慢整個頁面都響應時間。
在此只討論提高頁面渲染性能,包括以下方面。
在HTML頁面完成展現之后,動態改變頁面元素或調整CSS樣式都會引起瀏覽器重繪,盡量對小節點改動,對樣式有多重變動盡量合并到一起修改。
通常不設置緩存的情況下,每次刷新頁面都會重新讀取服務器的文件,而如果設置緩存之后,所有文件都可以從本地取得,就加速了訪問效率。
所有涉及到請求數據的文件盡量做壓縮,比如Javascript文件、css文件及圖片文件,特別是圖片文件,如果沒有高清晰要求,完全可以壓縮后再使用。數量少體積大的文件要比數量多體積小的文件加載速度快,所以有時候可以考慮將多個js文件、多個css文件合并在一起。
圖像合并其實就是把網頁中一些背景圖片整合到一張圖片文件中,再利用CSS的“backgroundimage”,“background- repeat”,“backgroundposition”的組合進行背景定位,backgroundposition可以用數字能精確的定位出背景圖片的位置。
一般來說,瀏覽器對于相同域名的圖片,最多用2-4個線程并行下載(不同瀏覽器的并發下載數是不同的)。而相同域名的其他圖片,則要等到其他圖片下載完后才會開始下載。
大多數內容發布系統都具備靜態頁面的生成能力,將內容生成為靜態頁面能有效緩解數據庫的壓力,一定程度上應對訪問量并發量只需要提高帶寬和提高磁盤的IO速度,是以內容為主導型的網站通用的做法。
靜態網頁化還可以提高網站穩定,從安全角度講,靜態網頁不宜遭到黑客攻擊,靜態頁面沒有攻入點,減少黑客進行攻擊的可能。從網站穩定性來講,如果程序、數據庫出了問題,會直接影響網站的訪問,而靜態網頁就避免了如此情況,不會因為程序等,而損失網站數據,影響正常打開,損失用戶體驗,影響網站信任度。
服務器檢索出數據,根據模版生成靜態頁面。模版的展示形式決定了靜態頁面的形式,同一個模版生成多個靜態頁面,頭部、底部、側邊欄等這些外觀都是一樣的,只是內容不同。服務器生成靜態頁面的速度必須要快,否則就會任務排隊,影響編輯人員的發稿,提高生成靜態頁面的性能和模版有巨大關系。
1)使用高性能模版引擎。推薦FreeMarker做為生成靜態頁面的工具,FreeMarker使用純Java編寫,被設計用來生成HTML Web頁面,簡單易用性能優異。
2)將通用部分的模版一次性生成。在批量生成頁面的時候,雖然模版不盡相同但總是能抽取出相同的部分,利用FreeMarker引入公共文件的功能把不同模版的公共部分引入,生成的時候只需要生成一次公共部分已達到快速生成的目的。
3)在需要分頁的列表頁減少生成靜態頁面的數量。對于內容為主導的網站分類列表是不可缺少的,如果文稿數量巨大,會超過上千頁,在有新文稿發布后,稿件的列表順序一定會發生改變,如果每次新增稿件把所有的分頁列表頁都生成一遍是相當耗時的。由于大量的點擊都集中在前幾頁,所以只把前幾頁生成為靜待頁面,把之后的分頁采用偽靜態讀取數據庫內容會比較提高效率。
內容分發網絡(CDN)是一種新型網絡構建方式,它是為能在傳統的IP網發布寬帶豐富媒體而特別優化的網絡覆蓋層;而從廣義的角度,CDN代表了一種基于質量與秩序的網絡服務模式。
簡單地說,內容分發網絡(CDN)通過用戶就近性和服務器負載的判斷,CDN確保內容以一種極為高效的方式為用戶的請求提供服務。
負載均衡的準確性和效率直接決定了整個CDN的效率和性能,和一般的鏡像有所區別,因為它比鏡像更智能,或者可以做這樣一個比喻:CDN=更智能的鏡像+緩存+流量導流。因而,CDN可以明顯提高Internet網絡中信息流動的效率。
提高性能,加快用戶操作的響應時間不僅是發布系統遇到的問題,也會是任何一個BS結構程序所面對的難題,影響系統性能的方面有很多,在系統長時間的運行中,一條低效的SQL語句或某行粗心大意的代碼都可能造成系統緩慢。本文只從設計方法宏觀上討論,沒有包含代碼質量,同時也沒有涉及硬件網絡等方面。
追求性能沒有極致,在實現需求等基礎上,能做到運行流暢已實屬不易。響應時間也并不是衡量系統好壞的唯一標準。開發設計之初若能根據需求特點合理規劃,有意識的避開嚴重影響性能的問題點,同時借鑒成熟的設計模式,促成一個性能優異的內容發布系統也不應是困難的工作。
[1]霍斯特曼,科內爾.Java核心技術[M].北京:機械工業出版社,2014.
[2]布洛克.Effective Java[M].北京:機械工業出版社,2009.
[3]施瓦茨(Schwartz,B.),扎伊采夫(Zaitsev,P.),特卡琴科(Tkachenko,V.).高性能MySQL[M].北京:電子工業出版社,2013.
[4]郭欣.構建高性能Web站點[M].北京:電子工業出版社,2012.
[5]雷葆華.CDN技術詳解[M].北京:電子工業出版社,2014.