puppet-rabbitmq模块

  1. 先睹为快
  2. 代码讲解
  3. 扩展阅读
  4. 动手练习

RabbitMQ是RabbitMQ Technologies Ltd开发的AMQP(Advanced Message Queue Protocol)的开源实现。RabbitMQ组件也是此书的重点章节,因为它与每个OpenStack服务息息相关,那么RabbitMQ解决了什么问题?

对于一个复杂的分布式系统而言,它包含了大量的组件或者子系统,那么这些组件之间是如何进行通信的呢?

分布式系统,顾名思义,其组件是运行在不同的服务器上,而传统的应用软件往往使用管道,信号,报文等方式来解决进程间的协作,这些进程间通讯IPC通常只是运行在单个操作系统上,不具备扩展的能力;如果使用Socket将服务组件部署到不同的服务器,需要解决以下问题:

1)消息的发送方和接收方如何维持连接,如果连接中断,如何处理这期间的已接收的数据?

2)如何解耦发送方和接收方?

3)如何有效地分发和接收消息?

4)如何实现消息处理能力的水平扩展?

5)如何保证接收方接收到了完整,正确的数据?

高级消息队列协议(AMQP)解决了上述问题,而RabbitMQ用Erlang实现了一个异步,模块化,可扩展的高级消息队列协议。

puppet-rabbitmq是由Puppet官方维护的模块,用于管理RabbitMQ服务的安装,配置。

puppet-rabbitmq项目地址:https://github.com/voxpupuli/puppet-rabbitmq

1.先睹为快

不想看下面大段的代码说明,已经跃跃欲试了?

OK,我们开始吧!

打开虚拟机终端并输入以下命令:

  1. $ puppet apply -e "class { 'rabbitmq': }"

等待上述命令执行完成,Puppet完成了对RabbitMQ服务的安装和配置。

2.代码讲解

2.1 class rabbitmq

class rabbitmq是一个入口类,用于声明当前模块中的相关资源,同时也会包含一些逻辑判断和声明,如:判断参数值类型是否符合预期、调用其它类(include)、继承params类、判断参数是否启用LADP验证等等。

  1. class rabbitmq(
  2. $admin_enable = $rabbitmq::params::admin_enable,
  3. $cluster_nodes = $rabbitmq::params::cluster_nodes,
  4. $config = $rabbitmq::params::config,
  5. $config_cluster = $rabbitmq::params::config_cluster,
  6. ...
  7. )inherits rabbitmq::params {
  8. validate_re($package_apt_pin, '^(|\d+)$')
  9. ...
  10. include '::rabbitmq::install'
  11. include '::rabbitmq::config'
  12. include '::rabbitmq::service'
  13. include '::rabbitmq::management'
  14. if $admin_enable and $service_manage {
  15. include '::rabbitmq::install::rabbitmqadmin'
  16. rabbitmq_plugin { 'rabbitmq_management':
  17. ensure => present,
  18. require => Class['rabbitmq::install'],
  19. notify => Class['rabbitmq::service'],
  20. provider => 'rabbitmqplugins',
  21. }
  22. Class['::rabbitmq::service'] -> Class['::rabbitmq::install::rabbitmqadmin']
  23. Class['::rabbitmq::install::rabbitmqadmin'] -> Rabbitmq_exchange<| |>
  24. }
  25. ...
  26. }

在代码块首有一些类似于validate_re($package_apt_pin, '^(|\d+)$')的代码,其实validate_re函数接收两个参数:参数名,正则表达式。用于检查指定参数的传入值是否与给定的正则表达式匹配。
因此,在应用catalog前对输入数据进行检查,可以提前发现的用户错误传参。

class rabbitmq作为一个入口类,声明了4个类:

  • rabbitmq::install
  • rabbitmq::config
  • rabbitmq::service
  • rabbitmq::management

2.2 class rabbitmq::install

