1. 關(guān)于Vert.x
1.1 Vertx是什么
在學(xué)習(xí)Vert.x前一定要看看官網(wǎng)給他的定位
Eclipse Vert.x is a tool-kit for building reactive applications on the JVM.
所以,我們必須首先搞清楚,Vertx不是類似Spring的那一套大而全的框架或者管理對(duì)象的容器弃鸦、工廠
盡管我們不能期待它承擔(dān)一個(gè)完整的項(xiàng)目腳手架的角色抗碰,但是麻雀雖小,五臟俱全词疼,作為一個(gè)工具集碳胳,它包含web服務(wù)器應(yīng)用(其中又包含對(duì)http協(xié)議、http2延赌、序列化及反序列化、驗(yàn)證叉橱、鑒權(quán)等的支持)挫以、數(shù)據(jù)庫客戶端、服務(wù)通信組件等模塊窃祝,我們可以根據(jù)需要自行組合他們
其中的Vertx core是底層組件掐松,它基于Netty構(gòu)建而成,其中的核心概念有:
- Vertx實(shí)例:Vertx的控制中心粪小,承擔(dān)對(duì)Verticle大磺、event loop等組件的配置、啟動(dòng)等任務(wù)
- Event Loop:Vertx應(yīng)用運(yùn)行的基本機(jī)制探膊,本質(zhì)上說就是利用固定數(shù)量的線程處理所有業(yè)務(wù)邏輯杠愧。由于線程數(shù)量可控,編碼時(shí)無需考慮線程安全逞壁,線程資源分配的等問題流济。每個(gè)Vertx實(shí)例默認(rèn)維護(hù)的線程數(shù)量為2*CPU核數(shù)
- Worker Pool:執(zhí)行阻塞任務(wù)所使用的線程池锐锣,默認(rèn)線程數(shù)量為20
- Verticle:Vertx應(yīng)用中的基本部署單位,一般一個(gè)Vertx應(yīng)用包含一個(gè)或多個(gè)Verticle绳瘟,不同verticle之間使用event bus進(jìn)行通信
- Event Bus:不同verticle間的通信工具
1.2. Vertx的特點(diǎn)
-
異步:
維基百科對(duì)event loop的定義
the event loop is a programming construct or design pattern that waits for and dispatches events or messages in a program(事件循環(huán)是一種架構(gòu)或設(shè)計(jì)模式雕憔,它等待并分發(fā)程序中的事件、消息)
Vertx使用event loop機(jī)制處理業(yè)務(wù)邏輯糖声,這種架構(gòu)模式提高了系統(tǒng)資源利用率斤彼,可以確保處理主業(yè)務(wù)的線程不會(huì)被浪費(fèi)在等待I/O的結(jié)果上,但要做到這些姨丈,我們必須更改編碼風(fēng)格畅卓,將對(duì)I/O結(jié)果的處理邏輯用回調(diào)的形式一并傳遞給event loop,Vertx將在action1完成時(shí)主動(dòng)調(diào)用我們注冊(cè)的回調(diào)函數(shù)
我們的代碼將由之前的
result1 = action1()
action2(result1)
變?yōu)?/p>
action1(
result1 ->
action2(result1)
)
這種代碼結(jié)構(gòu)在Vertx項(xiàng)目里隨處可見蟋恬。顯然翁潘,一旦邏輯變得復(fù)雜,多重函數(shù)的嵌套將導(dǎo)致回調(diào)地獄歼争,Vertx為提供了Promise類解決這種問題拜马,通過傳遞Promise對(duì)象,我們可以以同步的方式處理異步的邏輯沐绒。
private Future<Void> action() {
Promise<void> promise = Promise.promise();
// (...)
return promise.future();
}
Vertx4.0承諾所有的異步API都將具有Promise返回值俩莽。另外,也可以使用Rxjava以流的方式處理數(shù)據(jù)
-
模塊化及通信的解耦
Vertx使用vertical劃分模塊乔遮,各模塊間只能通過event bus通信扮超,而不是通過聚合等方式相互調(diào)用,這樣我們就不需擔(dān)心模塊間耦合蹋肮。
event bus使用起來相當(dāng)簡單出刷,它使用Json作為的消息格式,我們僅需在消費(fèi)端定義監(jiān)聽地址(僅僅是一個(gè)字符串)坯辩,在生產(chǎn)端指定消息發(fā)送地址即可馁龟,并且它有3種通信模式:
- 請(qǐng)求-響應(yīng):向目標(biāo)地址發(fā)送消息并由回調(diào)方法處理一個(gè)期待響應(yīng)結(jié)果
- 異步推送:直接發(fā)送一條信息,不期待響應(yīng)
- 廣播:當(dāng)多個(gè)verticle訂閱了相同的地址漆魔,以上兩種模式發(fā)送的消息只能被至多一個(gè)消費(fèi)者收到坷檩,而廣播模式可以向多個(gè)消費(fèi)者發(fā)送消息
當(dāng)event bus檢測到收發(fā)方均為本地模塊時(shí),他的底層僅僅會(huì)對(duì)數(shù)據(jù)做序列化和反序列化的操作改抡,不會(huì)增加產(chǎn)生額外消耗矢炼。它甚至可以結(jié)合官方推出的其他組件(如TCP橋接、集群管理器等)很方便地實(shí)現(xiàn)跨進(jìn)程阿纤、跨設(shè)備的通信裸删,這使得一個(gè)Vertx可以及其方便進(jìn)行橫向拓展
每個(gè)vertical默認(rèn)只使用event loop中的一個(gè)線程進(jìn)行運(yùn)算,所以模塊內(nèi)部的邏輯是高內(nèi)聚的阵赠,可以隨意使用全局變量而無需擔(dān)心線程安全問題
“多線程”的event loop是Vertx的殺手锏涯塔,當(dāng)一個(gè)Vertx實(shí)例中的某個(gè)vertical負(fù)荷過大時(shí),我們可以在Vertx實(shí)例啟動(dòng)時(shí)直接指定此vertical的部署數(shù)量清蚀,充分利用CPU資源
2.響應(yīng)式編程
Don't call us,we'll call you.
響應(yīng)式的編程范式其實(shí)就是設(shè)計(jì)模式中“觀察者模式”的一種實(shí)踐
我們?cè)谠O(shè)計(jì)代碼結(jié)構(gòu)(或設(shè)計(jì)項(xiàng)目架構(gòu))時(shí)匕荸,并不直接地針對(duì)某個(gè)具體業(yè)務(wù)給出方案,而是分析業(yè)務(wù)涉及到的各個(gè)角色枷邪,并對(duì)思考他們自身在項(xiàng)目中的地位以及他們之間的聯(lián)系榛搔,最后構(gòu)建出各個(gè)模塊
重點(diǎn)考慮模塊是如何與其他模塊達(dá)到松耦合的:
- 簡單使用“觀察者模式”:那么在核心邏輯執(zhí)行前觀察者將自身的引用提供給目標(biāo)對(duì)象抽象(被觀察的主體),目標(biāo)對(duì)象維護(hù)一個(gè)觀察者列表东揣,待自身特定事件發(fā)生時(shí)践惑,一次性通知所有的觀察者
- Vertx中的vertical僅僅使用evnet bus組件與其他模塊通信,并且對(duì)任何阻塞操作僅允許通過回調(diào)的方式執(zhí)行后續(xù)邏輯
構(gòu)建一套響應(yīng)式系統(tǒng)使得系統(tǒng)間各模塊協(xié)作更為自然嘶卧,代碼健壯性更高
如果不使用第三方框架尔觉,單純自行設(shè)計(jì)這一套系統(tǒng)的成本是巨大的,僅考慮線程間的同步問題就夠喝一壺的了芥吟,更不用說如何去滿足業(yè)務(wù)需求
3.工具的使用
但是理想中完美的東西未必能在現(xiàn)實(shí)中發(fā)我們所預(yù)期作用
作為一個(gè)貫徹響應(yīng)式編程思維的工具集侦铜,Vertx提供了一整套完善的響應(yīng)式系統(tǒng),它對(duì)幾乎所有一般項(xiàng)目中的業(yè)務(wù)需求提供了解決方案钟鸵,但它終究不是一個(gè)具有工程屬性的重量級(jí)框架钉稍,例如數(shù)據(jù)庫相關(guān)組件僅僅是在原生驅(qū)動(dòng)的基礎(chǔ)上提供了一層極薄封裝
需要做“規(guī)范化”的工程時(shí),使用這樣的工具集我們不免陷入“再造輪子”的困境棺耍,所以贡未,在項(xiàng)目開始初期時(shí),需要結(jié)合多方面因素考慮蒙袍,選擇適合項(xiàng)目的工具俊卤,以達(dá)到工具的“為我所用”的目的