新5 年时间服务器从 0 到 200,一个创业公司的架构野蛮生长史头疼哈
貝聊成立于2013年,是中國幼兒園家長工作平臺,致力于通過互聯網產品及定制化解決方案,幫助幼兒園解決展示、通知、溝通等家長工作中的痛點,促進家園關系和諧。貝聊是威創股份(A股幼教第一股)、清華啟迪、網易聯手投資的唯一品牌。在短短幾年內,用戶規模迅速達到千萬級別,每年DAU均呈倍數級增長。
面對如此快速的發展,原有的技術架構很難支撐越來越復雜的業務場景,在系統可用性以及穩定性方面,都給貝聊技術團隊帶來了很大的壓力。因此,如何針對當前需求,選擇合適的技術架構,保證架構平滑演進,值得我們深入思考。
貝聊架構總體經歷了三次重大歷程,由幾臺服務器搭建的單體架構到目前的幾百臺分布式部署架構,在整個變化過程中,我們踩過了很多坑,遇到過很多重大技術挑戰。
誕生期—技術架構選型V1.0
創業初期,我們的初始創業團隊在進行架構選型時,主要基于以下幾點進行考慮:
在創業初期,研發資源有限,研發人力有限,技術儲備有限,需要選擇一個易維護、簡單的技術架構;
產品需要快速研發上線,并能夠滿足快速迭代要求,現實情況決定了一開始沒有時間和精力來選擇一個過于復雜的分布式架構系統,研發速度必須要快;
創業初期,業務復雜度比較低,業務量也比較小,如果選擇過于復雜的架構,反而會增加研發難度以及運維難度;
遵從選擇合適的技術而不是最好的技術原則,并權衡研發效率和產品目標,同時創業初期貝聊只有一個PHP研發人員,過于復雜的技術架構必然會帶來比較高昂的學習成本。
正是基于以上幾點考慮,最終選擇了經典的LNMP技術架構,貝聊V1.0架構就這樣誕生了,為了加快產品研發速度,盡快上線產品,首期通過外包公司實現了研發以及部署,后續由我們的PHP研發人員接手,并進行后續的迭代開發。
?
初期部署時,部署了三臺ECS服務器,其中接入層nginx與系統部署在同一臺機器,RDS數據庫一臺機器,Memcached緩存一臺機器,V1.0架構具有以下特點:
?
-
單體架構,架構簡單,清晰的分層結構;
-
可以快速研發,滿足產品快速迭代要求;
-
沒有復雜的技術,技術學習成本低,同時運維成本低,無需專業的運維,節省開支。
LNMP架構支撐貝聊業務發展了將近一年半左右的時間,簡單、易維護的架構為貝聊的快速發展做出了很大的貢獻,期間業務發展迅速,用戶體量也越來越大,原有架構逐漸暴露出越來越多的問題。
成長期—技術架構重構V2.0
我是在2015年初加入了貝聊,初始研發團隊只有三人,有幸在這一時期
主導了貝聊技術架構重構,并經歷了貝聊后續的幾次架構演進路程,將原有PHP單體架構重構為JAVA分布式架構。
首先談一談我們做技術架構重構的契機,重構并非難在怎么做,而是難在何時開始做,所以我們做架構重構的契機主要基于以下幾點:
原有LNMP架構經歷了兩個團隊研發和維護,外包團隊和公司PHP研發人員,由于業務變化比較快,原有的數據庫設計逐漸暴露出來很多問題,很多表設計不合理, 很多字段定義不清,比較混亂;
2015年,由于業務發展,貝聊app需要拆分為兩個客戶端:貝聊家長端和貝聊老師端,通過不同的客戶端來服務不同的用戶群體,達到精準運營的目的,如果在原有架構上繼續進行開發,則會導致新舊接口邏輯混在一起,并且早期的很多接口定義不是很規范,維護起來越來越麻煩、越來越吃力;
原有API接口系統是單體架構,里面包含了各種接口,混合了各組業務邏輯處理,所有功能都集中在API接口系統中,代碼非常臃腫,業務非常繁雜,迭代開發的速度也逐漸減慢,各種性能問題經常爆出,BUG也比較多,并且部署困難,任何修改每次都需整體部署。由于業務邏輯混雜在一起,新入職研發人員需要很長時間才能夠完全熟悉系統,很難快速通過以點及面的方式切入系統;
所有數據存儲在一個RDS數據庫中,只使用了一個主庫,沒有從庫,同時很多系統共用一個數據庫,一方面數據庫沒有做到物理上的隔離,另一方面很多表都放在了同一個數據庫中,經常會碰到一個慢查詢或者其他性能問題,導致整個RDS各項指標飆升,造成雪崩效應,所有系統連鎖出現故障,最終都不能訪問;
公共服務耦合比較嚴重,很多第三方服務都散落在各個系統里面,不便于統一維護,當需要修改公共服務參數或者做其他調整時,需要深入到每個系統里進行修改或者排查,非常麻煩,還非常容易出現遺漏,最終產生BUG,急需獨立拆分出公共服務,將公共服務從業務系統中解耦出來,由專人進行獨立維護、獨立部署;
我們新的研發團隊都擁有豐富的JAVA分布式架構設計經驗,擁有高并發、高可用經驗,因此將原有的單體架構重構為JAVA分布式架構也是順勢而為。
由于公司業務高速發展,如果停下來專門做技術架構重構是不可能的,我們選擇了在維護現有系統的基礎上,同時進行新的技術架構重構工作。重構期間,在原有PHP研發團隊的大力支援下,我們的重構工作還算非常順利,既保障了業務的快速迭代需求,又成功完成了新的技術架構重構,新的V2.0架構如下:
?
在V2.0架構時期,初步實現了分布式部署架構,根據不同的功能以及業務邏輯,完成系統級別的拆分,同時對第三方服務進行解耦,拆分出了獨立的服務模塊,針對DB,我們實現了系統級拆分以及物理獨立部署,并實現了數據庫主從分離,同時引入了MQ消息隊列,并使用SLB實現了負載均衡和帶寬流量入口統一。
V2.0時期的架構具有以下特點:
?
-
分布式部署架構,系統易擴展;
-
系統級拆分,拆分出業務功能邏輯獨立的子系統,并獨立拆分出DB;
-
初步實現了服務化,系統間調用使用Hessian實現RPC;
-
DB實現了物理隔離,避免以前單DB出故障,引發業務連鎖故障,同時實現了數據庫主從分離;
-
引入MQ消息隊列實現消息和任務異步化,加快接口響應速度,提升用戶體驗,同時針對一些消息推送任務也實現異步化,避免早期的輪詢MySQL機制,減少消息推送延時,提升消息推送速度;
-
使用SLB實現了Nginx負載均衡,在V1.0架構時期,我們的Nginx是單點部署,若一臺Nginx服務器掛掉,則會影響很多業務系統,有單點故障風險,通過SLB實現多臺Nginx負載均衡,達到高可用的目的,避免單點故障。
系統拆分和DB拆分
針對系統拆分以及DB拆分,我們通過兩個階段來完成該項工作。
第一階段
首先在系統層面進行拆分,將原有的大系統拆分出多個業務邏輯獨立的子系統,而DB暫時不進行拆分,多套系統還繼續共用一個DB,只是根據業務邏輯劃分各個系統所依賴的表,不同業務邏輯系統之間不能互相訪問表,這樣新系統只訪問自己所歸屬的表,通過此種方案,可以保證原有系統業務不受影響,同時新拆分的業務系統研發工作也可以順利進行,此階段大概花費了我們幾個月的時間,最終順利完成系統層面的拆分。
第二階段
在完成系統層面拆分之后,我們緊接著實施DB層面的拆分,將各個子系統所依賴的表獨立拆分出來,分別放置到不同的RDS數據庫,實現物理的隔離,同時實現了數據庫主從分離。最終實現效果如下圖:
?
初步服務化
本階段,我們采用了比較簡單易用的Hessian實現初期的RPC服務化。針對第三方公共服務,從原有系統中解耦出來,獨立拆分出服務化組件,并做獨立部署,供其余業務系統統一調用。而系統間調用也通過Hessian來實現RPC遠程調用。
SLB負載均衡
在V1.0架構期間,我們的Nginx都是單點部署,一旦一臺Nginx服務器出現故障,則會波及到大量業務系統,風險非常大,如下圖:
在V2.0架構期間,我們引入了SLB實現負載均衡,SLB配置了多臺Nginx,同時在業務系統層面也實現了負載均衡,避免了單點故障,達到高可用的目的。
爆發期—微服務架構V3.0
進入2016年以來,貝聊業務高速發展,用戶規模在短時間內增長數百萬,同時各個業務線逐漸鋪開,業務場景更加復雜,代碼規模膨脹得也非常快,研發團隊迅速達到了幾十人規模,一個系統多人開發,研發人員層次不一,規范難以統一,同時業務邏輯耦合嚴重,每次上線都需要將整個大系統整體打包上線,風險非常大,并且新人入職之后學習成本非常高。因此我們引入了微服務架構,將業務邏輯拆分為獨立的微服務組件,每個微服務都圍繞著具體業務進行構建,由專人研發和維護,并由專人做性能優化和架構優化,各個微服務組件的研發與上線互不影響。
結合V2.0架構,在實施微服務架構時,基于多方面考慮,我們選擇了Dubbo作為分布式微服務框架。
?
-
成熟的高性能分布式框架,目前很多公司都在使用,已經經受住各方面性能考驗,比較穩定;
-
可以和Spring框架無縫集成,我們的架構正是基于Spring搭建,并且接入Dubbo時可以做到代碼無侵入,接入也非常方便;
-
具備服務注冊、發現、路由、負載均衡、服務降級、權重調節等能力;
-
代碼開源,可以根據需求進行個性化定制,擴展功能,進行自研發;
在做微服務時,我們考慮了以下幾個關鍵點:
-
以服務為中心,一切都是服務,每個服務都針對單一業務進行封裝,保證功能完整性和職責單一性;
-
松耦合性,服務之間功能獨立,能夠獨立部署,服務之間相互依賴;
-
高擴展性,分散資源,團隊協同工作,可無限擴展,更高的代碼重用率。
在實施微服務架構時,主要考慮從以下幾個方面進行實施:
?
-
獨立功能邏輯拆分為微服務,獨立部署,獨立維護;
-
系統功能全部通過調用微服務實現,系統不能直接訪問DB;
-
小數據量高并發調用使用Dubbo長連接協議進行通訊,大數據量服務比如文件、圖片、視頻等使用Hessian協議進行通訊;
-
每個微服務都維護獨立的DB。
微服務拆分案例
\1. 班級動態微服務
貝聊的班級動態是一個高頻率使用功能,園長、老師、家長都可以在班級進行發布動態,通過點贊、回復進行互動。隨著貝聊業務飛速發展,用戶規模爆發,每天都產生數十萬的班級動態量,同時日回復量和點贊量均達到了數百萬級別。面對如此大規模的數據量,我們一方面要應對高并發的性能壓力,另一方面又要應對數據壓力,原有的班級動態功能散落在API接口系統以及后臺管理系統中,相關的表也與原有系統共享一個DB,迫切需要我們拆分出獨立的班級動態微服務組件,同時還需要做分庫分表減少單數據庫壓力。因此我們專門抽調精干研發人力,拆分出了班級動態微服務組件。
舊班級動態調用方式如下
?
班級動態微服務組件調用方式如下:
?
拆分出班級動態微服務之后,我們解決了以下問題:
-
班級動態微服務對業務調用方透明,業務調用方只需調用接口即可,無需關注技術實現細節;
-
代碼復用性,班級動態業務邏輯單獨抽出來做成獨立微服務組件,業務系統不再散落班級動態業務邏輯代碼、無需再進行代碼拷貝;
-
采用DRDS實施了分庫分表,解決了單數據庫數據量大、數據處理能力有限的瓶頸問題,在單數據庫情況下,由于數據量比較大,高并發時期,經常遇到性能問題,接口響應速度非常慢,在實施分庫分表之后,班級動態接口的整體性能提升了幾倍,用戶體驗非常好,高并發時期也沒有了性能問題。
\2. 用戶通行證微服務
很多創業公司,在一開始發展時,為了追求速度,同時由于人力不足,都是將用戶數據表與業務數據表暫時放在了一個DB里面,貝聊早期也是這樣,這就造成了各個業務系統都是自己分別寫DAO來獲取用戶數據,產生了大量重復的用戶邏輯拷貝代碼。隨著業務發展的越來越快,越來越多的業務系統都需要訪問用戶數據,用戶邏輯代碼散落在各個業務系統,用戶數據越來越難維護,復雜度越來越高,同時用戶量越來越大,經常會遇到高并發性能問題,不容易做獨立性能優化,因此拆分出獨立的用戶通行證微服務迫在眉睫。
舊用戶數據獲取方式
?
用戶通行證微服務
?
拆分出用戶通行證微服務之后,我們解決了以下問題:
-
代碼復用性,原先幾乎每個業務系統都散落有用戶邏輯代碼,到處都是拷貝代碼,拆分出用戶通行證微服務之后,業務系統只需調用用戶通行證微服務接口即可;
-
用戶數據一致性,以前由于獲取以及修改用戶數據代碼散落在各個業務系統,經常會產生一些用戶臟數據,并且很難查詢在哪個系統修改了用戶數據,同時由于不同的研發人員開發維護不同的業務系統,也給維護用戶數據一致性帶來了很大的挑戰,拆分出用戶通行證微服務之后,所有跟用戶邏輯相關的功能,都由用戶通行證微服務提供,保證了修改數據以及獲取數據的接口一致性;
-
用戶數據解耦,原有業務系統中經常會join用戶表獲取用戶數據,難以拆分,拆分出微服務之后,用戶數據庫獨立設計部署,方便進行擴容以及性能優化。
微服務治理
微服務架構開發、測試、部署復雜度遠遠大于單體架構,因此需要構建能夠支撐微服務架構的交付和運維能力。
\1. 版本發布系統
微服務架構的應用開發、部署的復雜度都是遠大于單體架構應用的,大量的微服務組件如果依然靠運維人員手工的配置管理顯然是難于應付了,因此我們研發了自動化部署和發布的版本發布系統,我們的版本發布系統具有以下特性:
-
項目配置包括項目名稱、管理員、項目成員、SVN/Git地址、帳號、服務啟動的Shell、自定義腳本、不同環境的JVM配置、Web容器配置等等;
-
按照項目配置好之后,可以發起上線申請單,通過審批之后,一鍵即可部署;
-
支持灰度發布,可以灰度選擇服務器進行版本發布,確保版本發布安全穩定;
-
可以實時收集部署過程產生的日志,可視化實時監控部署過程產生的問題;
-
針對發布異常,我們有發布異常處理機制,針對有多臺服務器的情況,可以選擇只要有失敗就停止發布,即一臺發布出錯,后續其余服務器停止發布,也可以選擇不管是否有失敗都繼續發布;
-
快速回滾,針對版本發布出現異常的情況,我們支持快速回滾,可以快速回滾到上一個穩定的版本。
通過版本發布系統,實現代碼版本管理、一鍵部署上線、一鍵快速回滾、上線單申請、上線審核以及上線日志等。
\2. 開發測試發布部署
針對微服務復雜的架構,為了保證每個微服務交付的質量,我們部署了四個環境:
-
開發環境,供研發人員在開發、調試階段使用;
-
測試環境,研發人員在開發環境完成所有功能開發、測試之后,部署給測試人員進行驗收的環境;
-
預發布環境,在完成測試環境的功能驗收之后,功能發布至生產環境前的一個預演環境,與生產環境共用相同的數據庫、緩存、MQ消息隊列等,用來在微服務上線生產環境前,確認是否還存在BUG等問題,不會影響生產環境的用戶,最終用來確保上線生產環境成功;
-
生產環境,即線上環境,是面向用戶的線上環境。
通過以上四個環境,確保微服務組件的研發、測試、發布的質量。
\3. 分布式配置中心以及分布式任務調度平臺
隨著微服務架構的實施,我們拆分出了很多的微服務以及子系統,各種配置信息都以明文形式配置在配置文件中,同時各種定時任務也散落在各個微服務以及子系統中,非常難管理。因此我們選擇了合適的分布式配置中心以及分布式任務調度平臺
-
Disconf分布式配置管理平臺,實現了配置發布統一化,所有配置都存儲在云端系統,用戶統一在平臺上進行發布、更新配置,更改配置時,無需重新打包或重啟微服務,通過管理平臺直接修改即可,同時我們進行了個性化定制研發,所有配置信息都實現了加密方式,避免賬號、密碼等敏感信息泄露;
?
-
Elastic-Job分布式任務調度平臺,實現了定時任務注冊中心、任務分片、任務運行服務器彈性擴容縮容、失效轉移、任務停止恢復和禁用等特性,更方便的管理分布式架構環境中的定時任務。
\4. 全鏈路跟蹤
微服務架構拆分了大量的子系統以及微服務組件,面對如此復雜大規模分布式集群,一次鏈路調用可能會發生在多個微服務組件之間,如何進行鏈路調用追蹤,如何快速發現一次接口調用過程中哪些地方需要優化、哪個微服務接口導致了整體調用比較慢。針對上述問題,我們引入了美團點評的APM工具Cat實時監控系統,與Dubbo服務化框架進行整合,通過全局鏈路ID,實現鏈路追蹤功能。
\5. 微服務授權
默認Dubbo沒有實現服務授權功能,系統調用微服務、微服務之間調用均沒有實現授權驗證,都是直接訪問微服務組件接口,因此我們針對Dubbo進行了個性化定制研發,研發了微服務授權認證中心,通過授權認證保證核心微服務接口的調用安全性。
\6. 微服務監控
拆分出大量的微服務組件,我們面對的是如何監控這么多的微服務運行狀態,我們采用了Dubbo自帶的簡易監控中心,監控微服務組件的成功率、失敗率、平均耗時、最大耗時、并發量等指標,通過這些指標發現微服務性能瓶頸,進而優化微服務性能。同時我們進行個性化定制擴展與研發,針對Dubbo接口調用,統計接口耗時排行、接口失敗排行、接口訪問異動排行等等,通過定制化研發的統計報表,更直觀的監控Dubbo接口性能。
\7. 微服務管理
我們使用Dubbo的管理控制臺,實現對微服務的路由規則配置、訪問控制、權重調節、服務降級、服務禁用、容錯等功能,可以非常方便的管理運行中的微服務組件。
經過一年多的微服務化歷程,V3.0架構如下:
?
V3.0微服務架構具有以下特點:
?
-
完全實現了分布式部署架構,系統與微服務組件都非常容易擴展;
-
以服務為中心,全面構建了微服務組件;
-
系統、微服務組件、緩存、MQ消息隊列、DB等均無單點風險,全部實現了HA高可用;
未來—貝聊架構演進V4.0
V3.0架構雖然實現了微服務架構,但該架構還存在以下可以繼續演進的點:
-
Docker容器部署,Docker具備輕量級、快速部署、隔離應用、跨平臺的優勢,微服務非常適合與Docker結合進行快速部署,目前雖然我們實現了微服務架構,但還未做到快速彈性擴展,如果將微服務與Docker容器進行結合,可以實現快速彈性擴展,業務高峰期可以快速自動擴展服務器,業務低峰期可以自動回收服務器,接下來我們即將實施微服務組件的Docker容器化部署;
-
統一API網關,目前我們的核心API還只是一個統一的代理層,尚不具備網關的身份認證、防報文重放與防數據篡改、業務鑒權、流量與并發控制等等功能,實施API網關后,可以實現前后端分離,提供便捷的監控、報警、分析,還可以提供嚴格的權限管理以及流量限制,保障API的安全穩定。接下來我們將實施統一的API網關控制;
-
跨IDC機房部署,目前我們的系統還是單機房部署,單機房不具備冗余以及容災機制,首先我們將逐漸實施同地多機房部署,先具備多機房部署能力,避免單機房故障,最后我們再實施異地跨IDC機房部署,達到異地冗余高可用以及用戶就近訪問的目的。
總結
架構演進一直在路上,架構要圍繞業務進行,不能脫離于業務,不同的業務時期需要不同的架構。
單體應用架構,更適合創業初期,公司需要快速試錯以及驗證市場反應,需要更快的研發速度,同時研發人員比較少,而單體應用架構比較簡單,可以快速切入,對研發人員的技術棧要求不是特別高,可以快速上手快速研發,但在設計單體應用架構時最好可以提前規劃好未來的擴展性,可以在業務層面先規劃好,便于日后業務發展到一定規模,可以快速進行解耦,實施微服務化架構。
當企業發展到一定規模,業務線變的越來越多、越來越復雜,同時研發人員的數目也快速增長,單體應用架構就會慢慢暴露出來弊端,大量的研發人員在一個系統上進行開發,缺少并行研發能力,大量的業務代碼耦合在一起,同時研發效率非常低。微服務架構可以更好的進行業務解耦,具備更好的擴展性以及獨立性,可以提高研發團隊間的并行化研發速度,提升效率、提高模塊復用性,具備高可用、高并發特性。但微服務架構對服務治理的能力要求比較高,維護成本也會比單體應用高,需要強大的服務治理支持,對研發人員的技術能力要求也比較更高。
目前我們依然在架構演進的路上,經歷了以上幾次架構歷程,雖然取得了一定的進步,但依然有很多挑戰等待我們去迎戰。規劃技術架構需要綜合考慮業務的規模、業務的時效性、研發團隊的規模、研發的技術能力、基礎環境配置等。架構來源于業務,架構演進的生命周期只有完美匹配好業務的生命周期,才能最終發揮出最好的效果。
總結
以上是生活随笔為你收集整理的新5 年时间服务器从 0 到 200,一个创业公司的架构野蛮生长史头疼哈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 某小公司项目环境部署演变之路
- 下一篇: 如何用 Git 优雅回退代码,别搞错了!