rabbitmq::install用于管理RabbitMQ Server的软件部署和配置, 注意其参数的默认值是$rabbitmq::param_name的格式,说明该类在被声明时,class rabbitmq也需同时被声明。

  1. class rabbitmq::install {
  2. $package_ensure = $rabbitmq::package_ensure
  3. $package_name = $rabbitmq::package_name
  4. $package_provider = $rabbitmq::package_provider
  5. $package_require = $rabbitmq::package_require
  6. $package_source = $rabbitmq::real_package_source
  7. package { 'rabbitmq-server':
  8. ensure => $package_ensure,
  9. name => $package_name,
  10. provider => $package_provider,
  11. notify => Class['rabbitmq::service'],
  12. require => $package_require,
  13. }
  14. if $package_source {
  15. Package['rabbitmq-server'] {
  16. source => $package_source,
  17. }
  18. }
  19. if $rabbitmq::environment_variables['MNESIA_BASE'] {
  20. file { $rabbitmq::environment_variables['MNESIA_BASE']:
  21. ensure => 'directory',
  22. owner => 'root',
  23. group => 'rabbitmq',
  24. mode => '0775',
  25. require => Package['rabbitmq-server'],
  26. }
  27. }
  28. }

2.3 class rabbitmq::config

rabbitmq::config类用于统一管理RabbitMQ服务的目录和配置文件。可能会有读者有疑问,为什么要将软件包的安装和配置文件的管理分拆为
两个类。原因很简单,为了代码可读性,rabbitmq::config的代码长度有两百多行,若与其他代码合并在一起,阅读起来会非常痛苦。
这也是Puppet的最佳实践之一:尽可能保持代码的简洁和可读性。

  1. class rabbitmq::config {
  2. $admin_enable = $rabbitmq::admin_enable
  3. $cluster_node_type = $rabbitmq::cluster_node_type
  4. $cluster_nodes = $rabbitmq::cluster_nodes
  5. $config = $rabbitmq::config
  6. ...
  7. }
  8. ...
  9. file { '/etc/rabbitmq':
  10. ensure => directory,
  11. owner => '0',
  12. group => '0',
  13. mode => '0644',
  14. }
  15. file { '/etc/rabbitmq/ssl':
  16. ensure => directory,
  17. owner => '0',
  18. group => '0',
  19. mode => '0644',
  20. }
  21. ...

2.4 class rabbitmq::service

rabbitmq::installrabbitmq::config分别完成了软件包的安装、配置文件的生成,准备工作已经完成,rabbitmq::service类用于管理服务状态。

  1. class rabbitmq::service(
  2. Enum['running', 'stopped'] $service_ensure = $rabbitmq::service_ensure,
  3. Boolean $service_manage = $rabbitmq::service_manage,
  4. $service_name = $rabbitmq::service_name,
  5. ) inherits rabbitmq {
  6. if ($service_manage) {
  7. if $service_ensure == 'running' {
  8. $ensure_real = 'running'
  9. $enable_real = true
  10. } else {
  11. $ensure_real = 'stopped'
  12. $enable_real = false
  13. }
  14. service { 'rabbitmq-server':
  15. ensure => $ensure_real,
  16. enable => $enable_real,
  17. hasstatus => true,
  18. hasrestart => true,
  19. name => $service_name,
  20. }
  21. }
  22. }

读者可能已经注意到参数$service_ensure和$service_manage被声明了数据类型,其中Boolean被称为是数据类型(Data types),在Puppet中有以下数据类型:

  • Strings
  • Numbers
  • Booleans
  • Arrays
  • Hashes
  • Regular Expressions
  • Sensitive
  • Undef
  • Resource References
  • Default

此外,Enum称为是抽象数据类型(abstract data types),可以灵活地匹配/限制指定参数的数据类型。

例如,Boolean $service_manage严格地限定了$service_manage的数据类型为布尔型,而使用Optional[String, Boolean] $service_manage则可以指定$service_manage的数据类型可以是布尔型或者字符串。

3.扩展阅读

4.动手练习

1.默认安装的时候有guest用户,出于安全考虑,会删除此用户,请使用puppet-rabbitmq完成此操作。
2.如何使用自定义资源rabbitmq_user来创建用户?
3.在OpenStack中,fanout类型的队列应在程序退出时删除,RabbitMQ中可以使用Policy设置Queue的TTL,请使用rabbitmq_policy将.*上所有queue的ttl设置为18000s。