• rbd-mirror源码分析


    1. rbd mirror 流程从rbd-mirror二进制文件启动。

    在看这部分逻辑之前,需要对librbd中的回调函数,回调类有足够的理解。

    rbd-mirror从main函数开始启动,在main中调用Mirror::run()函数。
    这个run函数中调用update_pool_replayers函数。

    int r = mirror->init();
    
    mirror->run();
    

    在run函数中,调用update_pool_replayers(m_local_cluster_watcher->get_pool_peers());
    继续在update_pool_replayers()函数调用pool_replayer->init();函数。
    pool_replayer::init()函数,主要包含了更多的watcher函数以及启动pool_replayer的一个线程,用于监听admin socket。如下:

    m_instance_replayer.reset(InstanceReplayer<>::create(
        m_threads, m_service_daemon, m_image_deleter, m_local_rados,
        local_mirror_uuid, m_local_pool_id));
      m_instance_replayer->set_throttle(m_bps_throttle);
      m_instance_replayer->init();
      m_instance_replayer->add_peer(m_peer.uuid, m_remote_io_ctx);
    
      m_instance_watcher.reset(InstanceWatcher<>::create(
        m_local_io_ctx, m_threads->work_queue, m_instance_replayer.get()));
      r = m_instance_watcher->init();
      if (r < 0) {
        derr << "error initializing instance watcher: " << cpp_strerror(r) << dendl;
        m_callout_id = m_service_daemon->add_or_update_callout(
          m_local_pool_id, m_callout_id, service_daemon::CALLOUT_LEVEL_ERROR,
          "unable to initialize instance messenger object");
        return;
      }
    
      m_leader_watcher.reset(new LeaderWatcher<>(m_threads, m_local_io_ctx,
                                                 &m_leader_listener));
      r = m_leader_watcher->init();
      if (r < 0) {
        derr << "error initializing leader watcher: " << cpp_strerror(r) << dendl;
        m_callout_id = m_service_daemon->add_or_update_callout(
          m_local_pool_id, m_callout_id, service_daemon::CALLOUT_LEVEL_ERROR,
          "unable to initialize leader messenger object");
        return;
      }
    

    注意这里有:m_instance_replayer->init(), m_instance_watcher->init(), m_leader_watcher->init()
    其中:
    m_instance_replayer->init()有如下调用:

      template <typename I>
    int InstanceReplayer<I>::init() {
      C_SaferCond init_ctx;
      init(&init_ctx);
      return init_ctx.wait();
    }
    
    template <typename I>
    void InstanceReplayer<I>::init(Context *on_finish) {
      dout(20) << dendl;
      Context *ctx = new FunctionContext(
        [this, on_finish] (int r) {
          {
            Mutex::Locker timer_locker(m_threads->timer_lock);
            schedule_image_state_check_task();
          }
          on_finish->complete(0);
        });
      // 这里将包含schedule_image_state_check_task函数的ctx对象扔到了线程池队列中
      // 通过定时任务就可以执行schedule_image_state_check_task这个函数。
      m_threads->work_queue->queue(ctx, 0);
    }
    

    schedule_image_state_check_task中通过设置定时器的方式调用了,queue_start_image_replayers从这里就可以开始进行以下的调用:start_image_replayer,最终调用到image_replayer->start()这个函数。
    image_replayer->start()这个函数开始,经历如下的流程:

    /**
      * @verbatim
      *                   (error)
      * <uninitialized> <------------------------------------ FAIL
      *    |                                                   ^
      *    v                                                   *
      * <starting>                                             *
      *    |                                                   *
      *    v                                                   *
      * WAIT_FOR_DELETION                                      *
      *    |                                                   *
      *    v                                           (error) *
      * PREPARE_LOCAL_IMAGE  * * * * * * * * * * * * * * * * * *
      *    |                                                   *
      *    v                                           (error) *
      * PREPARE_REMOTE_IMAGE * * * * * * * * * * * * * * * * * *
      *    |                                                   *
      *    v                                           (error) *
      * BOOTSTRAP_IMAGE  * * * * * * * * * * * * * * * * * * * *
      *    |                                                   *
      *    v                                           (error) *
      * INIT_REMOTE_JOURNALER  * * * * * * * * * * * * * * * * *
      *    |                                                   *
      *    v                                           (error) *
      * START_REPLAY * * * * * * * * * * * * * * * * * * * * * *
      *    |
      *    |  /--------------------------------------------
      *    |  |                                            |
      *    v  v   (asok flush)                             |
      * REPLAYING -------------> LOCAL_REPLAY_FLUSH        |
      *    |                        |                     |
      *    |       |                 v                     |
      *    |       |             FLUSH_COMMIT_POSITION     |
      *    |       |                 |                     |
      *    |       |                 --------------------/|
      *    |       |                                       |
      *    |       | (entries available)                   |
      *    |       -----------> REPLAY_READY              |
      *    |                         |                     |
      *    |                         | (skip if not        |
      *    |                         v  needed)        (error)
      *    |                     REPLAY_FLUSH  * * * * * * * * *
      *    |                         |                     |   *
      *    |                         | (skip if not        |   *
      *    |                         v  needed)        (error) *
      *    |                     GET_REMOTE_TAG  * * * * * * * *
      *    |                         |                     |   *
      *    |                         | (skip if not        |   *
      *    |                         v  needed)        (error) *
      *    |                     ALLOCATE_LOCAL_TAG  * * * * * *
      *    |                         |                     |   *
      *    |                         v                 (error) *
      *    |                     PREPROCESS_ENTRY  * * * * * * *
      *    |                         |                     |   *
      *    |                         v                 (error) *
      *    |                     PROCESS_ENTRY * * * * * * * * *
      *    |                         |                     |   *
      *    |                         ---------------------/   *
      *    v                                                   *
      * REPLAY_COMPLETE  < * * * * * * * * * * * * * * * * * * *
      *    |
      *    v
      * JOURNAL_REPLAY_SHUT_DOWN
      *    |
      *    v
      * LOCAL_IMAGE_CLOSE
      *    |
      *    v
      * <stopped>
      *
      * @endverbatim
      */
    

    以上流程主要集中在ImageReplayer中。从以上流程可以看出,从初始化开始后,整个流程集中在start这个函数。
    void ImageReplayer<I>::start()函数一直到 ImageReplayer<I>::bootstrap()中,这里调用了request()函数

    void ImageReplayer<I>::bootstrap()
    {
        ....
        request->send();
        ....
    }
    
     /**
       * @verbatim
       *
       * <start>
       *    |
       *    v
       * GET_REMOTE_TAG_CLASS * * * * * * * * * * * * * * * * * *
       *    |                                                   * (error)
       *    v                                                   *
       * OPEN_REMOTE_IMAGE  * * * * * * * * * * * * * * * * * * *
       *    |                                                   *
       *    |/--------------------------------------------------*---
       *    v                                                   *   |
       * IS_PRIMARY * * * * * * * * * * * * * * * * * * * * *   *   |
       *    |                                               *   *   |
       *    | (remote image primary, no local image id)     *   *   |
       *    ----> UPDATE_CLIENT_IMAGE  * * * * * * * * * * *   *   |
       *    |         |                                     *   *   |
       *    |         v                                     *   *   |
       *    ----> CREATE_LOCAL_IMAGE * * * * * * * * * * * *   *   |
       *    |         |                                     *   *   |
       *    |         v                                     *   *   |
       *    | (remote image primary)                        *   *   |
       *    ----> OPEN_LOCAL_IMAGE * * * * * * * * * * * * *   *   |
       *    |         |   .                                 *   *   |
       *    |         |   . (image doesn't exist)           *   *   |
       *    |         |   . . > UNREGISTER_CLIENT * * * * * *   *   |
       *    |         |             |                       *   *   |
       *    |         |             v                       *   *   |
       *    |         |         REGISTER_CLIENT * * * * * * *   *   |
       *    |         |             |                       *   *   |
       *    |         |             -----------------------*---*---/
       *    |         |                                     *   *
       *    |         v (skip if not needed)                *   *
       *    |      GET_REMOTE_TAGS  * * * * * * *           *   *
       *    |         |                         *           *   *
       *    |         v (skip if not needed)    v           *   *
       *    |      IMAGE_SYNC * * * > CLOSE_LOCAL_IMAGE     *   *
       *    |         |                         |           *   *
       *    |         ----------------- /-----/           *   *
       *    |                            |                  *   *
       *    |                            |                  *   *
       *    | (skip if not needed)       |                  *   *
       *    ----> UPDATE_CLIENT_STATE  *|* * * * * * * * * *   *
       *                |                |                  *   *
       *    /-----------/----------------/                  *   *
       *    |                                               *   *
       *    v                                               *   *
       * CLOSE_REMOTE_IMAGE < * * * * * * * * * * * * * * * *   *
       *    |                                                   *
       *    v                                                   *
       * <finish> < * * * * * * * * * * * * * * * * * * * * * * *
       *
       * @endverbatim
       */
    

    image sync流程如下,经历过如下的流程后,一个image的所有数据都进行了同步。

     /**
       * @verbatim
       *
       * <start>
       *    |
       *    v
       * NOTIFY_SYNC_REQUEST
       *    |
       *    v
       * PRUNE_CATCH_UP_SYNC_POINT
       *    |
       *    v
       * CREATE_SYNC_POINT (skip if already exists and
       *    |               not disconnected)
       *    v
       * COPY_SNAPSHOTS
       *    |
       *    v
       * COPY_IMAGE . . . . . . . . . . . . . .
       *    |                                 .
       *    v                                 .
       * COPY_OBJECT_MAP (skip if object      .
       *    |             map disabled)       .
       *    v                                 .
       * REFRESH_OBJECT_MAP (skip if object   .
       *    |                map disabled)    .
       *    v                                 .
       * PRUNE_SYNC_POINTS                    . (image sync canceled)
       *    |                                 .
       *    v                                 .
       * COPY_METADATA                        .
       *    |                                 .
       *    v                                 .
       * <finish> < . . . . . . . . . . . . . .
       *
       * @endverbatim
       */
    

    在我的DR环境中,找个rbdmirror的pod,进入到/var/run/ceph目录下,执行:
    ceph --admin-daemon ./ceph-client.dr.asok rbd mirror start
    以下是命令的执行流程:

    void PoolReplayer::start()
    {
      dout(20) << "enter" << dendl;
    
      Mutex::Locker l(m_lock);
    
      if (m_stopping) {
        return;
      }
    
      m_instance_replayer->start();
    }
    

    然后执行现在的:

    template <typename I>
    void InstanceReplayer<I>::start()
    {
      dout(20) << dendl;
    
      Mutex::Locker locker(m_lock);
    
      m_manual_stop = false;
    
      for (auto &kv : m_image_replayers) {
        auto &image_replayer = kv.second;
        image_replayer->start(nullptr, true);
      }
    }
    

    从这里也可以看出,在m_image_replayers这个map中找到相关的image_replayer实例,这里有个疑问:m_image_replayers这个实例是怎么生成的?
    答案:这个实例,是从m_instance_replayer->acquire_image(this, global_image_id, on_finish);这个流程开始的(从InstanceWatcher.cc这里面调用的。)。这里先不管acquire_image里面的流程,只需要知道这里面生成m_image_replayer对象。
    需要说明的是,m_image_replayers这个map中,是一个global_image_id对应一个image_replayer实例。

    auto &image_replayer = kv.second;
    这个map的value对应的就是image_replayer对象。所以这里还是就开始跳到image replayer中去了。

    进入到ImageReplayer::start()中,这部分流程就和以前的流程相似了。

  • 相关阅读:
    免密登录配置
    C#实现文件Zip压缩
    mssql_Sqlserver创建Sqlserver DBlink
    mssql_Sqlserver创建Mysql DBlink
    VS创建项目清单
    css实现气泡对话框Demo
    安卓好用的软件和模块
    搭建Vmq
    解决openvmtools无法复制粘贴文件问题
    Python篇socket
  • 原文地址:https://www.cnblogs.com/powerrailgun/p/12336490.html
Copyright © 2020-2023  润新知