Dispatcher

dispatcher 是消息分发中心,所有收到的消息都经由该模块,并由该模块转发给相应的处理模块(moncliet、mdsclient、osd等)。

其实现方式比较简单,就是把所有的模块及其处理消息的方法 handle 注册到分发中心,具体函数为 add_dispatcher_head/tail(),这样就向 dispatcher_queue 中添加了指定模块。后续在分发消息时,对 dispatcher_queue 进行轮询,直到有一个处理模块能够处理该消息,通过 message->get_type() 来指定消息的处理函数。所有的消息分发都在 dispatcher 线程中完成。

在 add_dispatcher_head() 和 add_dispatcher_tail() 函数中,都做了 dispatcher 队列是否为空的判断(通过 dispatchers.empty() == true)。如果判定结果为空,说明需要重新创建 dispatcher 线程并绑定服务端地址,加入事件中心监听端口,具体方法在 ready() 中。

  void add_dispatcher_head(Dispatcher *d) {
bool first = dispatchers.empty();
dispatchers.push_front(d);
if (d->ms_can_fast_dispatch_any())
fast_dispatchers.push_front(d);
if (first)
ready();
}

 

 add_dispatche_* 中调用了 AsyncMessenger::ready() 方法。下面给出AsyncMessenger::ready()方法代码:

p->start()(Processor::start())方法中监听 EVENT_READABLE 事件,并把事件提交到 EventCenter 事件中心,由上文介绍的 msgr-worker-x 线程去轮询事件中心的队列,监听端口是否收到消息。收到的消息则由 dispatcher 线程分发给指定的处理程序,其分发消息的接口为 ms_dispatch() 和 ms_fast_dispatch()。

dispatch_queue.start() 中开启了消息分发线程,分别为处理外部消息的 ms_dispatch 线程和处理本地消息的 ms_local 线程。相应的,它们有各自的优先级队列(注意:分发消息的队列时有优先级的,优先级越高,发送时机越早),分别是存储外部消息的 mqueue 和本地消息队列的 local_messages。消息队列的添加方式也有两种:mqueue.enqueue() 和 local_queue.emplace()。

void AsyncMessenger::ready()
{
ldout(cct,10) << __func__ << " " << get_myaddrs() << dendl;

stack->ready();
//绑定端口
if (pending_bind) {
int err = bindv(pending_bind_addrs);
if (err) {
lderr(cct) << __func__ << " postponed bind failed" << dendl;
ceph_abort();
}
}

Mutex::Locker l(lock);
//调用 worker 线程,监听端口
for (auto &&p : processors)
p->start();
//开启 ms_dispatcher 和 ms_locla 线程
dispatch_queue.start();
}

void DispatchQueue::start()
{
ceph_assert(!stop);
ceph_assert(!dispatch_thread.is_started());
//开启 ms_dispatch 和 ms_local 线程
dispatch_thread.create("ms_dispatch");
local_delivery_thread.create("ms_local");
}

链接:https://www.jianshu.com/p/58956728dadc

============================================================

Dipatcher类是消息分发的接口,OSD、MON、等类都继承该类,并实现了Dipatcher的消息分发接口

class OSD : public Dispatcher,public md_config_obs_t
{
/** OSD **/
}

class Monitor : public Dispatcher,public md_config_obs_t
{
public:

// me
string name;
}

在OSD::init()函数中把不同类型的Dipatcher加入到SimpleMessenger实例中

// i'm ready!
client_messenger->add_dispatcher_head(this);
cluster_messenger->add_dispatcher_head(this);
hbclient_messenger->add_dispatcher_head(&heartbeat_dispatcher);
hb_front_server_messenger->add_dispatcher_head(&heartbeat_dispatcher);
hb_back_server_messenger->add_dispatcher_head(&heartbeat_dispatcher);
objecter_messenger->add_dispatcher_head(service.objecter);

在Messenger::add_dispatcher_head(Dispatcher *d)中加入Messenger::list<Dispatcher*> dispatchers中,并调用ready(),SimpleMessenger::ready()重写了基类的ready,

