摘要:趁實(shí)習(xí)前的這段業(yè)余時(shí)間,我實(shí)現(xiàn)了一個(gè)輕量級(jí)的分布式框架,名字叫做,代碼量不大,但是麻雀雖小卻五臟俱全。目前支持和兩種序列化框架。使用實(shí)現(xiàn)服務(wù)注冊(cè)與發(fā)現(xiàn)功能。代碼實(shí)現(xiàn)是我學(xué)習(xí)驗(yàn)證過(guò)程中誕生的一個(gè)輕量級(jí)分布式框架,代碼放在了。
遠(yuǎn)程過(guò)程調(diào)用(Remote Procedure Call,RPC)是一個(gè)計(jì)算機(jī)通信協(xié)議。該協(xié)議允許運(yùn)行于一臺(tái)計(jì)算機(jī)的程序調(diào)用另一臺(tái)計(jì)算機(jī)的子程序,而程序員無(wú)需額外地為這個(gè)交互作用編程。RPC的主要目標(biāo)是讓構(gòu)建分布式應(yīng)用更加容易,在提供強(qiáng)大的遠(yuǎn)程調(diào)用能力的同時(shí)不損失本地調(diào)用的語(yǔ)義的簡(jiǎn)潔性。
趁實(shí)習(xí)前的這段業(yè)余時(shí)間,我實(shí)現(xiàn)了一個(gè)輕量級(jí)的分布式RPC框架,名字叫做 buddha,代碼量不大,但是麻雀雖小卻五臟俱全。本篇文章將一步步闡明buddha的設(shè)計(jì)、框架組件的拆解以及需要考慮的因素。
序列化與反序列化在網(wǎng)絡(luò)中,所有的數(shù)據(jù)都將會(huì)被轉(zhuǎn)化為字節(jié)進(jìn)行傳送,所以在代碼層面上,一個(gè)RPC框架需要實(shí)現(xiàn)特定格式的數(shù)據(jù)與字節(jié)數(shù)組之間的相互轉(zhuǎn)化。像Java已經(jīng)提供了默認(rèn)的序列化方式,但是如果是在高并發(fā)的場(chǎng)景下,使用Java原生的序列化方式可能會(huì)遇到性能瓶頸。于是,出現(xiàn)了許多開源的、高效的序列化框架:如Kryo、fastjson和Protobuf等。buddha目前支持Kryo和fastjson兩種序列化框架。
TCP拆包、粘包由于TCP只關(guān)心字節(jié)流,并不知曉上層的數(shù)據(jù)格式。如果客戶端應(yīng)用層一次要發(fā)送的數(shù)據(jù)過(guò)大時(shí),TCP會(huì)將該數(shù)據(jù)進(jìn)行分解傳送,因此在服務(wù)端需要進(jìn)行粘包處理(由TCP來(lái)保證數(shù)據(jù)的有序性);如果客戶端一次要發(fā)送的數(shù)據(jù)量很小時(shí),TCP并不會(huì)馬上把數(shù)據(jù)發(fā)送出去,而是將其存儲(chǔ)在緩沖區(qū),當(dāng)達(dá)到某個(gè)閾值的時(shí)候再發(fā)送出去,因此在服務(wù)端需要進(jìn)行拆包的工作。
通過(guò)以上分析,我們了解了TCP粘包或者拆包的原因,解決這個(gè)問(wèn)題的關(guān)鍵在于向數(shù)據(jù)包添加邊界信息,常用的方法有如下三個(gè)。
發(fā)送端給每個(gè)數(shù)據(jù)包添加包首部,首部中至少包含數(shù)據(jù)包的長(zhǎng)度,這樣在接收端接收到數(shù)據(jù)時(shí),通過(guò)讀取首部的長(zhǎng)度信息得到該數(shù)據(jù)包有效數(shù)據(jù)的長(zhǎng)度。
發(fā)送端將每個(gè)數(shù)據(jù)包封裝為固定長(zhǎng)度(多余用0填充),這樣接收端在接收到數(shù)據(jù)后根據(jù)約定好的固定長(zhǎng)度讀取每個(gè)數(shù)據(jù)包的數(shù)據(jù)。
使用特殊符號(hào)將每個(gè)數(shù)據(jù)包區(qū)分開來(lái),接收端也是通過(guò)該特殊符號(hào)的劃分?jǐn)?shù)據(jù)包的邊界。
buddha采用第一種方式來(lái)解決TCP拆包、粘包的問(wèn)題。
BIO與NIOBIO往往用于經(jīng)典的每連接每線程模型,之所以使用多線程,是因?yàn)橄?b>accept()、read()和write()等函數(shù)都是同步阻塞的,這意味著當(dāng)應(yīng)用為單線程且進(jìn)行IO操作時(shí),如果線程阻塞那么該應(yīng)用必然會(huì)進(jìn)入掛死狀態(tài),但是實(shí)際上此時(shí)CPU是處于空閑狀態(tài)的。開啟多線程,就可以讓CPU去為更多的線程服務(wù),提高CPU的利用率。但是在活躍線程數(shù)較多的情況下,采用多線程模型回帶來(lái)如下幾個(gè)問(wèn)題。
線程的創(chuàng)建和銷毀代價(jià)頗高,在Linux操作系統(tǒng)中,線程本質(zhì)上就是一個(gè)進(jìn)程,創(chuàng)建和銷毀線程屬于重量級(jí)的操作。
在JVM中,每個(gè)線程會(huì)占用固定大小的??臻g,而JVM的內(nèi)存空間是有限的,因此如果線程數(shù)量過(guò)多那么線程本身就會(huì)占據(jù)過(guò)多的資源。
線程的切換成本較高,每次線程切換需要涉及上下文的保存、恢復(fù)以及用戶態(tài)和內(nèi)核態(tài)的切換。如果線程數(shù)過(guò)多,那么會(huì)有較大比例的CPU時(shí)間花費(fèi)在線程切換上。
使用線程池的方式解決前兩個(gè)問(wèn)題,但是線程切換帶來(lái)的開銷還是存在。所以在高并發(fā)的場(chǎng)景下,傳統(tǒng)的BIO是無(wú)能為力的。而NIO的重要特點(diǎn)是:讀、寫、注冊(cè)和接收函數(shù),在等待就緒階段都是非阻塞的,可以立即返回,這就允許我們不使用多線程充分利用CPU。如果一個(gè)連接不能讀寫,可以把這個(gè)事件記錄下來(lái),然后切換到別的就緒的連接進(jìn)行數(shù)據(jù)讀寫。在buddha中,Netty被用來(lái)編寫結(jié)構(gòu)更加清晰的NIO程序。
服務(wù)注冊(cè)與發(fā)現(xiàn)在實(shí)際應(yīng)用中,RPC服務(wù)的提供者往往需要使用集群來(lái)保證服務(wù)的穩(wěn)定性與可靠性。因此需要實(shí)現(xiàn)一個(gè)服務(wù)注冊(cè)中心,服務(wù)提供者將當(dāng)前可用的服務(wù)地址信息注冊(cè)至注冊(cè)中心,而客戶端在進(jìn)行遠(yuǎn)程調(diào)用時(shí),先通過(guò)服務(wù)注冊(cè)中心獲取當(dāng)前可用的服務(wù)列表,然后獲取具體的服務(wù)提供者的地址信息(該階段可以進(jìn)行負(fù)載均衡),根據(jù)地址信息向服務(wù)提供者發(fā)起調(diào)用??蛻舳丝梢跃彺婵捎梅?wù)列表,當(dāng)注冊(cè)中心的服務(wù)列表發(fā)生變更時(shí)需要通知客戶端。同時(shí),當(dāng)服務(wù)提供者變?yōu)椴豢捎脿顟B(tài)時(shí)也需要通知注冊(cè)中心服務(wù)不可用。buddha使用ZooKeeper實(shí)現(xiàn)服務(wù)注冊(cè)與發(fā)現(xiàn)功能。
代碼實(shí)現(xiàn)buddha是我學(xué)習(xí)驗(yàn)證RPC過(guò)程中誕生的一個(gè)輕量級(jí)分布式RPC框架,代碼放在了 GitHub。
參考RPC 的概念模型與實(shí)現(xiàn)解析
NettyRpc
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67289.html
摘要:都是分開部署,單獨(dú)上線的。序列化畢竟是遠(yuǎn)程通信,需要將對(duì)象轉(zhuǎn)化成二進(jìn)制流進(jìn)行傳輸。服務(wù)化架構(gòu)的演進(jìn)架構(gòu)當(dāng)業(yè)務(wù)規(guī)模很小時(shí),將所有功能都不熟在同一個(gè)進(jìn)程中,通過(guò)雙機(jī)或者負(fù)載均衡器實(shí)現(xiàn)負(fù)債分流此時(shí),分離前后臺(tái)邏輯的架構(gòu)是關(guān)鍵。 showImg(https://segmentfault.com/img/bVbiI2F?w=2250&h=1500); 前言 為什么需要RPC,而不是簡(jiǎn)單的HTTP...
摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對(duì)以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問(wèn)題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...
摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對(duì)以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問(wèn)題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...
摘要:具體可以參考消息隊(duì)列之具體可以參考實(shí)戰(zhàn)之快速入門十分鐘入門阿里中間件團(tuán)隊(duì)博客是一個(gè)分布式的可分區(qū)的可復(fù)制的基于發(fā)布訂閱的消息系統(tǒng)主要用于大數(shù)據(jù)領(lǐng)域當(dāng)然在分布式系統(tǒng)中也有應(yīng)用。目前市面上流行的消息隊(duì)列就是阿里借鑒的原理用開發(fā)而得。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問(wèn)題,目前已經(jīng)開源,會(huì)一直完善下去,歡迎建議和指導(dǎo)歡迎Star: https://github.com/Snail...
摘要:面向服務(wù)面向服務(wù)的基礎(chǔ)面向服務(wù)的三層應(yīng)用層,服務(wù)層,數(shù)據(jù)層應(yīng)用層用于給用戶展示,,,,安卓。在服務(wù)器端,進(jìn)程保持睡眠狀態(tài)直到調(diào)用信息到達(dá)為止。編譯完成,提示我們已經(jīng)在下了。 面向服務(wù) 面向服務(wù)的基礎(chǔ) 面向服務(wù)的三層:應(yīng)用層,服務(wù)層,數(shù)據(jù)層 * 應(yīng)用層:用于給用戶展示,PC,H5,IOS,安卓。 * 服務(wù)層:業(yè)務(wù)邏輯,提供接口(商品,訂單,支付,用戶,物流)。 * 數(shù)據(jù)層:提供數(shù)據(jù)支持(...
閱讀 2277·2023-04-26 01:57
閱讀 3298·2023-04-25 16:30
閱讀 2352·2021-11-17 09:38
閱讀 1116·2021-10-08 10:14
閱讀 1421·2021-09-23 11:21
閱讀 3724·2019-08-29 17:28
閱讀 3490·2019-08-29 15:27
閱讀 974·2019-08-29 13:04