千家信息网

Ceph中RGW是如何向底层OSD发送Message的

发表于:2024-11-16 作者:千家信息网编辑
千家信息网最后更新 2024年11月16日,这篇文章主要介绍Ceph中RGW是如何向底层OSD发送Message的,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. Librados的读写流程在src/cls/rgw/c
千家信息网最后更新 2024年11月16日Ceph中RGW是如何向底层OSD发送Message的

这篇文章主要介绍Ceph中RGW是如何向底层OSD发送Message的,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

1. Librados的读写流程

src/cls/rgw/cls_rgw_client.cc可以看到如下函数:

int cls_rgw_lc_set_entry(IoCtx& io_ctx, string& oid, pair& entry){    bufferlist in, out;    cls_rgw_lc_set_entry_op call;    call.entry = entry;    ::encode(call, in);    int r = io_ctx.exec(oid, "rgw", "lc_set_entry", in, out);    return r;}

继续跟踪io_ctx.exec()这个函数调用, 在src/librados/librados.cc可以查看到相应的函数实现如下:

int librados::IoCtx::exec(const std::string& oid, const char *cls, const char *method,                          bufferlist& inbl, bufferlist& outbl){  object_t obj(oid);  return io_ctx_impl->exec(obj, cls, method, inbl, outbl);}

继续跟踪io_ctx_impl->exec()这个函数调用,在librados/IoCtxImpl.cc中看到如下实现:

int librados::IoCtxImpl::exec(const object_t& oid,                               const char *cls, const char *method,                              bufferlist& inbl, bufferlist& outbl){  ::ObjectOperation rd;  prepare_assert_ops(&rd);  rd.call(cls, method, inbl);  return operate_read(oid, &rd, &outbl);}

rd.call()此函数将该操作封装成OSDOp,放入ObjectOperation对象的vector集合中。 在最后的operate_read(oid, &rd, &outbl)函数中发起读写请求操作:

int librados::IoCtxImpl::operate_read(const object_t& oid,                                       ::ObjectOperation *o,                                      bufferlist *pbl,                                      int flags){  if (!o->size())    return 0;  Mutex mylock("IoCtxImpl::operate_read::mylock");  Cond cond;  bool done;  int r;  version_t ver;   Context *onack = new C_SafeCond(&mylock, &cond, &done, &r);   int op = o->ops[0].op.op;  ldout(client->cct, 10) << ceph_osd_op_name(op) << " oid=" << oid << " nspace=" << oloc.nspace << dendl;  Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc,                                              *o, snap_seq, pbl, flags,                                              onack, &ver);  lock->Lock();  objecter->op_submit(objecter_op);  lock->Unlock();  mylock.Lock();  while (!done)    cond.Wait(mylock);  mylock.Unlock();  ldout(client->cct, 10) << "Objecter returned from "        << ceph_osd_op_name(op) << " r=" << r << dendl;  set_sync_op_version(ver);  return r;}

需要说明的是operate_read(oid, &rd, &outbl)可以分解为一下三个步骤:

  1. 创建一个Op实例,数据结构变成了Objecter::Op

Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc,                                              *o, snap_seq, pbl, flags,                                              onack, &ver);
  1. 操作提交到objecter层,操作对象类型变为Objecter::Op, 函数实现在osdc/Objecter.cc:

objecter->op_submit(objecter_op)

继续调用ceph_tid_t Objecter::_op_submit()函数,函数实现在osdc/Objecter.cc: 省略了部分代码,重点关注send_op(op)

ceph_tid_t Objecter::_op_submit(Op *op) {  // pick tid if we haven't got one yet  if (op->tid == ceph_tid_t(0)) {    ceph_tid_t mytid = ++last_tid;    op->tid = mytid;  }  assert(client_inc >= 0);  // pick target  num_homeless_ops++;  // initially; recalc_op_target() will decrement if it finds a target  int r = recalc_op_target(op);  bool check_for_latest_map = (r == RECALC_OP_TARGET_POOL_DNE);  ............  else if (op->session) {    send_op(op);  }   ............. }

这里的send_op(op)就是我们要关注的重点了. 从这里开始就会用到网络层提供的各种操作将消息,也就是这里的op发送出去. 这里可以看成是调用网络层的一个起点.


下面的代码就和网络层有关系了。

2. 发送消息的过程。

在网络层中,需要注意的是类Messenger是核心的数据结构。同时也是个抽象基类,在Firefly版本中,由于网络通信类型只实现了SimpleMessenger这一单一类型。在后面,就会看到SimpleMessenger是继承自Messenger类,很多方法最终都是调用的是SimpleMessenger(在此也可以体会到多态思想)。 首先,看一下Objecter类的声明(其他部分已省略):

class Objecter : public md_config_obs_t {    ...........    public:         Messenger *messenger;    ........}

在这个类中声明了messenger. 从ceph_tid_t Objecter::_op_submit(Op *op) 中可以看到,最后调用了send_op()函数。 这个函数末尾:

messenger->send_message(m, op->session->con);

可以看出,需要发送的消息是: m。 发送到哪里去呢? 通过**op->session->con**可以获取到相应的连接。

以上是"Ceph中RGW是如何向底层OSD发送Message的"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

0