性能
一開始的重點是提高服務(wù)的性能、反應(yīng)速度,并且盡可能的保證系統(tǒng)的安全。
第一階段

商城第一階段的框架采用的是傳統(tǒng)的動靜分離+負(fù)載均衡的配置。
- 最外層是采用
F5做的負(fù)載均衡和反向代理 - 兩臺
Ngnix服務(wù)器負(fù)責(zé)處理靜態(tài)資源的請求,并將動態(tài)請求分發(fā)給Tomcat服務(wù)器集群 - 商城的應(yīng)用(網(wǎng)站、觸屏版等)都建立在
Tomcat服務(wù)器上,主要采用SpringMVC+Freemarker - 應(yīng)用通過
API服務(wù)器暴露出的接口對數(shù)據(jù)庫進行增刪改查的操作
第二階段
第二階段框架的出現(xiàn)是為了解決第一階段暴露出的幾個問題:
-
Tomcat服務(wù)器過于忙碌:-
Tomcat服務(wù)器的一般工作流為:接收到Ngnix服務(wù)器轉(zhuǎn)發(fā)的動態(tài)請求 => 將動態(tài)請求按照業(yè)務(wù)邏輯調(diào)用API服務(wù)器的接口 => 將API服務(wù)器返回的數(shù)據(jù)和Freemarker結(jié)合,生成HTML文件 - 對于經(jīng)常被訪問到的頁面(首頁、商品詳情頁等),
Tomcat服務(wù)器需要不斷重復(fù)他的一般工作流,即使最后生成的HTML文件都是一模一樣的。
-
Tomcat服務(wù)器和API服務(wù)器交互過于頻繁:即使API服務(wù)器有如memcached類的緩存,依然會有很多不必要的網(wǎng)絡(luò)消耗
因此,我們覺得最好能將HTML文件緩存下來

我們在Tomcat服務(wù)器上加上了EhCache過濾器。一些經(jīng)常會被訪問到的頁面(譬如首頁、商品詳情頁等)在第一次被訪問過并成功生成HTML頁面后,會被記錄在內(nèi)存中,下一次訪問的時候就不會再向API服務(wù)器請求,也不會再解析Freemarker模板,內(nèi)存中的頁面會直接返回。
第三階段
第二階段的框架一上線就暴露出了問題:頁面不能及時更新,需要等EhCache自帶的緩存更新機制(通常是緩存池滿了)激活,緩存才會更新;而我們需要緩存更新是及時的、是可控的。
所以,我們自制了一個叫Backbone的微服務(wù)

其實Backbone目前就被當(dāng)成了一個定時任務(wù)系統(tǒng),只不過起名的時候,我們對這個系統(tǒng)寄以重托,所以給了一個很大的名號。
工作流是這樣的:
- 當(dāng)有緩存的內(nèi)容進入
EhCache的時候,Backbone會接收到請求的參數(shù) -
Backbone根據(jù)接收到的請求參數(shù),按照業(yè)務(wù)邏輯,請求API服務(wù)器;之后將API服務(wù)器返回的結(jié)果拼接,生成一個簽名,最后將<請求參數(shù),簽名>存入Redis中 -
Backbone定期從Redis中取出請求參數(shù),并按照頁面邏輯,請求API服務(wù)器,如果API服務(wù)器返回的結(jié)果拼接后的簽名和Redis中存的簽名一致,則無變化;如果不一致,Backbone會刪除Redis中的記錄,并調(diào)用Tomcat服務(wù)器暴露的接口刪除EhCache中該請求的緩存。
第四階段
第三階段的框架還是有瑕疵,有這么三個最為明顯:
- 既然第二次訪問同鏈接訪問的是緩存的內(nèi)容,為什么還要到
Tomcat服務(wù)器才處理 - 緩存的
HTML文件能不能看到 -
EhCache中存的很多數(shù)據(jù)都是冗余的
于是,我們采用了Ngnix+Lua的方式來解決上面三個問題。

Ngnix服務(wù)器將Tomcat服務(wù)器生成的HTML文件保存到Redis中,這樣Redis就被做成了Ngnix服務(wù)器集群統(tǒng)一存儲HTML文件的地方。
優(yōu)化
日志系統(tǒng)
經(jīng)過四個階段的性能優(yōu)化,整個商城的服務(wù)應(yīng)該算OK,接下來我們想讓開發(fā)調(diào)試更輕松一些。
我們覺得目前開發(fā)調(diào)試的瓶頸是日志:
- 一方面 因為正式環(huán)境需要堡壘機才能操作,如果需要通過看日志來解決問題,需要到堡壘機看日志或者讓運維拖日志下來,整個流程非常的難受。日志不是什么生死攸關(guān)的東西,我們想要看到線上實時的日志。
- 日志中打印了很多很多的內(nèi)容,使用
tail -f之類的命令,滾屏?xí)浅5目?,這樣看日志太傷神了。我們想要更優(yōu)雅、更簡單的查看日志的方法。
一種解決方法是將日志保存到專門的一臺服務(wù)器,然后通過tail -f XX | grep XXX之類的命令來看。這種方法是能基本解決以上兩個問題,但是不那么優(yōu)雅,不能算作一個系統(tǒng)的解決方案。
于是,我們采用了ElasticSearch + LogStash + Kinaba (ELK)。一開始我們想自己利用Bootstrap或者Framework7寫一套系統(tǒng),但是太懶,同時也發(fā)現(xiàn)ELK已經(jīng)把我們想做的都做了,有些小功能,我們改改Kinaba就能實現(xiàn),所以直接把ELK拿來用了。
首先我們自制了一個Admin微服務(wù)來監(jiān)聽處理Tomcat服務(wù)器通過MQ發(fā)送過來的日志

日志服務(wù)的工作流是這樣的:
-
Tomcat服務(wù)器的日志會被發(fā)送到MQ的Exchanger -
Admin系統(tǒng)會將監(jiān)聽到的日志進行處理(Tomcat服務(wù)器的日志利用拓展log4j.appender,封裝了一些附加信息),打印到admin-log.log文件中 -
LogStash會分析admin-log.log,并將分析的結(jié)果實時的放入ElasticSearch里 -
Kinaba為ElasticSearch提供了一個可視化的界面,在這個界面中,我們能篩選日志,能實時打印日志
小助手
最初的想法是利用Slack + Hubot,但是依然是因為懶,而轉(zhuǎn)用了微信。
微信小助手的主要用處就是檢查服務(wù)的上線狀態(tài),發(fā)送上線檢查之類的關(guān)鍵字,就會激活我們寫的檢查程序,主要涉及商城頁面能不能正常打開,有些流程能不能走通,如果走不通是因為跟API服務(wù)器的溝通斷了還是API服務(wù)器壞了還是什么。其次還加上了一些權(quán)限設(shè)置以及小助手注冊機制等等。
未完待續(xù)
之前堅持要自己做日志系統(tǒng),還有部分原因是會根據(jù)分析日志得到的結(jié)果加上推薦系統(tǒng)和優(yōu)化搜索。
