來騰訊之前在前公司做了3年的后端開發,經歷一款SaaS產品從0到10(還沒有到100, 哈哈哈)的程序,3年間后端的架構逐步演變,在微服務的實踐程序中遇到的問題也越來越多,在這里總結下,
產品是一款服務于人力資源的SaaS在線服務,面向HR有Web Android/iOS 小程式多個客戶端,后端采用RESTful風格API來提供服務,主要使用Python語言,方便快速迭代,
架構的演進經歷了4個大的階段:
一、MVC
專案剛開始的時候,后端同事不超過5個,這個階段主要的作業是實作產品的原型,沒有太多的考慮架構,使用Django來快速實作功能,DB的表結構設計好之后,抽象出功能View,由于產品設計也很不完善,后端需要很多的預留設計,避免產品邏輯的變更帶來整個表結構的變動,在這個階段代碼上最重要的是確定適合團隊的代碼規范,代碼檢查規則,
整體上架構如上圖,Nginx負責負載均衡,分發流量到多個Django服務,Django處理邏輯,需要異步任務就交給Celery,然后資料量比較大的地方使用Redis做快取,同時還有實時訊息通知的需要使用了Nginx Push Module,
問題與優化方式:
- Django并發性能差 使用uWSGI Master+Worker 配合 gevent 攜程支持高并發
- Redis連接數過多 使用redis-py自帶的連接池來實作連接復用
- MySQL連接數過多 使用djorm-ext-
pool(https://github.com/djangonauts/djorm-ext-pool)連接池復用連接 - Celery配置gevent支持并發任務
隨著開發的功能越來越多,Django下的app也越來越多,這就帶了發布上的不方便,每次發布版本都需要重啟所有的Django服務,如果發布遇到問題,只能加班解決了,而且單個Django工程下的代碼量也越來越多,不好維護,
二、服務拆分
隨著后端團隊的壯大,分給每個同事的需求也越來越細,如果繼續在一個工程里面開發所有的代碼,維護起來的代價太高,而我們的上一個架構中在Django里面已經按模塊劃分了一個個app,app內高類聚,app之間低耦合,這就為服務的拆分帶來了便利,
拆分的程序沒有遇到太大的問題,初期的拆分只是代碼的分離,把公用的代碼抽離出來實作一個公用的Python庫,資料庫,Redis還是共用,隨著負載的增加,資料庫也做了多實體,
如上圖,服務之間盡量避免相互呼叫,需要互動的地方采用http請求的方式,內網的呼叫使用hosts指向內網地址,
問題與優化方式:
Nginx Push Module由于長時間沒有維護,長連接最大數量不夠,使用Tornado + ZeroMQ實作了tormq(https://github.com/zhu327/tormq)服務來支撐訊息通知
服務之間的呼叫采用http的方式,并且要求有依賴的服務主機配置hosts指向被呼叫的地址,這樣帶來的維護上的不方便,以及在呼叫鏈的程序中沒有重試,錯誤處理,限流等等的策略,導致服務可用性差,
隨著業務拆分,繼續使用Nginx維護配置非常麻煩,經常因為修改Nginx的配置引發呼叫錯誤,每一個服務都有一個完整的認證程序,認證又依賴于用戶中心的資料庫,修改認證時需要重新發布多個服務,
三、微服務架構
首先是在接入層引入了基于OpenResty的Kong API Gateway,定制實作了認證,限流等插件,在接入層承接并剝離了應用層公共的認證,限流等功能,在發布新的服務時,發布腳本中呼叫Kong admin api注冊服務地址到Kong,并加載api需要使用插件,
為了解決相互呼叫的問題,維護了一個基于gevent+msgpack的RPC服務框架doge,借助于etcd做服務治理,并在rpc客戶端實作了限流,高可用,負載均衡這些功能,
在這個階段最難的技術選型,開源的API網關大多用Golang與OpenResty(lua)實作,為了應對我們業務的需要還要做定制,前期花了1個月時間學習OpenResty與Golang,并使用OpenResty實作了一個短網址服務shorturl用在業務中,
最終選擇Kong是基于Lua發布的便利性,Kong的開箱即用以及插件開發比較容易,性能的考量倒不是最重要的,為了支撐更多的并發,還使用了云平臺提供的LB服務分發流量到2臺Kong服務器組成的集群,集群之間自動同步配置,
餓了么維護一個純Python實作的thrift協議框架thriftpy,并提供很多配套的工具, 如果團隊足夠大,這一套RPC方案其實是合適的,但是我們的團隊人手不足,水平參差不齊,很難推廣這一整套學習成本高昂的方案,最終我們開發了類Duboo的RPC框架doge,代碼主要參考了weibo開源的motan,
四、領域驅動設計
在這一架構中我們嘗試從應用服務中抽離出資料服務層,每一個資料服務包含一個或多個界限背景關系,界限背景關系類只有一個聚合根來暴露出RPC呼叫的方法,資料服務不依賴于應用服務,應用服務可以依賴多個資料服務,有了資料服務層,應用就解耦了相互之間的依賴,高層服務只依賴于底層服務,
在我離職時領域驅動設計還在學習設計階段,還沒有落地,但是我相信前公司的后端架構一定會往這個方向繼續演進,
總結
架構的設計,技術的選型,不能完全按照流行的技術走,最侄訓是服務于產品,服務于客戶的需求,設計程序中由于團隊,人員的結構問題,有很多的妥協之處,如何在妥協中找到最優解才是最大的挑戰,
Service Mesh這種新一代的微服務架構正在成為主流,雖然現在的作業與微服務無關了,但是也還會繼續關注學習,
最后: 大家可以去我博客首頁看下側邊欄! 進去有許多資料共享!資料都是面試時面試官必問的知識點,也包括了很多測驗行業常見知識,其中包括了有基礎知識、Linux必備、Shell、互聯網程式原理、Mysql資料庫、抓包工具專題、介面測驗工具、測驗進階-Python編程、Web自動化測驗、APP自動化測驗、介面自動化測驗、測驗高級持續集成、測驗架構開發測驗框架、性能測驗、安全測驗等,
好文推薦
2021軟體測驗工程師面試題匯總(內含答案)-看完BATJ面試官對你豎起大拇指!
什么樣的人適合從事軟體測驗作業?
軟體測驗和軟體開發哪個發展更好
那個準點下班的人,比我先升職了…
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/295584.html
標籤:其他