在現在的網(wǎng)絡(luò )編程實(shí)現中,大多數項目都會(huì )采用基于事件通知的異步網(wǎng)絡(luò ) IO 方式來(lái)實(shí)現。目前無(wú)論是 Epoll 還是 Kqueue 都已經(jīng)成為主流網(wǎng)絡(luò )編程知識,本文就不介紹這些基本概念和使用了。主要圍繞目前 Ceph 的網(wǎng)絡(luò )層實(shí)現來(lái)解構和探討如何重構。
在 Ceph 項目伊始的 06 年,那時(shí)候在網(wǎng)絡(luò )編程還是線(xiàn)程模型當道的年頭,Ceph 采用了簡(jiǎn)單粗暴的采用了每?jì)蓚(gè)線(xiàn)程對應一個(gè)終端的方式,其中一個(gè)用于監聽(tīng)和讀取該終端的讀事件,另一個(gè)用于寫(xiě)事件。我們可以簡(jiǎn)單稱(chēng)這兩個(gè)線(xiàn)程為一條連接的讀線(xiàn)程和寫(xiě)線(xiàn)程。讀線(xiàn)程得到請求以后會(huì )解析網(wǎng)絡(luò )流并開(kāi)始構建消息,然后派發(fā)到后面的 Dispatcher。寫(xiě)線(xiàn)程在大部分時(shí)候會(huì )處于 Sleep 狀態(tài),直到有新的消息需要發(fā)送才會(huì )被喚醒。
Ceph 在目前的網(wǎng)絡(luò )層面上有三個(gè)重要概念,分別是 Messenger,Pipe,Connection。Messenger 實(shí)際上可以理解為一個(gè)監聽(tīng)地址和多個(gè)連接的集合。比如每個(gè) OSD 中會(huì )有 cluster_messenger 和 public_messenger,顧名思義 cluster_messenger 負責給 OSD 與其他 OSD 和 Monitor 的通信并提供了一個(gè)監聽(tīng)地址,public_messenger 負責與客戶(hù)端的通信并提供了一個(gè)面向客戶(hù)端的監聽(tīng)地址。因此 cluster_messenger 中負責的連接會(huì )全部是面向其他 OSD 或者 Monitor 的連接。Pipe 實(shí)際上是一個(gè) Session 的載體,為了解決網(wǎng)絡(luò )連接不穩定或者臨時(shí)閃斷連接的問(wèn)題,Pipe 會(huì )一直維護面向一個(gè)終端地址的會(huì )話(huà)狀態(tài),如類(lèi)似 TCP 包序號的消息序號和發(fā)送隊列。Connection 就是一個(gè) socket 的 wrapper,它從屬于某一個(gè) Pipe。
上圖主要聚焦 OSD 端的網(wǎng)絡(luò )邏輯,客戶(hù)端實(shí)際上是一模一樣的網(wǎng)絡(luò )實(shí)現只是不會(huì )擁有一個(gè)監聽(tīng)端口。網(wǎng)絡(luò )上層的業(yè)務(wù)實(shí)際上只需要關(guān)注一個(gè)邏輯上的持久會(huì )話(huà),通過(guò) Dispatcher 得到消息處理,然后通過(guò) Connection 接口把消息放到發(fā)送隊列發(fā)送。
上面這個(gè)圖主要描述了一個(gè)會(huì )話(huà)建立的流程,其中 banner 類(lèi)似于一個(gè)宣告,然后互相了解對方的地址信息。主要邏輯在于 connection message 中的信息,服務(wù)器端會(huì )校驗這些連接信息并確保面向這個(gè)地址的連接只有一條,如果 client 發(fā)送了一個(gè)已經(jīng)建立會(huì )話(huà)的地址,服務(wù)器端會(huì )考慮是否需要替換或者廢棄當前連接。另外在這里會(huì )需要確定是否要發(fā)送驗證信息(圖中省略)。在會(huì )話(huà)成功后,實(shí)際上就對雙方當前的 Pipe 狀態(tài)達成了一致。
實(shí)際上我們從中很容易發(fā)現這個(gè)線(xiàn)程模型是存在重大問(wèn)題的,也就是隨著(zhù)一個(gè)實(shí)體(如 OSD)的增加會(huì )線(xiàn)性增加一個(gè)實(shí)體的線(xiàn)程數目。線(xiàn)程的增加會(huì )導致嚴重的 Context Switch 損耗,線(xiàn)程級的 Context Switch 大概在 us 級別,會(huì )影響延遲敏感性應用的性能并且對系統造成資源壓力。
因此,在去年 Accelio 提交了基于開(kāi)源的一個(gè) RPC 庫的高性能的 Ceph 網(wǎng)絡(luò )層實(shí)現,另外,作者也在上個(gè)月完成了一個(gè)基于事件通知的異步 Messenger 實(shí)現,主要將之前同步的 SimpleMessenger 改造成狀態(tài)機并且實(shí)現了一個(gè)簡(jiǎn)單的事件管理器。相對于 accelio 的實(shí)現,本人的實(shí)現希望避免引入一個(gè)巨大的 RPC 庫造成諸多不便,會(huì )大大限制 Ceph 在網(wǎng)絡(luò )層實(shí)現上的范圍,也可能會(huì )引來(lái)第三方庫使用的問(wèn)題。而實(shí)際上 Ceph 只需要一個(gè)簡(jiǎn)單的事件管理器即可高效的達到目的。