天天看點

《Ceph源碼分析》——第3章,第1節Ceph網絡通信架構

本節書摘來自華章出版社《ceph源碼分析》一書中的第3章,第3.1節ceph網絡通信架構,作者常濤,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

第3章

ceph網絡通信

本章介紹ceph網絡通信子產品,這是用戶端和伺服器通信的底層子產品,用來在用戶端和伺服器之間接收和發送請求。其實作功能比較清晰,是一個相對較獨立的子產品,了解起來比較容易,是以首先介紹它。

3.1 ceph網絡通信架構

一個分布式存儲系統需要一個穩定的底層網絡通信子產品,用于各節點之間的互聯互通。對于一個網絡通信系統,要求如下:

高性能。性能評價的兩個名額:帶寬和延遲。

穩定可靠。資料不丢包,在網絡中斷時,實作重連等異常處理。

網絡通信子產品的實作在源代碼src/msg的目錄下,其首先定義了一個網絡通信的架構,三個子目錄裡分别對應:simple、async、 xio 三種不同的實作方式。

simple是比較簡單,目前比較穩定的實作,系統預設的用于生産環境的方式。 它最大的特點是:每一個網絡連結,都會建立兩個的線程,一個專門用于接收,一個專門用于發送。這種模式實作比較簡單,但是對于大規模的叢集部署,大量的連結會産生大量的線程,會消耗cpu資源,影響性能。

async模式使用了基于事件的i/o多路複用模式。這是目前網絡通信中廣泛采用的方式,但是在ceph中,官方宣稱這種方式還處于試驗階段,不夠穩定,還不能用于生産環境。

xio方式使用了開源的網絡通信庫accelio來實作。這種方式需要依賴第三方的庫accelio穩定性,需要對accelio的使用方式以及代碼實作都比較熟悉。目前也處于試驗階段。特别注意的是,前兩種方式隻支援tcp/ip協定,xio可以支援infiniband網絡。

在msg目錄下定義了網絡通信的抽象架構,它完成了通信接口和具體實作的分離。在其下分别有msg/simple子目錄、msg/async子目錄、msg/xio子目錄,分别對應三種不同的實作。

3.1.1 message

類message 是所有消息的基類,任何要發送的消息,都要繼承該類,格式如圖3-1所示。

`

《Ceph源碼分析》——第3章,第1節Ceph網絡通信架構

圖3-1 消息發送格式

消息的結構如下:header是消息頭,類似一個消息的信封(envelope),user_data是用于要發送的實際資料,footer是一個消息的結束标記,如下所示:

下面分别介紹其中的重要參數。

ceph_msg_header為消息頭,它定義了消息傳輸相關的中繼資料:

struct ceph_msg_header {

__le64 seq; //目前session内消息的唯一序号

__le64 tid; //消息的全局唯一的id

__le16 type; //消息類型

__le16 priority; //優先級

__le16 version; //消息編碼的版本

__le32 front_len; // payload的長度

__le32 middle_len; // middle的長度

__le32 data_len; // data的長度

__le16 data_off; //對象的資料偏移量

struct ceph_entity_name src;//消息源

//一些舊的代碼,用于相容,如果為零就忽略

__le16 compat_version;

__le16 reserved;

__le32 crc; //消息頭的crc32c校驗資訊

} attribute ((packed));

ceph_msg_footer為消息的尾部,附加了一些crc校驗資料和消息結束标志:

struct ceph_msg_footer {

__le32 front_crc, middle_crc, data_crc;

__le64 sig; //消息的64位signature

__u8 flags; //結束标志

消息帶的資料分别儲存在payload、middle、data這三個bufferlist中。payload一般儲存ceph操作相關的中繼資料,middle目前沒有使用到,data一般為讀寫的資料。

在源代碼src/messages下定義了系統需要的相關消息,其都是message類的子類。

3.1.2 connection

類connection對應端(port)對端的socket連結的封裝。其最重要的接口是可以發送消息:

3.1.3 dispatcher

類dispatcher是消息分發的接口,其分發消息的接口為:

`virtual bool ms_dispatch(message *m) = 0;

virtual void ms_fast_dispatch(message *m);`

server端注冊該dispatcher類用于把接收到的message請求分發給具體處理的應用層。client端需要實作一個dispatcher函數,用于處理收到的ack應對消息。

3.1.4 messenger

messenger是整個網絡抽象子產品,定義了網絡子產品的基本api接口。網絡子產品對外提供的基本功能,就是能在節點之間發送和接受消息。

向一個節點發送消息的指令如下:

<code>virtual int send_message(message *m, const entity_inst_t&amp; dest) = 0;</code>

注冊一個dispatcher用來分發消息的指令如下:

<code>void add_dispatcher_head(dispatcher *d)</code>

3.1.5 網絡連接配接的政策

policy定義了messenger處理connection的一些政策:

3.1.6 網絡子產品的使用

通過下面最基本的伺服器和用戶端的執行個體程式,了解如何調用網絡通信子產品提供的接口來完成收發請求消息的功能。

server程式分析

server程式源代碼在test/simple_server.cc裡,這裡隻展示有關網絡部分的核心流程。

1)調用messenger的函數create 建立一個messenger的執行個體,配置選項g_conf-&gt;ms_type為配置的實作類型,目前有三種方式:

client程式分析

源代碼在test/simple_client.cc裡,這裡隻展示有關網絡部分的核心流程。

1)調用messenger的函數create建立一個messenger的執行個體:

2)設定相關的政策:

`messenger-&gt;set_magic(msg_magic_trace_ctr);

messenger-&gt;set_default_policy(messenger::policy::lossy_client(0, 0));`

3)建立dispatcher類并添加,用于接收消息:

`dispatcher = new simpledispatcher(messenger);

messenger-&gt;add_dispatcher_head(dispatcher);

dispatcher-&gt;set_active(); `

4)啟動消息:

`r = messenger-&gt;start();

if (r &lt; 0)

5)下面開始發送請求,先擷取目标server的連結:

<code>conn = messenger-&gt;get_connection(dest_server);</code>

6)通過connection來發送請求消息。這裡的消息發送方式都是異步發送,接收到請求消息的ack應答消息後,将在dispatcher的 ms_dispatch或者ms_fast_dispatch處理函數裡做相關的處理:

`message *m;

for (msg_ix = 0; msg_ix &lt; n_msgs; ++msg_ix) {

//如果需要,這裡要添加實際的資料

if (! n_dsize) {

} else {

}

conn-&gt;send_message(m);

}`

綜上所述,通過ceph的網絡架構發送消息比較簡單。在server端,隻需要建立一個messenger執行個體,設定相應的政策并綁定服務端口,然後就設定一個dispatcher來處理接收到的請求。在client端,隻需要建立一個messenger執行個體,設定相關的政策和dispatcher用于處理傳回的應答消息。通過擷取對應server的connection來發送消息即可。