【ceph】AsyncMessenger模块源码分析03消息的发送和接收

目录

1、消息模块的生命周期

2、消息模块初始化

 3.消息的发送

4、消息的接收

消息接收的过程

消息接收初始工作流程

消息接收状态转换图


原文:Ceph网络模块(3)——AsyncMessenger代码流程分析_Hequan的专栏-CSDN博客  去给大神点个赞

1、消息模块的生命周期

消息模块的生命周期

如图所示以OSD为例描述了消息模块的生命周期。

本文如果没有特殊说明均指的是OSD守护进程。

在main()函数中首先创建一个Messenger,然后对注册的Messenger进行bind,绑定后start消息模块进行工作,消息模块start后init OSD。

在OSD的初始化中让Messenger处于ready状态,即准备工作状态。当消息模块工作结束后处于wait状态,如果需要的话则删除注册的Messenger。这就是消息模块大致的生命周期,下面详细描述一下每个过程的操作。

不同的角色会启动相应的守护进程,如果OSD,则通过 ceph_osd.cc这个文件来启动守护进程,首先进入的是main()函数;


在main()函数中注册了6个Messenger的实例,如下表所示。

编号    Messenger实例名称    作用
1    *ms_public    用来处理OSD和Client之间的消息
2    *ms_cluster    用来处理OSD和集群之间的消息
3    *ms_hbclient    用来处理OSD和其它OSD保持心跳的消息
4    *ms_hb_back_server    用来处理OSD接收心跳消息
5    *ms_hb_front_server    用来处理OSD发送心跳消息
6    *ms_objecter    用来处理OSD和Objecter之间的消息

Messenger是一个接口类,根据不同的需求对其进行实现,async就是AsyncMessenger。
初始化消息模块后进行绑定。具体执行绑定的是调用AsyncMessenger的bind函数(),调用的参数是配置文件中的g_conf->public_addr和g_conf->cluster_addr等。

AsyncMessenger的bind()函数执行的是Processor::bind()。在Processor的bind函数中真正完成了绑定,Processor的bind函数有两个参数,一个是addr,另一个是port。

在Processor的bind函数中主要进行的操作有:
1) 根据bind_addr得出socket的参数family;
2) 创建socket,family参数根据步骤1)获取;
3) 将socket设置为非阻塞;
4) 绑定需要监听的端口;
5) 获取绑定的socket的name;
6) 监听端口。


开启消息模块。在步骤2中create了Messenger(AsyncMessenger),还需要开启它的服务来工作,AsyncMessnger在start函数中调用WorkPool的start来具体执行AsyncMessenger的开启工作。


启动OSD,在这个之前有一个pre启动(int err = osd->pre_init()),在这个后面还有一个final启动(osd->final_init();)。执行OSD启动的是osd.cc文件中的init函数,调用Messenger的add_dispatcher_head()函数将响应的消息的分拣器实例(dispatchers)加入到dispatchers的链表中。

在add_dispatcher_head()函数中如果是链表中的第一个元素,则执行ready函数。ready函数的具体执行是由AsyncMessenger的ready来实现,通过WorkerPool来获取worker,然后启动事件处理中心来处理事件。启动worker线程,并通知事件处理中心可以开始工作了,主要是事件的create和处理。

这个时候AsyncMessenger的机制已经基本全部启动完成,可以进行正常的工作。

Messenger进入wait状态,等待stop条件变量,一但stop添加变量满足,就完成清理工作,关闭所有的连接。执行完wait操作后,删除之前创建的Messenger。

2、消息模块初始化


消息模块的初始化流程如下图所示。

消息模块初始化

上图表示了消息模块初始化时一些关键函数的调用流程,和代码流程大体上是一致的。

下面以OSD为例来描述消息模块的初始化流程。

Messenger::create()用来创建一个Messenger,如果配置是async模式,则根据配置创建的是一个AsyncMessenger实例。

在main()函数中调用AsyncMessenger::bind()绑定IP地址。

在OSD模块的初始化函数init()中,调用add_dispatcher_head()或者add_dispatcher_tail()函数,执行如下操作:

将OSD创建的所有Dispatcher添加到Messenger中定义的dispatchers队里中;


调用AsyncMessenger::ready()启动AsyncMessenger。


消息模块的初始化主要启动两个模块:

一个是EventerCenter(事件中心),事件中心的启动流程在下面小节中详细描述。

另一个启动的是AsyncMessenger,调用AsyncMessenger::ready()获取一个工

Ceph中,stripe是一种将数据分片存储的概念。当进行文件读取操作时,需要通过一系列的计算来确定数据所在的具体位置。本文以CephFS的文件读取流程为例进行分析。 首先,在文件读取过程中,Ceph会将文件划分为若干个条带(stripe),每个条带由多个对象分片(stripe unit)组成。条带可以看作是逻辑上连续的一维地址空间。 接下来,通过file_to_extent函数将一维坐标转化为三维坐标(objectset,stripeno,stripepos),来确定具体的位置。其中,objectset表示所在的对象集,stripeno表示条带号,stripepos表示条带内的偏移位置。 具体的计算过程如下:假设需要读取的数据的偏移量为offset,每个对象分片的大小为su(stripe unit),每个条带中包含的对象分片数为stripe_count。 首先,计算块号blockno = offset / su,表示数据所在的分片号。 然后,计算条带号stripeno = blockno / stripe_count,表示数据所在的条带号。 接着,计算条带内偏移stripepos = blockno % stripe_count,表示数据在条带内的偏移位置。 接下来,计算对象集号objectsetno = stripeno / stripes_per_object,表示数据所在的对象集号。 最后,计算对象号objectno = objectsetno * stripe_count + stripepos,表示数据所在的对象号。 通过以上计算,可以确定数据在Ceph中的具体位置,从而完成文件读取操作。 需要注意的是,以上分析是基于Ceph版本10.2.2(jewel)进行的,尽管版本跨度较大,但是该部分代码在12.2.10(luminous)版本中仍然比较稳定,基本的框架没有发生变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值