rabbitmq的中流砥柱

来源:互联网 发布:索尼淘宝授权店真假 编辑:程序博客网 时间:2024/06/11 13:47

rabbit相信在很多公司的异步架构中出现的频率很高,因为其基于通用AMQP协议又有自身的多种独特优点。话不多说,直接看一下其基础部件,这些东西是构成整个rabbit实例,甚至是整个集群的中流砥柱。

一切操作基于channel信道

每一个应用程序(生产者或者消费者)与rabbit通信,都要建立一个tcp链接,信道channel就是在这条tcp链接上创建的虚拟连接。AMQP的命令都是从信道传出去的,每个channel都会有唯一ID。所有的操作,包括发布信息,订阅信息或者接受信息,都是通过信道完成。

可是为何要采用信道这一机制?直接采用tcp不可以吗?

一般我们程序都是多线程的,而操作系统建立tcp会话是非常耗资源的。如果为每一条线程都建立tcp连接的话,那么我们的程序建立的tcp连接数将会是很庞大,会造成程序的性能瓶颈。如果我们只为每一个程序建立一条tcp连接,所有线程都在这条连接内通信,那么性能将大大提高。而信道就是为了这一需求设计的,每一条线程会单独创建一个信道,彼此之间相互独立,保证私密,就像拥有独立连接一样。也就是一条tcp连接上可以创建成百上千条信道,他是没有限制的。

AMQP被称为加强版的传输层,既不影响程序的传输效率,又大大降低系统开销。

消息路由的中转站——queue队列

rabbit的队列通过basic.declare来声明,每个队列都会有自己的名字,名字用在:

  • 创建队列时候,如果没有指定,就会产生一个随机名称
  • 订阅队列时候
  • 绑定队列时候

消费者在同一信道上,不能同时订阅其他队列,又创建队列。如果要在同一信道上创建队列,需要先取消订阅其他队列,将信道置为传输模式。创建队列有两个有用参数

  • exclusive 队列是否私有,如果是代表只有消费者自己能使用
  • auto-delete 当最后一个订阅者取消订阅后,队列自动销毁

如果只有一个临时队列给一个消费者使用的话,就要配合以上两个参数

声明的队列如果同名,参数相同的话,会返回已存在的队列,参数不同的话,就会失败报错。
如果仅仅是想测试队列存不存在,而不是真的想创建队列,设置参数passive为true,存在就成功返回,不存在就不会创建队列而是返回一个错误。

路由规则三分天下——exchange交换器

  • direct 根据路由键,投递到相应的队列。包含一个默认空白字符的交换器,其路由键就是要投递的队列名字。basic_public($msg,”“,”queue_name”),第一个是消息内容,第二个是代表默认空白交换器,第三个代表路由键,在这里就是队列的名字。
  • heads 路由键不适用队列名字而是AMQP消息的header,其他都一样,这种效率很低。(所以这个可忽略)
  • topic 将多种不同消息投递到一个或者多个相同的队列中,绑定队列中basic_bind(queue_name,exchage_name,routing_key),如果routing_key是一个具体的值,那么其实这是一个direct类型的,但是如果这个routing_key存在等通配符,那就意味着符合这些规则的消息都会投递到这个队列中。在routing_key中,“.”代表分模块,“”代表匹配任何字符,“#”代表匹配所有规则。
  • fanout 将一个消息投递到多个不同队列中,适用于一个消息多任务,比如用户注册,需要记录用户信息,分配初始金额等不同任务。

队列声明后绑定到交换器上,绑定不是说交换器就一定会将消息发送到绑定的队列上,而是根据交换器类型和规则,消息到达交换器后再投递到相应的队列中。队列要绑定到交换器的时候,要提供的参数包括队列名、交换器名和路由键,即queue_bind(‘queue_name,exchange_name,routing_key),这个路由键也就是绑定规则。

vhost分身术

rabbit中可以创建多个虚拟主机,每个虚拟主机都拥有独立的交换器、队列和绑定规则,多个虚拟主机共享同一台设备,而彼此间相互隔离,互不影响。这个在实际生产上很有用,因为队列服务器肯定会存在多个业务,而是之间是互不关联的,那么每个业务使用一个虚拟主机,将不会影响其他队列,安全性也得到保障。rabbit 的权限是细化到虚拟主机的,可以通过给虚拟主机配置账户来访问相应的虚拟主机。