本文介绍Ceph客户端方面的某些模块的实现。
(摘抄自:https://blog.csdn.net/CSND_PAN/article/details/78707756)
客户端主要是实现了接口,让外部可以调用实现访问操作。上层可以通过调用这些接口来访问Ceph存储。
Ceph的客户端通过一套名为librados的接口进行集群的访问,这里的访问包括:
1)对集群的整体访问
2)对象的访问
两类接口,这套接口(API)包括C、C++和Python常见语言的实现,接口通过网络实现对Ceph集群的访问。在用户层面,可以在自己的程序中调用该接口,从而集成Ceph集群的存储功能,或者在监控程序中实现对Ceph集群状态的监控。上述接口与Ceph集群的关系如图1所示。
RADOS的客户端API
上述接口几乎包括了对Ceph集群和其中数据的所有访问功能:
集群的整体访问:包括连接集群、创建存储池、删除存储池和获取集群状态等等。
对象访问:是指对存储池中对象的访问,包括创建删除对象、向对象写数据或者追加数据和读对象数据等接口。
上述功能通过Rados和IoCtx两个类实现,两个类的主要函数如图2所示(这里仅是示例,实际接口数量要多很多,具体参考源代码)。
为了了解如何使用这些API,我们这里给出一些代码片段。具体完整的代码大家可以参考Ceph官方的示例代码。
librados::IoCtx io_ctx;
const char *pool_name = "test";/* 创建进行IO处理的上下文,其实就是用于访问Ceph的对象 */
cluster.ioctx_create(pool_name, io_ctx);/* 同步写对象 */
librados::bufferlist bl;
bl.append("Hello World!"); /* 对象的内容 */
/*写入对象itworld123*/
ret = io_ctx.write_full("itworld123", bl);
/* 向对象添加属性,这里的属性与文件系统
* 中文件的扩展属性类似。 */
librados::bufferlist attr_bl;
attr_bl.append("en_US");
io_ctx.setxattr("itworld123", "test_attr", attr_bl);
/* 异步读取对象内容 */
librados::bufferlist read_buf;
int read_len = 1024;
/* 创建一个异步完成类对象 */
librados::AioCompletion *read_completion = librados::Rados::aio_create_completion();
/* 发送读请求 */
io_ctx.aio_read("itworld123", read_completion, &read_buf, read_len, 0);
/* 等待请求完成 */
read_completion->wait_for_complete();
read_completion->get_return_value();
/* 读取对象属性 */
librados::bufferlist attr_res;
io_ctx.getxattr("itworld123", "test_attr", attr_res);
/* 删除对象的属性 */
io_ctx.rmxattr("itworld123", "test_attr");
/* 删除对象 */
io_ctx.remove("itworld123");
Librados 与 Osdc 位于Ceph客户端中比较底层的位置,
Librados 提供了Pool的创建、删除、对象的创建、删除等基本接口;
Osdc则用于封装操作,计算对象的地址,发送请求和处理超时。
如图:
根据LIBRADOS架构图,叙述大概的事件流程。在 Ceph分布式存储实战中 这本书中有如下一段话:
先根据配置文件调用LIBRADOS创建一个RADOS,接下来为这个RADOS创建一个radosclient,radosclient包含3个主要模块(finisher、Message、Objector)。
再根据pool创建对应的ioctx,在ioctx中能够找到radosclient。在调用OSDC生成对应的OSD请求,与OSD进行通信响应请求。这从大体上叙述了librados与osdc在整个Ceph中的作用。
客户端软件架构概述
librados客户端基本架构如图3所示,主要包括4层,分别是API层、IO处理层、对象处理层和消息收发层。其中API层是一个抽象层,为上层提供统一的接口。API层提供的原生接口包括C和C++两种语言的实现外,还有Python的实现。
图3 RADOS客户端基本架构
IO处理层用于实现IO的简单封装,其通过一个名为ObjectOperation类实现,该类主要包括的是读写操作的数据信息。之后在IO处理层在IoCtxImpl::operate函数中将ObjectOperation转换为Objecter::Op类的对象,并将该对象提交到对象处理层进行进一步的处理。对象处理层包括了Ceph对象处理所需要的信息,包括通信管道、OSDMap和MonMap等内容。因此,在这里,根据对象的信息可以计算出对象存储的具体位置,最终找到客户端与OSD的连接信息(Session)。消息收发层的接口会被对象处理层调用,此时消息会传递到本层,并且通过本层的线程池发送到具体的OSD。这里需要注意的是,消息收发层与服务端的消息收发公用Messager的代码。
如图是核心流程的流程图,本文不详细介绍,具体细节可以按照该流程读对应源代码理解。
在这个流程中需要注意的是_op_submit函数会调用_calc_target和_get_session两个函数,两个函数的作用分别是获取目的OSD和对应的Session(连接),这个是后面发送数据的基础。
作者:SunnyZhang的IT世界
链接:https://www.jianshu.com/p/d7f69900ae8e
Librados
该模块包含两个部分,分别是RadosClient 模块和IoctxImpl。RadosClient处于最上层,是librados的核心管理类,管理着整个RADOS系统层面以及pool层面的管理。
而IoctxImpl则对于其中的某一个pool进行管理&#