ceph async代码分析

数据结构

封装了socket的基本使用

class NetHandler {

public:

int connect(const entity_addr_t &addr, const entity_addr_t& bind_addr);//连接

int reconnect(const entity_addr_t &addr, int sd);//重连

int set_socket_options(int sd, bool nodelay, int size);//设置属性

};

 

封装了NetHandler的接口,同时一个worker实例会绑定一个处理线程id

class PosixWorker : public Worker {

ceph::NetHandler net;//NetHandler实例

public:

  PosixWorker(CephContext *c, unsigned i)//输入必须要有线程对应数据组的id

  : Worker(c, i), net(c) {}

  int listen(entity_addr_t &sa, const SocketOptions &opt,

                     ServerSocket *socks) override;//封装了服务端监听的一系列接口

  int connect(const entity_addr_t &addr, const SocketOptions &opts, ConnectedSocket *socket) override;//封装了客户端连接的一系列接口

}

 

单例模式,维护统一的worker线程池,以及线程池中线程的处理函数

class NetworkStack : public CephContext::ForkWatcher {

std::string type;//posix,rdma,dpdk

  unsigned num_workers = 0;//线程数

  Spinlock pool_spin;

  bool started = false;//是否已启动

  std::function<void ()> add_thread(unsigned i);//具体线程的处理函数

public:

  static Worker* create_worker(

          CephContext *c, const string &t, unsigned i);//创建worker实例

  void start();//启动线程池

  void stop();//停止线程池

  virtual Worker *get_worker();

  Worker *get_worker(unsigned i) {

    return workers[i];

  }

 

EventDriver是一个抽象的接口,定义了添加事件监听,删除事件监听,获取触发的事件的接口,我们主要使用EpollDriver

class EventDriver {

public:

  virtual ~EventDriver() {}       // we want a virtual destructor!!!

  virtual int init(EventCenter *center, int nevent) = 0;//对应初始化epoll_create

  virtual int add_event(int fd, int cur_mask, int mask) = 0;// epoll_ctl

  virtual int del_event(int fd, int cur_mask, int del_mask) = 0;// epoll_ctl

  virtual int event_wait(vector<FiredFileEvent> &fired_events, struct timeval *tp) = 0;// epoll_wait

  virtual int resize_events(int newsize) = 0;

  virtual bool need_wakeup() { return true; }

}

 

保存所有事件以及相关事件的处理

class EventCenter {

public:

  static const int MAX_EVENTCENTER = 24;//线程的最大上线

private:

  struct FileEvent {//socket对应的事件

    int mask;//读写等标识

    EventCallbackRef read_cb;

    EventCallbackRef write_cb;

    FileEvent(): mask(0), read_cb(NULL), write_cb(NULL) {}

  };

  struct TimeEvent {//暂时还没弄清楚干嘛的,主流程不太需要

    uint64_t id;

    EventCallbackRef time_cb;

    TimeEvent(): id(0), time_cb(NULL) {}

  };

  private:

  CephContext *cct;

  std::string type; //dpdk,rdma,posix

  int nevent; //初始化的事件数量

  // Used only to external event

  pthread_t owner; //线程实例

  std::mutex external_lock;

  std::atomic_ulong external_num_events;

  deque<EventCallbackRef> external_events;

  vector<FileEvent> file_events;

  EventDriver *driver;

  std::multimap<clock_type::time_point, TimeEvent> time_events;

  // Keeps track of all of the pollers currently defined.  We don't

  // use an intrusive list here because it isn't reentrant: we need

  // to add/remove elements while the center is traversing the list.

  std::vector<Poller*> pollers;

  std::map<uint64_t, std::multimap<clock_type::time_point, TimeEvent>::iterator> event_map;

  uint64_t time_event_next_id;

  int notify_receive_fd; //用于监听事件的fd

  int notify_send_fd; //用于wakeup的fd

  ceph::NetHandler net;

  EventCallbackRef notify_handler;

  unsigned idx;

  AssociatedCenters *global_centers = nullptr; //单例,用于保存所有的eventcenter

};

 

class AsyncMessenger : public SimplePolicyMessenger {

private:

static const uint64_t ReapDeadConnectionThreshold = 5;//deleted_conns达到的水位则真正删除

NetworkStack *stack;//单例

std::vector<Processor*> processors;//posix场景只有一个

DispatchQueue dispatch_queue;//请求分发队列

Worker *local_worker;// worker线程中的一个,目前只用于asyncmessenger来回收conns

uint64_t nonce;//进程识别码

ceph::unordered_map<entity_addr_t, AsyncConnectionRef> conns;//正在连接的conns

set<AsyncConnectionRef> accepting_conns;//刚刚accept的conns

set<AsyncConnectionRef> deleted_conns;//待删除的conns

};

 

class AsyncConnection : public Connection {

private:

  ConnectedSocket cs;//对应的socket

  map<int, list<pair<bufferlist, Message*> > > out_q;//发送消息队列

  Worker *worker;//工作线程

};

概要分析

主要实例之间的关系

以osd举例

34b1297628957476ad42bc8c61d32b24170.jpg

基于事件投递的线程模型

每个EventCenter中会包含notify_receive_fd和notify_send_fd2个字段。

EventCenter::init中会调用pipe来生成这2个fd

eb966b8ef43ec39413a2746949849509cac.jpg

 

上图为整个线程处理的框架,其中在set_owner会向epoll注册notify_receive_fd的读监听事件以及相关的回调处理。

4421b24d68f663fa3e6295b63bca148a538.jpg

当需要worker线程干活的时候,只需要调用EventCenter::dispatch_event_external函数,worker线程就能够执行传入的回调

ae62b989c1b288b7d9ae9e0684f1f3c3d5e.jpg

下图为worker线程EventCenter::process_events的部分处理流程

3a1c5fb94bc1075df4890a72160e9f7c4b7.jpg

 

主要流程

客户端和服务端正常交互的流程

Client发送请求的异步流程:

f5939496c8ca860183f77f348995763c12a.jpg

AsyncConnection::process负责整个connect的建立以及状态机变化,handle_write负责发送message数据。

整个连接的建立流程

Client和server在建立连接的过程都会最终调到AsyncConnection::process函数,只不过client进入process函数的时候state是STATE_CONNECTING,而server进入process函数的时候状态是STATE_ACCEPTING

Client调用到process的流程上文已经说明,server调用到process的流程如下:

7871fce2985967cbfb365afab0f14ad4335.jpg

5a7ccc284ddbb39a8cbf46e87b17790f920.jpg

由上图可以看到messenger在start的过程中会注册listen的fd到epoll的监听事件中回调为C_processor_accept。后续流程为

4510eca54865d6825cb1123453fbd16b8bf.jpg

  整个连接过程的client和server的状态机变化,以及各个状态的处理逻辑如下图:

2fb1275545dd2043f83532fef183904e455.jpg

发送message的过程

776355c1805685769298e58dbac88688d9b.jpg

  1.  

转载于:https://my.oschina.net/u/2257799/blog/2907036

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值