Rabbit MQ持久化

来源:互联网 发布:指南针炒股软件诈骗 编辑:程序博客网 时间:2024/05/10 21:44

4. 持久化: Rabbit MQ默认是不持久队列、Exchange、Binding以及队列中的消息的,这意味着一旦消息服务器重启,所有已声明的队列,Exchange,Binding以及队列中的消息都会丢失。通过设置Exchange和MessageQueue的durable属性为true,可以使得队列和Exchange持久化,但是这还不能使得队列中的消息持久化,这需要生产者在发送消息的时候,将delivery mode设置为2,只有这3个全部设置完成后,才能保证服务器重启不会对现有的队列造成影响。这里需要注意的是,只有durable为true的Exchange和durable为ture的Queues才能绑定,否则在绑定时,RabbitMQ都会抛错的。持久化会对RabbitMQ的性能造成比较大的影响,可能会下降10倍不止。


RabbitMQ支持消息的持久化,也就是数据写在磁盘上,为了数据安全考虑,我想大多数用户都会选择持久化。消息队列持久化包括3个部分:
  (1exchange持久化,在声明时指定durable => 1
  (2queue持久化,在声明时指定durable => 1
  (3)消息持久化,在投递时指定delivery_mode=> 21是非持久化)

如果exchangequeue都是持久化的,那么它们之间的binding也是持久化的。如果exchangequeue两者之间有一个持久化,一个非持久化,就不允许建立绑定。




 生产者在发送消息时,都需要指定一个RoutingKeyExchangeExchange在接到该RoutingKey以后,会判断该ExchangeType:

                         a) 如果是Direct类型,则会将消息中的RoutingKey与该Exchange关联的所有Binding中的BindingKey进行比较,如果相等,则发送到该Binding对应的Queue中。

RabbitMQ系列二(构建消息队列) - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客
                  b) 如果是Fanout类型,则会将消息发送给所有与该Exchange定义过Binding的所有Queues中去,其实是一种广播行为。
         
RabbitMQ系列二(构建消息队列) - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客 

        c)如果是Topic类型,则会按照正则表达式,对RoutingKeyBindingKey进行匹配,如果匹配成功,则发送到对应的Queue中。

             RabbitMQ系列二(构建消息队列) - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客


3、Exchange类型topic

这个类型的路由规则如果你掌握啦,那是相当的好用,与灵活。他是根据RoutingKey的设置,来做匹配的,其中这里还有两个通配符为:

*,代表任意的一个词。例如topic.zlh.*,他能够匹配到,topic.zlh.one ,topic.zlh.two ,topic.zlh.abc, ....

#,代表任意多个词。例如topic.#,他能够匹配到,topic.zlh.one ,topic.zlh.two ,topic.zlh.abc, ....






  1. boolean durable = true;  
  2. channel.queueDeclare("hello", durable, falsefalsenull);  
       尽管这行代码是正确的,但他不会在我们当前的设置中起作用。因为我们已经定义了一个名叫hello的未持久化的队列。RabbitMQ不允许使用不同的参数设定重新定义已经存在的队列,并且会向尝试如此做的程序返回一个错误。一个快速的解决方案——就是声明一个不同名字的队列,比如task_queue。


 Auto-delete:自动删除,如果该队列没有任何订阅的消费者的话,该队列会被自动删除。这种队列适用于临时队列。


) Exclusive:排他队列,如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。这里需要注意三点:其一,排他队列是基于连接可见的,同一连接的不同信道是可以同时访问同一个连接创建的排他队列的。其二,“首次”,如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同。其三,即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除的。这种队列适用于只限于一个客户端发送读取消息的应用场景。



  还有几个概念是上述图中没有标明的,那就是Connection(连接),Channel(通道,频道)。

   Connection : 就是一个TCP的连接。Producer和Consumer都是通过TCP连接到RabbitMQ Server的。以后我们可以看到,程序的起始处就是建立这个TCP连接。

   Channels : 虚拟连接。它建立在上述的TCP连接中。数据流动都是在Channel中进行的。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel。

    那么,为什么使用Channel,而不是直接使用TCP连接?

    对于OS来说,建立和关闭TCP连接是有代价的,频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理高并发的能力。但是,在TCP连接中建立Channel是没有上述代价的。对于Producer或者Consumer来说,可以并发的使用多个Channel进行Publish或者Receive。



最简单的方式是使RabbitMQ以Windows Service的方式在后台运行,所以我们需要以管理员权限打开cmd,然后切换到sbin目录下,执行这三条命令即可:

rabbitmq-service installrabbitmq-service enablerabbitmq-service start

Start RabbitMQ Service

现在RabbitMQ的服务端已经启动起来了。

下面可以使用sbin目录下面的rabbitmqctl.bat这个脚本来查看和控制服务端状态的,在cmd中直接运行rabbitmqctl status。如果看到以下结果:

Unable to connect node

显示node没有连接上,需要到C:\Windows目录下,将.erlang.cookie文件,拷贝到用户目录下 C:\Users\{用户名},这是Erlang的Cookie文件,允许与Erlang进行交互,现在重复运行刚才的命令就会得到如下信息:

rabbit mq status

RabbitMQ Server上面也有用户概念,安装好之后,使用rabbitmqctl list_users命令,可以看到上面目前的用户:

RabbitMQ users

可以看到,现在只有一个角色为administrator的名为guest的用户,这个是RabbitMQ默认为我们创建的,他有RabbitMQ的所有权限,一般的,我们需要新建一个我们自己的用户,设置密码,并授予权限,并将其设置为管理员,可以使用下面的命令来执行这一操作:

rabbitmqctl  add_user  yy  hello!rabbitmqctl  set_permissions  yy  ".*"  ".*"  ".*"rabbitmqctl  set_user_tags yy administrator

Create RabbitMQ user

上面的一条命令添加了一个名为yy的用户,并设置了密码hello!,下面的命令为用户yy分别授予对所有消息队列的配置、读和写的权限。

现在我们可以将默认的guest用户删掉,使用下面的命令即可:

rabbitmqctl delete_user guest

如果要修改密码,可以使用下面的命令:

rabbitmqctl change_password {username}  {newpassowrd}



       //普通使用方式BasicGet
                    
//noAck = true,不需要回复,接收到消息后,queue上的消息就会清除
                    
//noAck = false,需要回复,接收到消息后,queue上的消息不会被清除,直到调用channel.basicAck(deliveryTag, false); queue上的消息才会被清除 而且,在当前连接断开以前,其它客户端将不能收到此queue上的消息
                    BasicGetResult res = ch.BasicGet("q1"false/*noAck*/);






0 0