void add_dispatcher_head(Dispatcher *d)
{
bool first = dispatchers.empty();
dispatchers.push_front(d);
if (d->ms_can_fast_dispatch_any())
fast_dispatchers.push_front(d);
if (first)
ready();
}

在ready函数中调用DispatchQueue::start, start()函数启动DispatchQueue::DispatchThread和DispatchQueue::LocalDeliveryThread线程类,最终调用DispatchQueue::entry()和DispatchQueue::run_local_delivery。

void DispatchQueue::start()
{
assert(!stop);
assert(!dispatch_thread.is_started());
dispatch_thread.create("ms_dispatch"); //调用Thread::create->Thread::try_create->Thread::_entry_func->Thread::entry_wrapper->DispatchThread::entry
local_delivery_thread.create("ms_local");
}

class DispatchThread : public Thread
{
DispatchQueue *dq;
public:
explicit DispatchThread(DispatchQueue *dq) : dq(dq) {}
void *entry()
{
dq->entry();
return 0;
}
} dispatch_thread;

在DispatchQueue::entry()中调用根据不同的命令码调用不同的Messenger类中的处理函数

void DispatchQueue::entry()
{
.
.

switch (qitem.get_code())
{
case D_BAD_REMOTE_RESET:
msgr->ms_deliver_handle_remote_reset(qitem.get_connection());
break;
case D_CONNECT:
msgr->ms_deliver_handle_connect(qitem.get_connection());
break;
case D_ACCEPT:
msgr->ms_deliver_handle_accept(qitem.get_connection());
break;
case D_BAD_RESET:
msgr->ms_deliver_handle_reset(qitem.get_connection());
break;
default:
assert(0);
}
}
else
{
Message *m = qitem.get_message();
if (stop)
{
ldout(cct, 10) << " stop flag set, discarding " << m << " " << *m << dendl;
m->put();
}
else
{
uint64_t msize = pre_dispatch(m);
msgr->ms_deliver_dispatch(m);
post_dispatch(m, msize);
}
}
.
.

}

在Messenger::ms_deliver_dispatch中最终调用不同的Dipatcher继承类的ms_dispatch进行处理

void ms_deliver_dispatch(Message *m)
{
m->set_dispatch_stamp(ceph_clock_now(cct));
for (list<Dispatcher *>::iterator p = dispatchers.begin();
p != dispatchers.end();
++p)
{
if ((*p)->ms_dispatch(m)) //在Dispatcher继承类中进行处理
return;
}
lsubdout(cct, ms, 0) << "ms_deliver_dispatch: unhandled message " << m << " " << *m << " from "
<< m->get_source_inst() << dendl;
assert(!cct->_conf->ms_die_on_unhandled_msg);
m->put();
}

 

创建 osd_dispatcher/mon_dispatcher ==>add_dispatcher_

                                                                 ==>ready()

                                                                       ==>start()

                                                                             ==>DispatchThread

                                                                                   ==>entry()

                                                                             ==>LocalDeliveryThread

                                                                                   ==>run_local_delivery()

 

ms_fast_dispatch和ms_dispatch的区别

d) 调用函数read_message()来接收消息,当本函数返回后,就完成了接收消息

2) 调用函数in_q->fast_preprocess(m)预处理消息

3) 调用函数in_q->can_fast_dispatch(m),如果可以进行fast_dispatch,就in_q->fast_dispatch(m)处理。fast_dispatch并不把消息加入到mqueue里,而是直接调用msgr->ms_fast_dispatch()函数,并最终调用注册的fast_dispatcher来进行处理。

4) 如果不能fast_dispatch,就调用函数in_q->enqueue(m, m->get_priority(), conn_id)把接收到的消息加入到DispatchQueue的mqueue队列里,由DispatchQueue的分发线程调用ms_dispatch处理。

ms_fast_dispatch和ms_dispatch两种处理的区别在于:ms_dispatch是由DispatchQueue的线程处理的,它是一个单线程;ms_fast_dispatch函数是由Pipe接收线程直接调用处理的,因此性能比前者好。

https://ivanzz1001.github.io/records/post/ceph/2019/01/05/ceph-src-code-part3_1

​https://blog.51cto.com/wendashuai/2497104​