高效的數(shù)據(jù)序列化框架
實(shí)現(xiàn)RPC框架的分布式協(xié)議允許程序在不同計(jì)算機(jī)上進(jìn)行交互,而無需為此編寫額外的代碼。RPC的目標(biāo)是讓構(gòu)建分布式應(yīng)用更加容易,同時(shí)保持本地調(diào)用的簡潔性。在代碼層面上,一個(gè)RPC框架需要實(shí)現(xiàn)將數(shù)據(jù)轉(zhuǎn)化為字
實(shí)現(xiàn)RPC框架的分布式協(xié)議允許程序在不同計(jì)算機(jī)上進(jìn)行交互,而無需為此編寫額外的代碼。RPC的目標(biāo)是讓構(gòu)建分布式應(yīng)用更加容易,同時(shí)保持本地調(diào)用的簡潔性。在代碼層面上,一個(gè)RPC框架需要實(shí)現(xiàn)將數(shù)據(jù)轉(zhuǎn)化為字節(jié)數(shù)組以及字節(jié)數(shù)組與數(shù)據(jù)之間的相互轉(zhuǎn)換。雖然Java已經(jīng)提供了默認(rèn)的序列化方式,但在高并發(fā)場(chǎng)景下可能會(huì)遇到性能瓶頸。因此,出現(xiàn)了許多開源的、高效的序列化框架,例如Kryo、fastjson和Protobuf等。buddha目前支持Kryo和fastjson兩種序列化框架。
TCP拆包與粘包處理
TCP關(guān)注的是字節(jié)流,不了解上層數(shù)據(jù)的格式。當(dāng)客戶端應(yīng)用層一次要發(fā)送的數(shù)據(jù)過大時(shí),TCP會(huì)將數(shù)據(jù)進(jìn)行分解傳輸,因此服務(wù)端需要進(jìn)行粘包處理(由TCP保證數(shù)據(jù)的有序性)。另一方面,如果客戶端一次要發(fā)送的數(shù)據(jù)量很小,TCP則不會(huì)立即發(fā)送數(shù)據(jù),而是將其存儲(chǔ)在緩沖區(qū)中,當(dāng)達(dá)到某個(gè)閾值時(shí)再發(fā)送。這就需要在服務(wù)端進(jìn)行拆包的工作。為解決這類問題,我們可以向數(shù)據(jù)包添加邊界信息,在發(fā)送端給每個(gè)數(shù)據(jù)包添加包首部,其至少包含了數(shù)據(jù)包的長度。接收端在接收到數(shù)據(jù)時(shí),通過讀取首部的長度信息來獲取有效數(shù)據(jù)的長度。此外,發(fā)送端還可以將每個(gè)數(shù)據(jù)包封裝為固定長度(多余的位置用0填充),接收端則根據(jù)約定好的固定長度讀取每個(gè)數(shù)據(jù)包的數(shù)據(jù)。另一種方法是使用特殊符號(hào)將每個(gè)數(shù)據(jù)包區(qū)分開來,接收端也可以通過該特殊符號(hào)來劃分?jǐn)?shù)據(jù)包的邊界。buddha采用添加包首部的方式來解決TCP拆包和粘包的問題。
多線程與NIO優(yōu)化
傳統(tǒng)的BIO(同步阻塞)模型中,像accept()、read()和write()等函數(shù)都是同步阻塞的。這意味著當(dāng)應(yīng)用程序以單線程進(jìn)行IO操作時(shí),如果線程被阻塞,應(yīng)用程序就會(huì)進(jìn)入掛死狀態(tài),而CPU卻處于空閑狀態(tài)。通過開啟多線程,可以讓CPU為更多的線程提供服務(wù),提高CPU的利用率。然而,線程切換帶來的開銷仍然存在。因此,在高并發(fā)場(chǎng)景下,傳統(tǒng)的BIO模型無法滿足需求。相比之下,NIO(非阻塞IO)模型具有重要特點(diǎn):讀、寫、注冊(cè)和接收函數(shù)在等待就緒階段都是非阻塞的,可以立即返回。這允許我們?cè)诓皇褂枚嗑€程的情況下,充分利用CPU資源。如果一個(gè)連接不能讀寫,可以將該事件記錄下來,并切換到其他就緒的連接進(jìn)行數(shù)據(jù)讀寫。在buddha中,我們使用Netty來編寫結(jié)構(gòu)更加清晰的NIO程序。
服務(wù)注冊(cè)與發(fā)現(xiàn)
為了保證RPC服務(wù)的穩(wěn)定性和可靠性,RPC服務(wù)提供者通常需要使用集群。因此,我們需要實(shí)現(xiàn)一個(gè)服務(wù)注冊(cè)中心,服務(wù)提供者將當(dāng)前可用的服務(wù)地址信息注冊(cè)到注冊(cè)中心。當(dāng)客戶端進(jìn)行遠(yuǎn)程調(diào)用時(shí),首先通過服務(wù)注冊(cè)中心獲取當(dāng)前可用的服務(wù)列表,然后獲取具體服務(wù)提供者的地址信息(可以進(jìn)行負(fù)載均衡),并向服務(wù)提供者發(fā)起調(diào)用。這種服務(wù)注冊(cè)與發(fā)現(xiàn)的機(jī)制能夠有效地管理和調(diào)度分布式系統(tǒng)中的服務(wù)。