rabbitMQ

1.rabbitMQ相对于传统的socket通信解决的问题

 1)信息的发送者和接收者如何维持这个连接,如果一方的连接中断,这期间的数据如何方式丢失?

 2)如何降低发送者和接收者的耦合度?

 3)如何让Priority(优先级)高的接收者先接到数据?

 4)如何做到load balance?有效均衡接收者的负载?

 5)如何有效的将数据发送到相关的接收者?也就是说将接收者subscribe 不同的数据,如何做有效的filter。

 6)如何做到可扩展,甚至将这个通信模块发到cluster上?

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

  AMDQ协议解决了以上的问题,而RabbitMQ实现了AMQP。

150733_eBKA_3721784.png

rabbitmq 服务相当于一个传输服务

1.2 rabbitmq的相关概念

 Producer,数据的发送方,相当于生产者

 Consumer ,数据的接收方,相当于消费者

 Connection: 就是一个TCP的连接。Producer和Consumer都是通过TCP连接到RabbitMQ Server的

 Channels: 通道,虚拟连接。它建立在上述的TCP连接中。数据流动都是在Channel中进行的。

 一个Message有两个部分:payload(有效载荷)和label(标签)。payload顾名思义就是传输的数据。 label是exchange的名字或者说是一个tag,它描述了payload,而且RabbitMQ也是通过这个label来决定把这个Message发给哪个Consumer。AMQP仅仅描述了label,而RabbitMQ决定了如何使用这个label的规则。

1.3 消息回应机制

   使用ack确认消息的正确传递

  默认情况下,如果一个消息被Consumer正确的接收到了,那么该Message会被从queue(队列)中删除。当然也可以让多个队列消费同一个消息(订阅模式)。

 如果一个queue没被任何的Consumer Subscribe(订阅),那么,如果这个queue有数据到达,那么这个数据会被cache,不会被丢弃。当有Consumer时,这个数据会被立即发送到这个Consumer,这个数据被Consumer正确收到时,这个数据就被从queue中删除。

如果这个app有bug,忘记了ack,那么RabbitMQ Server不会再发送数据给它,因为Server认为这个Consumer处理能力有限。

ack的机制可以起到限流的作用(Benefitto throttling):在Consumer处理完成数据后发送ack,甚至在额外的延时后发送ack,将有效的balance Consumer的load。

需要注意的是 在消息被Consumer接收处理的过程中出现了异常(没有处理异常),而ack的机制是消息处理完才会回应,因此RabbitMQ Server会一直发同一个message。

1.4 队列 queue

consumer和producer  都可以创建队列,队列是rabbitmq内容用于存储消息的。

多个消费者可以订阅同一个Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。

1.设置为持久化的队列,queue中的消息会在server本地硬盘存储一份,防止系统crash,数据丢失

2.设置为临时队列,queue中的数据在系统重启之后就会丢失

3.设置为自动删除的队列,当不存在用户连接到server,队列中的数据会被自动删除

1.5 Exchange 交换机

    生产者将消息发送到Exchange(交接机)中,由Exchange将消息路由到queue中

1.6 routing key (路由key)

生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则,而这个routing key需要与Exchange Type及binding key联合使用才能最终生效。

1.7 binding 

而queue需要与exchange type(交换机类型) 和binding key 绑定

RabbitMQ中通过Binding将Exchange与Queue关联起来,这样RabbitMQ就知道如何正确地将消息路由到指定的Queue

1.8 Exchange Type

direct-exchange: direct类型的Exchange路由规则也很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中。

fanout-exchange: fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。

topic-exchange: 

direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,它约定:

  • routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”
  • binding key与routing key一样也是句点号“. ”分隔的字符串
  • binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)

133513_RXN5_3721784.png

以上图中的配置为例,routingKey=”quick.orange.rabbit”的消息会同时路由到Q1与Q2,routingKey=”lazy.orange.fox”的消息会路由到Q1与Q2,routingKey=”lazy.brown.fox”的消息会路由到Q2,routingKey=”lazy.pink.rabbit”的消息会路由到Q2(只会投递给Q2一次,虽然这个routingKey与Q2的两个bindingKey都匹配);routingKey=”quick.brown.fox”、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息将会被丢弃,因为它们没有匹配任何bindingKey。

headers-exchange:

headers类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。
在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。

2. java 利用 spring的 template 对rabbit mq 进行操作

 2.1 maven 配置

//pom.xml
<dependency>
      <groupId>com.rabbitmq</groupId>
      <artifactId>amqp-client</artifactId>
      <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
        <version>1.4.5.RELEASE</version>
    </dependency>

app.properties中的文件配置

135536_Snuw_3721784.png

//application-mq.xml
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:rabbit="http://www.springframework.org/schema/rabbit" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/rabbit
    http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd" >

    <description>rabbitmq 连接服务配置</description>
    <!-- 连接配置 -->
    <rabbit:connection-factory id="connectionFactory" host="${mq.host}" username="${mq.username}" password="${mq.password}" port="${mq.port}"  virtual-host="${mq.vhost}"/>
    <rabbit:admin connection-factory="connectionFactory"/>

    <!-- spring template声明-->
    <rabbit:template exchange="amqpExchange" id="amqpTemplate"  connection-factory="connectionFactory"  message-converter="jsonMessageConverter" />

    <!-- 消息对象json转换类 -->
    <bean id="jsonMessageConverter" class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />  
</beans>
申明一个消息队列Queue
//application-mq.xml
<rabbit:queue id="test_queue_key" name="test_queue_key" durable="true" auto-delete="false" exclusive="false" />

durable:是否持久化

exclusive: 仅创建者可以使用的私有队列,断开后自动删除

auto_delete: 当所有消费客户端连接断开后,是否自动删除队列

交换机定义,

//application-mq.xml
<rabbit:direct-exchange name="test-mq-exchange" durable="true" auto-delete="false" id="test-mq-exchange">
    <rabbit:bindings>
        <rabbit:binding queue="test_queue_key" key="test_queue_key"/>
    </rabbit:bindings>
</rabbit:direct-exchange>

rabbit:binding:设置消息queue匹配的key,由于exchange是direct模式,这里的binding key 和路由key完全匹配

发送消息的代码:

140408_FLgf_3721784.png

将消息 发送到direct exchange中,并且指定路由key,queue(队列)和路由key binding的时候,binding 也是指定的这个routingkey。

 

接收消息的代码,通过监听消息队列获取消息即可

140822_OgsU_3721784.png

QueueListenter 实现MessageListener,复写onMessage方法

 

 

104607_qOnM_3721784.png

 

 

转载于:https://my.oschina.net/u/3721784/blog/1603035

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值