Ceph源码分析之Async模块:2、上层通信模型

在博文Ceph源码分析之Async模块:1、异步通信核心模块EventCenter+Epoll 里面介绍了Async实现异步通信的底层核心模块。这次打算从上层应用来看ceph的通信模型模型。

ceph通信模块的源代码定义在msg目录下,消息类型定义在message目录下面。

概述

ceph各个组件直接的通信以及和客户端直接的通信都依赖与ceph的通信模块,捋清楚通信模块对阅读源代码会有帮助。
先看一张简单的交互图
这里写图片描述

ceph通信模块的角色主要分为Messenger和Dispatcher两大角色

  • Messenger

    消息管理器,对上负责将消息转给Dispatcher和提供发送消息的接口:send_message,对下负责将应用发送的消息转发给Connection(封装的socket连接实例)

  • Dispatcher

    消息分法器,根据消息类型将消息分发给应用层的具体操作接口

其它涉及到的两个重要的角色

  • Message

    消息格式基类,可以根据需求派生出不同类型的消息,不同的消息类型定义在message目录下面,最大的不同就是msg_type(消息类型)

  • Connection

    连接实例,负责维护同客户端建立的socket连接以及ceph的协议栈操作接口(在Async中间层协议栈的时候会深入介绍),向上提供发送消息接口及转发底层消息给DispathcQueue或者消息管理器,向下发送和介绍消息。

模块设计

使用ceph通信模块来收发消息
* 发送消息

发消息比较简单,应用只需将消息内容按照需要的消息类型(定义在messaging/*或自定义)进行封装后调用Messenger的send_message即可。


  • 接收消息

Messenger是如何将消息转给应用的或者说是如何管理?Messenger设计了两个分发器管理成员:dispatchers和fast_dispatchers,用来处理不同类型的请求处理。应用层则按需求将不同的分发器注册给Messenger,进而Messenger接收到底层来的消息时,会将消息分发给已经注册的两个dispatchers。
设计fast_dispatchers的目的就是为了让有些消息能够省去底层的一层流程(比如跳过入队列),直接到达应用。Dispatcher类是一个基类,里面设计封装了应用同Messenger交互的接口(每个具体的Dispatcher派生类自行去实现更具体的消息处理,一般都是再根据消息类型来分开处理消息)。Dispatcher并不是所有的接口封装都是为了转发消息,它更深层次的含义是提供一个应用层和底层的通信接口,而这个接口的桥梁是Messenger消息管理器。
当底层有消息到来时,Messenger会将消息转给dispatcher对于的ms_*系列的接口,最常用的是ms_dispatch接口,因此你可以看到像monitor,osd这些应用的核心消息处理都在ms_dispatch接口里面实现。

Dispatcher的使用
  • 最简单的方式就是应用本身作为Dispatcher的派生类,如此,Messenger便是直接通过应用关联,比如Monitor、osd、mgr都是应用组件本身作为Dispatcher的派生类。

  • 申请一个Dispatcher的派生类实例,做为应用的模块注册给Messenger,比如RadosClient里面会注册各个Client给Messenger,而这些Client都是Dispatcher的派生类。

消息类型

ceph的消息基类是:Message,Message里面设计了一个type成员,用来区分不同的消息类型,不同的消息模块可以通过type来构造,而这些type定义在Message.h中

技巧:比如你想要看某个消息是谁发的,那么你只需要去查看这个消息类型对应的消息模块有哪些,然后再查到谁在使用这个消息模块来封装消息,进而就可以找到发送这个消息的地方。

例子

以ceph-mon为例子,Monitor类继承自Dispatcher

class Monitor : public Dispatcher,
实现它的ms_dispatcher方法,这个方法里面实现了mon的消息处理
注册给Messenger,add_dispatcher_tail方法就是将当前应用添加到dispatcher列表中

messenger->add_dispatcher_tail(this); 

Messenger收到消息转给dipatcher

  void ms_deliver_dispatch(Message *m) {
     m->set_dispatch_stamp(ceph_clock_now());
     for (list<Dispatcher*>::iterator p = dispatchers.begin();
          p != dispatchers.end();
          ++p) {
       if ((*p)->ms_dispatch(m))
         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();
   }

ceph monitor处理消息

  bool ms_dispatch(Message *m) override {
    lock.Lock();
    _ms_dispatch(m);
    lock.Unlock();
    return true;
  }
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值