Chinaunix首页 | 论坛 | 博客
  • 博客访问: 221500
  • 博文数量: 39
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 218
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-06 12:33
文章分类
文章存档

2017年(2)

2015年(11)

2014年(18)

2013年(8)

我的朋友

分类: 云计算

2017-03-24 13:46:25

在博文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); 
		
  • 1
  • 1

Messenger收到消息转给dipatcher

 void ms_deliver_dispatch(Message *m) {
     m->set_dispatch_stamp(ceph_clock_now()); for (list::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();
   }
		
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ceph monitor处理消息

 bool ms_dispatch(Message *m) override { lock.Lock();
    _ms_dispatch(m); lock.Unlock(); return true;
  }
		
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
阅读(2745) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~