企業QQ SaaS團隊,談企業級LNMP架構設計
來自: http://blog.csdn.net//jiao_fuyou/article/details/38755215
對比IaaS和PaaS,SaaS得到的關注顯然要少一些。究其根本,不僅因為SaaS關注的是功能方面的探索,更偏向于某個領域或層面的實際應用,還歸結于相較前兩者,軟件的云化已基本趨于成熟,些許突破并不能帶來產業上的變革。然而,較少的關注并不意味著缺乏明星產品:放眼國外,企業級SaaS服務已成為許多公司的一項重要收益來源,比如Salesforce、Oracle;而聚焦國內,同樣有很多值得我們關注的產品,就比如本次我們關注的焦點——騰訊企業QQ。這里,我們接觸到了企業QQ的Web技術團隊,與他們團隊的王帥、甘德建、趙凱、陳勝強、唐朝等幾位核心人員進行了深入溝通,了解了基于LNMP,超過4萬付費企業辦公平臺的架構及優化經驗。由王帥代表團隊回答。
企業QQ平臺狀況
騰訊企業QQ SaaS團隊
CSDN:請首先介紹一下你個人、團隊,及貴團隊從事的工作和關注的重點。
王帥:在騰訊工作近5年,一直負責企業產品的Web架構。作為SNG乃至整個騰訊使用PHP最廣泛的團隊之一,我們為企業內部、企業之間提供了高效的通信。企業QQ依托QQ的賬號、通信體系,具備內部組織架構管理、對內溝通、無縫與8.6億活躍QQ用戶溝通(文字/表情/音視頻/遠程協助等)、對外形象統一、開放API等能力。在平時辦公中,企業QQ的Rich溝通形式更是座機電話、手機的很好補充。試想在電話中解釋很久的問題,可能在企業QQ上一個截屏就可以解決。我們關注企業的信息溝通及管理,幫助企業掌握運營情況,我們堅信能幫助企業實現其目標與價值。我們的口號是隨時隨地,隨心辦公。
CSDN:能否談一下騰訊企業QQ當下的用戶規模?都包括了哪些重量級客戶?以及這套平臺在騰訊內部的使用情況?
王帥:經過幾年的積累,企業QQ擁有4W家的付費企業,超過100W的用戶數,在整個企業級SaaS市場屬于領先的地位。我們設計定位是對座機電話、手機的補充,企業QQ提供的SaaS通信服務,適合所有開通寬帶的企業和幾乎所有行業。我們的客戶行業分布十分廣泛,除了快遞物流領域的天天快遞、圓通,餐飲領域的西貝,同時還包括政府機關、教育單位(比如,上海交通大學)、跨國企業(比如,IT巨頭Intel)等。
騰訊SNG的即通綜合部平時用企業QQ進行溝通辦公,但是由于全公司范圍代替RTX的實施成本比較高,所以在騰訊內部只推廣到了企業產品部門,不過隨著產品影響力的日益增強,我們相信企業QQ必然有機會在全公司范圍推廣。
CSDN:就騰訊企業QQ這個SaaS來說,客戶的擔心都在什么地方?有什么問題是大家共同關注的?貴團隊使用什么方法攻克了這些難關?
王帥:在使用任何一家的SaaS時,企業CIO/IT經理最擔心的就是這套系統的穩定性和安全性。我們從多個維度,保證系統穩定性:
- 服務器方面,我們采用騰訊自建機房,在保證不間斷供電的同時,還具備火災/洪水預警、硬件/軟件雙重防火墻防護、百G級DDoS攻擊防護等能力;除此之外,我們還配備了7*24小時響應的安全管理團隊。系統安全方面,采取了分布式數據采樣與集中告警機制,不間斷的滲透性測試,提前發現系統潛在問題。
- 數據安全方面,我們使用了異地備份機制以保證數據的完整。
- 服務穩定方面,除了優秀的負載均衡技術,我們還使用了N+1的冗余機制以保證系統的平穩運行。
- 軟件安全方面,我們更采取了多個措施:客戶端防注入、登錄加密等方式自保護,消息傳輸過程采用私有加密協議,客戶端與服務端相互不信任的通信設計保證傳輸安全,即使在網關上監聽也無法破解。良好的代碼review機制保證核心代碼的穩定性,快速下發patch能力保證一旦問題發生能快速修復。
在SaaS的安全方面,我們與Intel共同打造了一套基于SaaS服務,由廠商自己或第三方提供加密方式的解決方案,并已為之申請專利。保證了客戶采用自己希望的加密方式,在企業QQ的安全通道中傳輸。
CSDN:可否談下QQ企業平臺系統的規模/狀態,比如RPS,QPS,TPS等?峰值又會有多少?使用什么樣的硬件資源支撐了這個平臺?
王帥:作為一款企業級產品,用戶量不能和個人產品相比,比如QQ空間。騰訊大部分業務是免費+增值方式,大部分服務器只有不到10%承載的是付費用戶。企業QQ的服務器規模較小,但幾乎100%承載的都是付費用戶。目前的RPS在3000左右,峰值可以達到4000至5000,整個團隊所維護的服務器大概是幾十臺。
幾十臺已經是算了全部支持系統,主邏輯服務器較少。我們會不斷壓榨現有服務器性能,從最開始開發企業QQ到現在,基本沒有新增過服務器。我們會有階段性的做架構優化,服務器負載一直保持較低水平。后面會介紹一些優化的方法。
走進騰訊企業QQ
CSDN:能不能詳細介紹一下這個平臺架構的構建過程?都使用了一些什么技術,分別做了什么?
王帥:目前的SaaS平臺架構根據產品和量級的需求經歷過多次演變,最終演化成了現在的結構。
由最初的快慢分離和簡單容災,增強容災和提供灰度發布能力,逐漸抽取統一數據層/減少無用請求,強化多set模型和立體監控,到最后統一數據存儲。最終演變為:DNS+GSLB+LVS/TGW+業務邏輯機(Nginx+php-fpm+APC)+中間層和異步系統(PHPServer)+cache層+UDS、Redis、CKV等存儲層。
LNMP經驗分享
1. 基于PHPServer的中間層:采用PHP作為UDP/TCP Server提供中間層數據服務,每秒可以處理請求2萬次以上。中間層封裝大部分緩存和數據邏輯,因為由PHP擴展和純PHP開發,開發人員無需關心內存泄露和core的問題,極大的提高了開發效率。同時我們實現了CPU親和性綁定,PHP的Epoll支持,消息隊列,Unix Socket等Linux底層特性提高Server的吞吐能力。
2. 基于C++的PHP擴展:部分邏輯用C++封裝成擴展,提高運行效率。公司級業務對接大部分使用C++為PHP編寫擴展,是PHP與公司級C/C++ API的產品無縫對接。
3. PHPServer旁路系統:使PHP的pctnl,主進程管理和監控所有的業務進程,所有后臺服務器天然支持自動拉起,接入便利,極大提高了后臺服務器的可服務范圍。
4. Xhprof:可以在運營環境部署的性能調優插件。為提高QPS,降低服務器CPU,提高機器利用率在業務層級提供了可靠的仰仗。
5. 數據上報和監控:基于PHPServer及公司成熟組件的UDP上報和展示以及RTX、微信通知機制進行全面系統的監控,及時發現服務器異常
6. Cache技術:采用APC進行PHP的OPCode緩存。利用共享內存進行第一層cache,緩存高頻數據,采用業界常見的memcache、redis進行分布式cache,按照數據單元組合分為多級cache。采用公司級別的CKV作為落地Cache方案。
7. 數據庫技術:采用基于MySQL的數據庫UDS系統托管。部分數據使用騰訊提供的CDB托管,保證寫熱備。
8. Yii框架:利用Yii框架的WebApp和ConsoleApp構建所有的PHP工程。
9. 前端技術:我們產品非常重視前端體驗。隨著RIA富因特網應用程序類型產品的盛行,我們在前端技術方面采用了分模塊按需加載(自研的LBF框架)、前端MVC模式的使用(BackBone)、Single Page Application單頁開發模式(SPA)等等。同時在移動端頁面的開發上,借助html5的各種便利新特性,大大提高了用戶體驗(LBF Mobile)。未來,隨著在多平臺多終端上的發展,在前端方面我們也會采用響應式布局等的新理念,來優化多終端之間的智能適配。
10. 前端系統:自建NodeJS+ULS(海量log系統)上報JS的錯誤,使我們對用戶瀏覽器可能出現錯誤了如指掌。前端代碼發布前對模板文件預編譯(ArtTemplate),同時多個靜態資源文件合并和壓縮(Combo機制),推送到CDN,加速用戶側的加載。使用公司級OZ測速系統,能夠了解全國的接入速度,針對性的優化服務器拓撲。
CSDN:如此規模下,平臺打造的主要挑戰在什么地方?貴團隊在這些技術上都做了哪些方面的調優?能達到一個什么樣的級別?
王帥:作為一款企業級服務,穩定、安全性是我們最重要的挑戰。在穩定性方面,我們堅持進行灰度發布,在正式發布前已經經過多輪灰度用戶驗證。服務的多Set隔離,在極端情況下一個set出問題,其他set依然能夠提供服務。服務器提供各個維度的監控(CPU、內存、流量、磁盤、程序錯誤等等),同時也有各種觸達運維人員的告警(手機、短信、微信、RTX等等),此外,在平行擴展方面也下了很多功夫,服務器負載過大的時候可以通過增加機器輕松擴展。安全性方面,我們的功能在上線前均接受公司的XSS、CSRF等各種漏洞掃描,并且時刻關注所使用的開源軟件的漏洞發布情況,及時防堵。
另外,很多查詢和操作需要以企業為單位進行操作,在Cache設計上我們支持了多級的Cache模型。
大部分公司的上班時間是一致的,因此很多請求會在早高峰上班時撞車,我們也一直致力與削峰和減少高峰期CPU占用率。
性能調優經驗分享
- 所有數據Cache化,多級Cache
- 使用Linux的運維命令查找高峰期耗時較高的CGI和進程,運用Xhprof定位業務性能問題
- 同步網絡請求異步化
- 使用Epoll提到Select提高網絡IO效率,為使用PHP做后臺server提供基礎架構能力
- 快慢請求業務分離,互不影響。
- 有效的利用Nginx反向代理能力,將部分(如灰度邏輯)做在nginx層以提高處理性能。
采用上述調優后,我們團隊在流量增大2倍的前提下未加一臺機器,CPU保持不變。
前端方面,在大型企業人員規模巨大,依然要展現整個公司組織的情況下,我們進行前端json文件本地緩存,對部門和成員數據查找檢索算法方面做了算法優化,能夠基于拼音首字母、多音字、ID、中文等進行檢索,該檢索算法已經申請專利。在CGI方面也做了按場景和權限分離,分批拉取,在一個頁面上用戶量達到3萬級別,也能保證用戶體驗和加載速度。
CSDN:作為web的分布式架構大師,你認為重點在什么地方?架構時應該使用一個什么樣的理念?架構師應該具備哪些知識?需要避免哪些坑?
王帥:Web架構選型,最重要的一點是選擇最合適的架構,而不是最好的。我們設計架構最根本的理念是:任何時候架構都是為業務服務的,在選型階段要避免過度設計。任何時候都要符合敏捷迭代的思想,最快速的支持業務開發。在規劃一個分布式架構系統的時候,可以從架構的可用性、可靠性、高性能、可管理性、可伸縮性、成本等方面重點關注,這幾個方面環環相扣缺一不可,一個成熟架構師會靈活運用各種計算機基礎知識,在上述幾個方面進行妥協。
架構盡量不要設計得過于復雜化,越簡單的模型對于今后的維護成本越有利;同時也不必過度設計,滿足現有需求同時為將來擴展預留適當的空間即可,因為產品方向、業務需求的變化可能改變甚至推翻現有的架構,過度設計將造成資源的不必要浪費。在設計一個分布式架構的時候,要對網絡、服務器、IDC、帶寬、均衡設施、系統容量等等方面都要有較為深入的認識,這些都是較為基礎的準備,同時,也要對公司內、外相關的成熟組件有所了解,比如外界開源LVS可以很好的實現負載均衡,自研的TGW/L5/CMLB等系統也可以實現類似需求,可以避免重復造輪子,享受開源技術紅利,集中資源去快速滿足業務需求。至于如何避免哪些坑,這個就多到無法窮舉了。服務壓力上漲屬于幸福的煩惱,服務器沒故障過幾次,很多經驗也積累不起來。。
除了自身要具備上述提到的各種前提下,還要多多關注業界主流設計方案,同時將方案請同行指點指點不失為一個很好的方法。推薦一本書《軟件架構師應該知道的97件事》,每隔一段時間的重新閱讀都會有新的收獲。
CSDN:LNMP是個非常普及的web架構,但是很少能將他們用到你們的規模,是否可以給大家分享一些大流量開發過程中總結的一些秘訣,以及一些需要特殊注意的地方。
王帥:LNMP作為最為普及的web架構之一,在當今互聯網架構方案中起舉足輕重作用。在上述所提到做好架構設計的前提下,在應對大流量時,數據緩存機制重要性顯得尤為重要,舉例子來說,業務代碼中獲取數據源的時候,要充分考慮對數據源的訪問保護,同時也要防止因緩存失效或者預熱過程中大流量直接穿透導致數據源被壓垮,尤其是數據庫;代碼層面上,抽象出一些公共類庫,為前端業務、中間層等系統服務。
另外Nginx可以做很多事情,包括但不限于染色、錯誤處理、反向代理、容災等。
而PHP本身作為使用C語言開發的腳本語言,在純后臺Server(WebServer)的實現上有極高的開發效率,且效率不會比純C的Server低太多,在互聯網快速變化中,能夠快速的幫助產品進行試錯。
CSDN:在容災和資源調度上,這個平臺能達到什么樣的水準?可否詳細談談,比如各個層面的副本數量,可用性可以達到幾個9?
王帥:我們在容災和負載均衡上都做了較大努力,從最靠近用戶的LVS/TGW接入層開始,到Nginx反向代理層,再到業務邏輯層,最后到中間層、Cache層、數據源等各層系統,每層都可以自容災,同時向下負載均衡,服務器是跨機房熱備,即使一個機房故障,也可以給用戶提供穩定服務。同時,任何一臺機器主要性能指標達到波動閾值,我們的全體開發成員均會及時收到微信、短信、RTX等全方位的告警,及時采取應對措施,可以保守的說,我們的總體系統可用性達到5個9以上。
CSDN:在企業級產品SaaS的打造上,你有什么可以補充給大家的?比如說如何才能獲得一個更好的用戶體驗?
王帥:在企業產品SaaS的打造上,我們團隊多年來在產品體驗上積累了相當豐富的經驗。首先,我們的部分產品需求基本都來自用戶真實的訴求,也就是我們產品始終秉持著為企業用戶解決企業痛點而觸發的。其次,一個產品需求被認可需要開發前,首先產品方案會經過產品同學內部的溝通,然后會拿到整個項目組一起討論需求的可行性、合理性等,這樣在開發之出就可以暴露出產品設計的種種缺陷,減少后期產品方案反復變更帶來的資源浪費。再后來,產品開發、測試完畢后,我們會先根據調查給希望嘗鮮的用戶灰度試用,在灰度的這段時間內(一般為1~2周),積極收集用戶的反饋意見、建議,產品組同學、項目經理全程參與其中,決策是否要調整產品。當然灰度期間,我們整個產品中心也是灰度用戶,大家可以就新產品暢所欲言自己的觀點。最終,產品經過道道工序后終于推向全體企業,這個時候推出的版本由于已經經過部分用戶持續試用、反饋、修正,無論從穩定性還是交互體驗上都經過真實用戶的驗證,更加容易得到廣大用戶的認可。
</div>