RabbitMQ源码分析 - 启动

RabbitMQ是一个消息队列的实现,基于AMQPAdvanced Message Queuing Protocol)。最近因为工作需要,打算深入了解RabbitMQ的架构以实现,后续会出一系列文章记录分析过程。这篇总结RabbitMQ的启动过程。

(注:分析代码基于RabbitMQ 2.8.2

 

         RabbitMQ的启动入口在[$RABBIT_SRC/src/rabbit.erl --> start/2]。主要代码如下:

start(normal, []) ->
    case erts_version_check() of
        ok ->
            {ok, SupPid} = rabbit_sup:start_link(),
            true = register(rabbit, self()),
            [ok = run_boot_step(Step) || Step <- boot_steps()],
            io:format("~nbroker running~n"),
            {ok, SupPid};
        Error ->
            Error
end.
其中 rabbit_sup:start_link/0 启动 rabbit 的监控树。最重要是这个调用 [ok = run_boot_step(Step) || Step <- boot_steps()]

boot_steps会从已加载的模块中提取自定义属性rabbit_boot_step的值(大部分定义在[$RABBIT_SRC/src/rabbit.erl]文件中),该结构定义了rabbit在启动过程中的一个启动步骤,其中包含:启动该步骤的启动入口,该步骤所依赖的步骤以及依赖于该步骤的步骤。其结构如下:

-rabbit_boot_step({rabbit_registry,
                   [{description, "plugin registry"},
                    {mfa,         {rabbit_sup, start_child,
                                   [rabbit_registry]}},
                    {requires,    external_infrastructure},
                    {enables,     kernel_ready}]}).
  其中 rabbit_registry 定义步骤名称, mfa 定义启动入口, requires 定义该步骤所依赖的步骤(组名), enables 说明依赖于该步骤成功执行的步骤。

         启动步骤可以分组。一组步骤的启动会依赖于另一组步骤的成功执行。像上面的rabbit_registry就依赖于external_infrastructure(包含多个启动步骤)的成功执行,而rabbit_registry的成功启动则会使kernel_ready进入准备状态。实际上,会有多个启动步骤会使kernel_ready进入准备状态,只有所有这些启动步骤都成功启动后,依赖于kernel_ready的步骤才能启动(像rabbit_log, rabbit_event都会使kernel_ready进入准备状态)。

         RabbitMQ就根据这些启动步骤之间的依赖关系,构造一个有向无环图(这跟我在ganger里对进程依赖关系的组织类似),并拓扑排序所有步骤(参见[$RABBIT_SRC/src/rabbit.erl --> sort_boot_steps/2]),生成唯一的启动顺序,然后按照该启动顺序调用相应启动步骤的MFA启动相应功能(参见[$RABBIT_SRC/src/rabbit.erl --> run_boot_steps/2])。

(具体有哪些启动步骤,以及每个步骤的具体功能参见这篇文章:RabbitMQ Boot Process

扫描二维码关注公众号,回复: 843420 查看本文章

猜你喜欢

转载自jzhihui.iteye.com/blog/1540047