Ceph AsyncMessenger 简析 II

在IO栈的优化中,同步改异步是很常用的一种方法,往往可以提高系统的吞吐率,Ceph Messenger就是利用Linux的阻塞异步IO机制,以及自身设计的队列结构来实现对Event的异步处理,进而获取了比Simple Messenger优越很多的性能。Ceph的异步机制根据EventCenter::EventDriver的不同实例可以使用几种模型,本文讨论的是基于epoll机制的Ceph Async + RDMAStack下的IO路径
Ceph Async机制的核心即是EventCenter,下图简述了EventCenter对这一机制的实现


在Async机制中,Ceph Msg模块将所有的异步事件分为两类:

  1. handler固定、”定点”执行的file_event,通常用于频繁执行的routine,
  2. handler形式多样但”顺便”执行的external_event

file events

file events的核心结构是EventCenter::vectorfile_events,该vector以fd为索引封装了一组FileEvents实例,每个FileEvents实例都包含两个handler:readcb用于处理fd可读,writecb用于fd可写。系统通过create_file_event()将fd及其handler注册到file_events。最终,所有的file_events注册的fd都会通过epoll_ctl()将其注册到内核,并通过在Worker中调用epoll_wait()来实现异步阻塞IO

external events

相比于file_events与特定的fd绑定,external events要自由的多,external_events就是一个EventCallback的deque,使用方式与fd无关, 所以只要EventCallback及其子类的实例,都可以在需要的时候注册到其中以此让Worker线程执行之。值得注意的是,在Ceph的设计中,file event和external event并不是割裂的,事实上,external event依赖于在file_events中设置代理才能工作,通过将管道的读端注册为file event,dispatch_event_external()首先会将相应的EventCallback实例入队,再向管道的写端notify_send_fd写入一个字符,如此一来管道的读端notify_receive_fd就会变的可读,进而通过的epoll机制wakeup相应的Worker工作线程,Worker工作线程首先会回调发生事件的notify_receive_fd的readcb,该cb只是将在写端写入的字符读出,之后,Worker就会将external event全部回调一遍,即将其从队列清空。

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: