MSG模块源码分析—NetworkStack
MSG模块源码分析—NetworkStack
以mon为例,在ceph_mon.cc的main函数中:
// bind
int rank = monmap.get_rank(g_conf()->name.get_id());
std::string public_msgr_type = g_conf()->ms_public_type.empty() ? g_conf().get_val<std::string>("ms_type")
: g_conf()->ms_public_type;
Messenger *msgr = Messenger::create(g_ceph_context, public_msgr_type,
entity_name_t::MON(rank), "mon", 0);
首先,从配置文件中获取ms_type,该字段用于指定传输类型,这里默认是async+posix
。
Messenger *Messenger::create(CephContext *cct, const std::string &type,
entity_name_t name, std::string lname,
uint64_t nonce) {
if (type == "random" || type.find("async") != std::string::npos)
return new AsyncMessenger(cct, name, type, std::move(lname), nonce);
return nullptr;
}
进而创建了一个AsyncMessenger
,其构造函数如下:
AsyncMessenger::AsyncMessenger(CephContext *cct, entity_name_t name,
const std::string &type, std::string mname,
uint64_t _nonce)
: SimplePolicyMessenger(cct, name),
dispatch_queue(cct, this, mname),
nonce(_nonce) {
std::string transport_type = "posix";
if (type.find("rdma") != std::string::npos)
transport_type = "rdma";
else if (type.find("dpdk") != std::string::npos)
transport_type = "dpdk";
auto single = &cct->lookup_or_create_singleton_object<StackSingleton>(
"AsyncMessenger::NetworkStack::" + transport_type, true, cct);
single->ready(transport_type);
stack = single->stack.get();
stack->start();
...
}
在这里,我们的
transport_type
为posix
。
第13行,会创建一个StackSingleton
对象,他就是我们分析的开端。首先看一下与之相关的类图。
简单的介绍一些每一个类的作用:
类名 | 作用 |
---|---|
ceph::NetHandler |
封装了一些对socket的基本操作(创建、连接、非阻塞、option等) |
EventDriver |
提供了一些IO多路复用的抽象接口,我们这个具体的实现是EpollDriver |
EventCenter |
基于EventDriver 实现了事件处理,支持FileEvent 和TimeEvent |
Worker |
每一个Worker 都会对应一个EventCenter ,其本质上就是一个线程,不断的处理EventCenter 中的事件 |
NetworkStack |
管理多个Worker ,我是将其理解为一个处理网络连接的线程池,具体的实现是PosixNetworkStack |
线程池(PosixNetworkStack)创建
AsyncMessenger
会创建一个SingleNetworkStack
对象,然后调用其ready
方法,实现如下:
struct StackSingleton {
CephContext *cct;
std::shared_ptr<NetworkStack> stack;
explicit StackSingleton(CephContext *c) : cct(c) {}
void ready(std::string &type) {
if (!stack) stack = NetworkStack::create(cct, type);
}
~StackSingleton() { stack->stop(); }
};
这里进入到NetworkStack
的静态方法create
中:
std::shared_ptr<NetworkStack> NetworkStack::create(CephContext* c,
const std::string& t) {
std::shared_ptr<NetworkStack> stack = nullptr;
//创建PosixNetworkStack
if (t == "posix") stack.reset(new PosixNetworkStack(c));
...
//设置异步线程数,默认是3个([1, 24])
unsigned num_workers = c->_conf->ms_async_op_threads;
const int InitEventNumber = 5000;
for (unsigned worker_id = 0; worker_id < num_workers; ++worker_id) {
Worker* w = stack->create_worker(c, worker_id);
int ret = w->center.init(InitEventNumber, worker_id, t);
...
stack->workers.push_back(w);
}
return stack;
}
- 创建完成
PosixNetworkStack
后,会根据配置文件中的ms_async_op_threads来配置Worker的数量。 PosixNetworkStack->create_worker
返回一个PosixWorker
对象。- 初始化
PosixWorker
的EventCenter
。这里面会创建一个EpollDriver
。InitEventNumber
指定了EventCenter
内部事件缓存池的初始大小,以及EpoolDriver
每次epoll_wait
的最大事件数(第三个参数)。 - 所有的worker都会保存在
staock->workers
中。
线程池(PosixNetworkStack)启动
对应 NetworkStack::start()
:
void NetworkStack::start() {
std::unique_lock<decltype(pool_spin)> lk(pool_spin);
if (started) {
return;
}
for (Worker* worker : workers) {
if (worker->is_init()) continue;
spawn_worker(add_thread(worker));
}
started = true;
lk.unlock();
for (Worker* worker : workers) {
worker->wait_for_init();
}
}
class PosixNetworkStack : public NetworkStack {
std::vector<std::thread> threads;
virtual Worker* create_worker(CephContext *c, unsigned worker_id) override {
return new PosixWorker(c, worker_id);
}
public:
explicit PosixNetworkStack(CephContext *c);
void spawn_worker(std::function<void ()> &&func) override {
threads.emplace_back(std::move(func));
}
void join_worker(unsigned i) override {
ceph_assert(threads.size() > i && threads[i].joinable());
threads[i].join();
}
};
这里,逐个通过spawn_worker
函数启动Worker
线程(工作线程的主要工作就是add_thread
返回的std::function
)。
Worker线程的主循环
std::function<void()> NetworkStack::add_thread(Worker* w) {
return [this, w]() {
rename_thread(w->id);
const unsigned EventMaxWaitUs = 30000000; ?/30s
w->center.set_owner();
ldout(cct, 10) << __func__ << " starting" << dendl;
w->initialize(); //空实现
w->init_done(); //stack->start() 最后的 worker->wait_for_init()对应
while (!w->done) { //什么时候会退出?
ceph::timespan dur; //记录process_events的执行时间
int r = w->center.process_events(EventMaxWaitUs, &dur);
if (r < 0) {
ldout(cct, 20) << __func__
<< " process events failed: " << cpp_strerror(errno)
<< dendl;
// TODO do something?
}
w->perf_logger->tinc(l_msgr_running_total_time, dur);
}
w->reset();
w->destroy();
};
}
over!
非阻塞IO+事件驱动的实现基本类似,不同的就是 封装方式吧。 所以 Stack往下就不继续贴代码了。