1 Socket簡介
Ceph的網絡通信是基于Socket技術實作的,是以要想搞清楚網絡部分,必須先清楚socket的工作機制,這裡介紹一些基本的内容,要深入了解socket請參閱《linux網絡程式設計》一書和《tcp/ip詳解》。
socket起源于Unix,而Unix/Linux基本哲學之一就是“一切皆檔案”,都可以用“打開open -> 讀寫write/read -> 關閉close”模式來操作。Socket也是按照這個思想實作的,而我們工作中主要會用到它的以下接口:
-
int socket(int domain, int type, int protocol);
這個函數建立一個socket描述符,唯一辨別一個socket,對應于普通檔案的打開接口。
-
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
該函數把一個具體的位址綁定到相應的socket描述符上。通常伺服器在啟動的時候都會綁定一個衆所周知的位址(如ip位址+端口号),用于提供服務,客戶就可以通過它來接連伺服器;而用戶端就不用指定,有系統自動配置設定一個端口号和自身的ip位址組合。
-
int listen(int sockfd, int backlog);
如果作為一個伺服器,在調用socket()、bind()之後就會調用listen()來監聽這個socket。socket()函數建立的socket預設是一個主動類型的,listen函數将socket變為被動類型的,等待客戶的連接配接請求。
-
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
用戶端這時調用connect()發出連接配接請求,伺服器端就會接收到這個請求。
-
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
TCP伺服器監聽到這個請求之後,就會調用accept()函數取接收請求,這樣連接配接就建立好了。之後就可以開始網絡I/O操作了,即類同于普通檔案的讀寫I/O操作。
以上這些接口,就可以用于實作用戶端和伺服器端的socket連接配接的建立了。之後就可以通過::send()和::recv()接口從socket中讀取資料了。
2 Ceph中的相關實作
在Ceph中,網絡部分主要是在msg目錄中,包括Messenger、Accepter、Pipe和Connection這幾個實體,當然其還要和具體的dispatcher結合起來。單說socket部分,Ceph将其分拆成了兩個部分,socket連接配接的維護(建立、綁定、監聽、删除)主要實作在了Accepter 這個檔案中了以及I/O部分主要實作在了Pipe中。也就是說可以用一個公式表示就是:
- Accepter + Pipe = socket
而Messenger它是Ceph網絡傳輸的抽象體,包括Accepter、Pipe、Dispatch_queue。
Ceph通過OSDSession這個類來維護管理client端和server端之間建立的Session連接配接,并且維護了Pending在Session中的所有Op。OSDSession暴露出來的接口就是一個ConnectionRef結構的send_message(),而在這個函數裡,它實際上又傳回過來找到messenger、pipe然後将請求發送出去。
主要的使用流程是:
|