架構(gòu)的終極目標(biāo)是降本增效硅确。是各方面折中的結(jié)果。
本文以互聯(lián)網(wǎng)軟件架構(gòu)的演進之路為主線明肮,結(jié)合案例分析每個階段架構(gòu)的適用場景菱农、技術(shù)棧和優(yōu)缺點。
0柿估、架構(gòu)的本質(zhì)
架構(gòu)是對業(yè)務(wù)場景抽象后循未,對各方面因素折中后的結(jié)果,這些因素包括:
- 業(yè)務(wù)復(fù)雜度
- 數(shù)據(jù)規(guī)模大小
- 團隊技術(shù)棧/研發(fā)能力
- 時間成本
- 運維成本
只有對這些因素都妥善折中后秫舌,才能達到降本增效的目的的妖。
場景驅(qū)動架構(gòu)不斷演進,脫離場景談架構(gòu)都是耍流氓足陨。
1嫂粟、架構(gòu)演進概述
從單體架構(gòu)演進到微服務(wù)架構(gòu)的精髓用一個字概括:拆。
2墨缘、單體架構(gòu)設(shè)計與實踐
客戶端APP發(fā)送請求到單體服務(wù)星虹,服務(wù)端接收到請求后從DB讀取數(shù)據(jù)零抬,并進行業(yè)務(wù)邏輯處理,最后對返回結(jié)果進行封裝宽涌,返回結(jié)果給APP平夜。
- 案例 (如下比較簡單的案例可以用單體來實現(xiàn))
如用戶個人主頁,獲取用戶個人詳細信息等簡單場景卸亮。 - 實踐
MVC框架套用在單體上:
--M:數(shù)據(jù)庫讀取數(shù)據(jù)
--V:封裝結(jié)果返回
--C:業(yè)務(wù)邏輯處理
2.1 單體架構(gòu)優(yōu)點
只有一個進程忽妒,簡單。
注意單體架構(gòu)實際也必須擴展兼贸,即使只有一個QPS段直,生產(chǎn)環(huán)境下也不能只部署一個單體實例。
上圖中溶诞,生產(chǎn)環(huán)境中Nginx一般也至少兩臺坷牛,前面還有一組主備的LVS,LVS的VIP直接和app交互很澄。
上面的單體WAR必須是無狀態(tài)的,才是可擴展的颜及,因為這樣它的冗余備份才是完全對等的甩苛。
2.2 單體架構(gòu)適用場景:
- 業(yè)務(wù)場景簡單、功能不負(fù)責(zé)俏站、人員少
如O2O - 創(chuàng)業(yè)公司初期
- 性能要求極其苛刻
性能指吞吐量和RTT(響應(yīng)延遲)
金融案例:
股票讯蒲、虛擬幣等高頻交易的背景下,量化交易軟件要及時毫秒級捕捉價格變化肄扎。所以service和DB最好在一臺機器上(單體)墨林,請求端和服務(wù)端也盡量在同一機房。
思考下公司哪些業(yè)務(wù)適用于單體架構(gòu)犯祠。
單體架構(gòu)缺點
單體架構(gòu)最大的一個痛點就是耦合度太高旭等,業(yè)務(wù)壯大后都在一個單體內(nèi)肯定不行。
拆分
由此衡载,單體架構(gòu)需要破局演進搔耕。很自然想到,把上圖單體服務(wù)原本的一個進程安裝業(yè)務(wù)種類垂直拆成三個服務(wù)進程痰娱。當(dāng)然可以按功能水平拆分弃榨,并且數(shù)據(jù)庫也需要拆。
總結(jié):
1梨睁、 數(shù)據(jù)庫存儲量大 鲸睛、請求量大,拆分主要兩種方式:
- 垂直拆分(分庫)
- 水平拆分(分表)
如uid取模
2坡贺、 架構(gòu)拆分
其實架構(gòu)的拆分也和DB的拆分的思路是類似的:
- 垂直分拆(業(yè)務(wù)維度)
- 水平分拆(功能維度)
3官辈、面向服務(wù)架構(gòu)設(shè)計與實踐
SOA是由單體架構(gòu)的垂直方向拆分演變而來箱舞。
但是生產(chǎn)中的SOA架構(gòu)和上圖這樣的理想模型是有一點差別的。
以58為例:
每個單體有自己的DB钧萍,服務(wù)間通信有soap(也可以json)褐缠。
3.1 SOA架構(gòu)缺點
- 僅垂直方向拆分
- 每個服務(wù)還是單體服務(wù)
- 有一些公共服務(wù)并沒有抽象出來
- 服務(wù)間通信消耗較大
思考:公司里哪些業(yè)務(wù)適用于SOA/ESB
4、水平分層架構(gòu)設(shè)計與實踐
按請求功能進行聚類风瘦。
水平風(fēng)向拆分队魏,如電商案例(按請求鏈路拆分)
APP到GW 傳輸部分用的http協(xié)議,數(shù)據(jù)部分用json万搔。
網(wǎng)關(guān)到業(yè)務(wù)邏輯層一般用TCP(也可以用http2.0胡桨,支持長連接,機房內(nèi)部可以用)瞬雹,數(shù)據(jù)部分用pb/msgpack昧谊,可以跨語言的。
數(shù)據(jù)訪問層到DB是SQL2003.
業(yè)務(wù)邏輯層和數(shù)據(jù)訪問層可以考慮合并成一個進程酗捌,從而降低分層后交互的延遲呢诬。又能節(jié)省成本。
接下來深入介紹每一層的功能胖缤。
網(wǎng)關(guān)層功能
純數(shù)據(jù)尚镰,前后端分離。
- 功能一: 請求鑒權(quán)
發(fā)布商品哪廓,登錄鑒權(quán)狗唉。看此用戶是否帶著session涡真,以及session是否合法分俯。 - 功能二: 數(shù)據(jù)完整性檢查
數(shù)據(jù)包定長header + 變長body。
主要是檢查header各個字段有沒有填寫哆料。
header: uid + cmd + session id + body length
變長body:{k1:v1, k2:v2}(網(wǎng)關(guān)是不關(guān)心這部分缸剪,因為屬于業(yè)務(wù)語義部分。)
- 功能三: 協(xié)議轉(zhuǎn)換
JSON -> HashMap(String,Object) -> pb(proto buffer)
在golang中可以用grpc來解決东亦? - 功能四: 路由轉(zhuǎn)發(fā)
根據(jù)CMD轉(zhuǎn)發(fā)到不同業(yè)務(wù)邏輯層 - 功能五:服務(wù)治理
限流橄登、降級、熔斷
網(wǎng)關(guān)層框架對比
業(yè)務(wù)邏輯層功能
- 功能一: 業(yè)務(wù)邏輯判斷
- 案例一: 微信黑明單檢查
- 案例二: 微信好友刪除
業(yè)務(wù)編排就是在這層做讥此。
數(shù)據(jù)訪問層功能
- 功能一: CRUD
業(yè)務(wù)增刪改查接口(批量) - 功能二: ORM
MyBatis3 - 功能三:Sharding(分庫分表)(可選)
Sharding-JDBC (sharding sphere)
這部分最難拢锹,最好不分庫分表。所以mysql-> mongo - >TiDB - 功能四: 屏蔽底層存儲差異性
MySQL/MongoDB, Redis, TiDB
4.1 水平分層架構(gòu)服務(wù)和協(xié)議
思考如何把同步變異步萄喳。加個MQ就可以卒稳。
所以上面如果想異步,MQ要加在GW與logic層之間他巨。
請求異步
- 讀請求:不可以異步(臟讀)
- 寫請求:
- AP(社交場景)可以:如發(fā)朋友圈失敗充坑,gw可以把數(shù)據(jù)發(fā)給app緩存减江,但重試三次后都不能持久化,則發(fā)給用戶提示發(fā)送失敗捻爷。
- CP(發(fā)紅包場景)不可以:
4.2 水平分層架構(gòu)缺點
-
粒度太粗
如業(yè)務(wù)邏輯層會部署多個實例辈灼,但是公司所有的服務(wù)邏輯都在一起,粒度太粗也榄。
4.3 水平層次劃分案例
后來路由層干掉了巡莹,存到Redis
百度空間案例:
5、微服務(wù)架構(gòu)與實踐
既做水平拆分甜紫,又做垂直拆分就是微服務(wù)降宅。比SOA粒度更小,且去掉了ESB囚霸。
沒必要按DDD來做腰根,落地難度太大。
微服務(wù)中垂直拆分不容易拓型。比如额嘿,用戶功能中有用戶注冊、用戶登錄劣挫、用戶查詢岩睁。讀(用戶登錄)會影響寫(用戶注冊),因此要考慮讀寫分離揣云,所以這樣就是按API的粒度來拆分,其實是否要拆主要就看讀寫之間影響是不是很大冰啃。另如下單和查詢邓夕。
再如user,user主庫用于寫阎毅,從庫用于讀焚刚。從庫沒有數(shù)據(jù),再去主庫查冤议。但是insert可以凡桥,update不行名挥,解決方案是主從強同步,主進行切片碳柱。根據(jù)uid就可以知道落到哪個庫“疚撸或者采用集群的方式莲镣。
網(wǎng)關(guān)層相當(dāng)于SaaS層。
一般沒必要按API的粒度去拆分涎拉。
以上不同層其實可以用不同語言來寫瑞侮。
微服務(wù)問題1:服務(wù)設(shè)計和服務(wù)治理強耦合的圆。
微服務(wù)問題2: 基礎(chǔ)組件升級困難
微服務(wù)問題3:多語言之間通信問題
解決方案:微服務(wù)2.0,即service mesh半火。就是把服務(wù)設(shè)計(業(yè)務(wù))和服務(wù)治理(通信)解耦越妈。
把通信組件獨立為一個進程,叫sidecar钮糖,和應(yīng)用程序在同一臺機器梅掠。
6. Service Mesh 架構(gòu)設(shè)計與實踐
- 最早由開發(fā)Linkerd的Buoyant公司提出,并在內(nèi)部使用藐鹤。
- 2016年9月第一次公開使用
- 2017年初瓤檐,Service Mesh進入國內(nèi)技術(shù)社區(qū)視野
服務(wù)網(wǎng)格化的目的:把和業(yè)務(wù)無關(guān)的服務(wù)治理功能剝離出來。
linkerd后來被istio被替代了娱节。
Service Mesh 優(yōu)勢
- SM獨立進程挠蛉,獨立升級
- 業(yè)務(wù)團隊可以更專注于業(yè)務(wù)邏輯本身
- 一套基礎(chǔ)設(shè)施支持多語言開發(fā)
- 業(yè)務(wù)團隊和基礎(chǔ)設(shè)施團隊物理解耦
- 服務(wù)治理和服務(wù)本身的物理剝離
重點注意,數(shù)據(jù)訪問流向肄满。
上圖數(shù)據(jù)訪問層訪問DB畫的不對谴古,應(yīng)直接訪問DB/Cache。
7. 大中臺架構(gòu)設(shè)計與實踐
同層調(diào)用不允許稠歉,可以直接跨層向下調(diào)用掰担,為了避免循環(huán)調(diào)用。
業(yè)務(wù)數(shù)據(jù)和中臺數(shù)據(jù)如何存儲
上圖是mysql要這么做怒炸,如果是MongoDB不需要擴展表带饱,只要一張表,因為不需要schema阅羹。
8. 云原生架構(gòu)設(shè)計與實踐
重點是部署勺疼。
- 云原生
最初由Pivotal公司2013年提出,該公司先后開源了云原生的java開發(fā)框架Spring Boot和Spring Cloud捏鱼。
2015年Google成立了CNCF(cloud native computing foundation),使得云原生受到了越來越多的關(guān)注执庐。而云原生真正在生產(chǎn)中普及,應(yīng)該說歸功于docker和k8s的發(fā)展和成熟导梆。 - 云原生架構(gòu)
指專門為云平臺部署和運行而設(shè)計的架構(gòu) - 云原生架構(gòu)本質(zhì)
- 按需使用和彈性伸縮
- 無狀態(tài)化設(shè)計(stateless)
- 自動化部署和管理
- CICD
9. 架構(gòu)演進
公共邏輯層即技術(shù)中臺轨淌。
架構(gòu)設(shè)計思考:
思考:
- Dubbo和grpc是一個層面的嗎?
- 同步和阻塞IO有啥區(qū)別看尼,異步和非阻塞IO
- OLAP和OLTP有何區(qū)別递鹉。前者搞數(shù)倉。
- 如何理解回調(diào)是進程內(nèi)的小異步藏斩。
- schema什么意思梳虽?行擴展。 shema不固定只能用列擴展灾茁?
- MongoDB這種free shema怎么存都行窜觉。但是mysql建議other字段存pb/json谷炸。