收发代码流分析:https://blog.51cto.com/wendashuai/2497104
原文:https://blog.csdn.net/zhq5515/article/details/49814941
UML
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/51bbe6bb78deee4e523fb88b4fbf4791.jpeg)
架构上采用 Publish/subscribe(发布/订阅) 的设计模式.
模块说明:
Messenger
该类作为消息的发布者, 各个 Dispatcher 子类作为消息的订阅者, Messenger 收到消息之后,通过 Pipe 读取消息,然后转给 Dispatcher 处理
SimpleMessenger
Messenger 接口的实现
Dispatcher
该类是订阅者的基类,具体的订阅后端继承该类,初始化的时候通过 Messenger::add_dispatcher_tail/head 注册到 Messenger::dispatchers. 收到消息后,通知改类处理
Accepter
监听 peer 的请求, 有新请求时, 调用 SimpleMessenger::add_accept_pipe() 创建新的 Pipe 到 SimpleMessenger::pipes 来处理该请求
Pipe
用于消息的读取和发送,该类主要有两个组件,Pipe::Reader 和 Pipe::Writer, 分别用来处理 消息的读取和发送. 这两个类都是 class Thread 的子类,意味这每次处理消息都会有两个 线程被分别创建.
消息被 Pipe::Reader 读取后,该线程会通知注册到 Messenger::dispatchers 中的某一个 Dispatcher(如 Monitor) 处理, 处理完成之后将回复的消息放到 SimpleMessenger::Pipe::out_q 中,供 Pipe::Writer 来处理发送
DispatchQueue
该类用来缓存收到的消息, 然后唤醒 DispatchQueue::dispatch_thread 线程找到后端的 Dispatch 处理消息
详细解析:
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/3ffccf2b797afcbedbee2f8e1767c58f.jpeg)
下面的代码涉及到的订阅子类以 Monitor 为例:
初始化
int main(int argc, char *argv[])
{
// 创建一个 Messenger 对象,由于 Messenger 是抽象类,不能直接实例化,提供了一个
// ::create 的方法来创建子类,目前 Ceph 所有模块使用 SimpleMessenger
Messenger *messenger = Messenger::create(g_ceph_context,
entity_name_t::MON(rank),
"mon",
0);
/**
* 执行 socket() -> bind() -> listen() 等一系列动作, 执行流程如下:
SimpleMessenger::bind()
--> Accepter::bind()
socket() -> bind() -> listen()
*/
err = messenger->bind(ipaddr);
// 创建一个 Dispatch 的子类对象, 这里是 Monitor
mon = new Monitor(g_ceph_context, g_conf->name.get_id(), store,
messenger, &monmap);
// 启动 Reaper 线程
messenger->start();
/**
* a). 初始化 Monitor 模块
* b). 通过 SimpleMessenger::add_dispatcher_tail() 注册自己到
* SimpleMessenger::dispatchers 中, 流程如下:
* Messenger::add_dispatcher_tail()
* --> ready()
* --> dispatch_queue.start()(新 DispatchQueue 线程)