共计 2529 个字符,预计需要花费 7 分钟才能阅读完成。
由于 Ceph 的历史很久,网络没有采用现在常用的事件驱动(epoll)的模型,而是采用了与 MySQL 类似的多线程模型,每个连接 (socket) 有一个读线程,不断从 socket 读取,一个写线程,负责将数据写到 socket。多线程实现简单,但并发性能就不敢恭维了。
Messenger 是网络模块的核心数据结构,负责接收 / 发送消息。OSD 主要有两个 Messenger:ms_public 处于与客户端的消息,ms_cluster 处理与其它 OSD 的消息。
数据结构
网络模块的核心是 SimpleMessager:
(1)它包含一个 Accepter 对象,它会创建一个单独的线程,用于接收新的连接(Pipe)。
void *Accepter::entry() | |
{ | |
... | |
int sd = ::accept(listen_sd, (sockaddr*)&addr.ss_addr(), &slen); | |
if (sd >= 0) { | |
errors = 0; | |
ldout(msgr->cct,10) << "accepted incoming on sd" << sd << dendl; | |
msgr->add_accept_pipe(sd); | |
... | |
// 创建新的 Pipe | |
Pipe *SimpleMessenger::add_accept_pipe(int sd) | |
{lock.Lock(); | |
Pipe *p = new Pipe(this, Pipe::STATE_ACCEPTING, NULL); | |
p->sd = sd; | |
p->pipe_lock.Lock(); | |
p->start_reader(); | |
p->pipe_lock.Unlock(); | |
pipes.insert(p); | |
accepting_pipes.insert(p); | |
lock.Unlock(); | |
return p; | |
} |
(2)包含所有的连接对象(Pipe),每个连接 Pipe 有一个读线程 / 写线程。读线程负责从 socket 读取数据,然后放消息放到 DispatchQueue 分发队列。写线程负责从发送队列取出 Message,然后写到 socket。
class Pipe : public RefCountedObject { | |
/** | |
* The Reader thread handles all reads off the socket -- not just | |
* Messages, but also acks and other protocol bits (excepting startup, | |
* when the Writer does a couple of reads). | |
* All the work is implemented in Pipe itself, of course. | |
*/ | |
class Reader : public Thread { | |
Pipe *pipe; | |
public: | |
Reader(Pipe *p) : pipe(p) {} | |
void *entry() { pipe->reader(); return 0; } | |
} reader_thread; /// 读线程 | |
friend class Reader; | |
/** | |
* The Writer thread handles all writes to the socket (after startup). | |
* All the work is implemented in Pipe itself, of course. | |
*/ | |
class Writer : public Thread { | |
Pipe *pipe; | |
public: | |
Writer(Pipe *p) : pipe(p) {} | |
void *entry() { pipe->writer(); return 0; } | |
} writer_thread; /// 写线程 | |
friend class Writer; | |
... | |
/// 发送队列 | |
map<int, list<Message*> > out_q; // priority queue for outbound msgs | |
DispatchQueue *in_q; /// 接收队列 |
(3)包含一个分发队列 DispatchQueue,分发队列有一个专门的分发线程(DispatchThread),将消息分发给 Dispatcher(OSD)完成具体逻辑处理。
消息的接收
接收流程如下:Pipe 的读线程从 socket 读取 Message,然后放入接收队列,再由分发线程取出 Message 交给 Dispatcher 处理。
消息的发送
发送流程如下:
其它资料
这篇文章解析 Ceph: 网络层的处理简单介绍了一下 Ceph 的网络,但对 Pipe 与 Connection 的关系描述似乎不太准确,Pipe 是对 socket 的封装,Connection 更加上层、抽象。
在 CentOS 7.1 上安装分布式存储系统 Ceph http://www.linuxidc.com/Linux/2015-08/120990.htm
Ceph 环境配置文档 PDF http://www.linuxidc.com/Linux/2013-05/85212.htm
CentOS 6.3 上部署 Ceph http://www.linuxidc.com/Linux/2013-05/85213.htm
Ceph 的安装过程 http://www.linuxidc.com/Linux/2013-05/85210.htm
HOWTO Install Ceph On FC12, FC 上安装 Ceph 分布式文件系统 http://www.linuxidc.com/Linux/2013-05/85209.htm
Ceph 文件系统安装 http://www.linuxidc.com/Linux/2013-05/85208.htm
CentOS 6.2 64 位上安装 Ceph 0.47.2 http://www.linuxidc.com/Linux/2013-05/85206.htm
Ubuntu 12.04 Ceph 分布式文件系统 http://www.linuxidc.com/Linux/2013-04/82588.htm
Fedora 14 上安装 Ceph 0.24 http://www.linuxidc.com/Linux/2011-01/31580.htm
Ceph 的详细介绍:请点这里
Ceph 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-10/124549.htm
