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然后将请求发送出去。
主要的使用流程是:
1)通过Messenger::create_client_messenger()或者Messenger::create()创建一个messenger,目前支持SimpleMessenger、AsyncMessenger、Xio这三种,可以在ceph的配置文件中配置。 2)创建一个dispatcher,如果是客户端一般就是创建一个Objecter和Monc,如果是服务端就创建对应的角色实例如OSD、Mon等,并且上一步创建的messenger会被设置为他们的messenger。 3)设置Messenger的policy,用于配置socket连接的异常处理策略。 4)Dispatcher的初始化,如objecter->init(); 5)如果是服务器端(比如OSD),则需要调用messenger的bind()接口,为messenger绑定一个地址和端口,如果是客户端(比如Objecter)则不需要。这个bind操作是通过Accepter的bind()接口完成的,它里面实际上干了三件事情:创建socket、bind地址和端口、listen地址和端口; 6)通过Messenger的add_dispatcher_head()/add_dispatcher_tail()将初始化后的dispatcher加入的messenger的dispatcher list中。如果是添加的第一个dispatcher,则会调用Messenger的ready()接口,这个接口会调用Accepter的start()接口。而在客户端和服务端,他们对于start()的处理是不一样的。服务器端会创建一个线程使用poll机制去处理accept的连接,客户端则不会处理。服务器accept的socket连接会创建相应的Pipe,丢到messenger里面。 7)当pipe建立好之后,客户端就会通过OSDSession中的conn找到messenger的接口,发送数据了。 |
本文介绍了Ceph网络通信的基础,涉及Socket原理及其在Ceph中的应用。Ceph的网络模块由Messenger、Accepter、Pipe和Connection组成,其中Accepter负责连接的维护,Pipe处理I/O操作。Ceph的OSDSession管理client-server Session,通过ConnectionRef的send_message()发送请求。
848

被折叠的 条评论
为什么被折叠?



