Rabbitmq学习

RabbitMQ简介

目前RabbitMQ是AMQP 0-9-1(高级消息队列协议)的一个实现,使用Erlang语言编写,利用了Erlang的分布式特性。

代码地址

http://download.csdn.net/download/qq_27116489/10131642


概念介绍:

  1. Broker:简单来说就是消息队列服务器实体。
  2. Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
  3. Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
  4. Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
  5. Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
  6. vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
  7. producer:消息生产者,就是投递消息的程序。
  8. consumer:消息消费者,就是接受消息的程序。
  9. channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。

使用流程

AMQP模型中,消息在producer中产生,发送到MQ的exchange上,exchange根据配置的路由方式发到相应的Queue上,Queue又将消息发送给consumer,消息从queue到consumer有push和pull两种方式。 消息队列的使用过程大概如下:

  1. 客户端连接到消息队列服务器,打开一个channel。
  2. 客户端声明一个exchange,并设置相关属性。
  3. 客户端声明一个queue,并设置相关属性。
  4. 客户端使用routing key,在exchange和queue之间建立好绑定关系。
  5. 客户端投递消息到exchange。

exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。 exchange也有几个类型,完全根据key进行投递的叫做Direct交换机,例如,绑定时设置了routing key为”abc”,那么客户端提交的消息,只有设置了key为”abc”的才会投递到队列。

Exchange类型

Exchange路由消息的集中类型:

名称

默认的预先定义exchange名字

作用描述

Direct exchange

(Empty string) and amq.direct

根据Binding指定的Routing Key,将符合Key的消息发送到Binding的Queue

Fanout exchange

amq.fanout

将同一个message发送到所有同该Exchange bingding的queue

Topic exchange

amq.topic

根据Binding指定的Routing Key,Exchange对key进行模式匹配后路由到相应的Queue,模式匹配时符号”#”匹配一个或多个词,符号”*”匹配正好一个词。

Headers exchange

amq.match (and amq.headers in RabbitMQ)

同direct exchange类似,不同之处是不再使用Routing Key路由,而是使用headers(message attributes)进行匹配路由到指定Queue。

Hello,Rabbitmq搭建

本文基于Spring rabbitmq搭建基础框架,

需要的依赖pom

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mq</groupId>
	<artifactId>rabbitmq</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>

		<!-- <dependency> <groupId>com.rabbitmq</groupId> <artifactId>rabbitmq-client</artifactId> 
			<version>1.3.0</version> </dependency> -->
		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-rabbit</artifactId>
			<version>1.4.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-amqp</artifactId>
			<version>1.4.5.RELEASE</version>
		</dependency>       
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.1.6.RELEASE</version>
		</dependency>
		<!-- Junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>

	</dependencies>
</project>

applicationcontext.xml

1,连接rabbitmq

<rabbit:connection-factory id="connectionFactory"
		host="127.0.0.1" username="admin" password="admin" port="5672"
		virtual-host="/" />
	<!-- 连接配置 -->
	<rabbit:admin connection-factory="connectionFactory" />

2,声明


	<!-- spring template声明 -->
	<rabbit:template exchange="test-mq-exchange" id="amqpTemplate"
		connection-factory="connectionFactory" message-converter="messageConverter" />
	<bean id="messageConverter"
		class="org.springframework.amqp.support.converter.SimpleMessageConverter" />

3,队列



	<!-- 标准的建立Queue的参数 -->
	<rabbit:queue-arguments id="amqpQueueArguments">
		<!-- 暂时没有 -->
	</rabbit:queue-arguments>
	
	<!-- queue -->
	<rabbit:queue id="test_queue_key" name="test_queue_key"  queue-arguments="amqpQueueArguments"
		durable="true" auto-delete="false" exclusive="false" />

	<rabbit:queue id="test_queue_key2" name="test_queue_key2"  queue-arguments="amqpQueueArguments"
		durable="true" auto-delete="false" exclusive="false" />
	<rabbit:queue id="test_queue_key3" name="test_queue_key3"  queue-arguments="amqpQueueArguments"
		durable="true" auto-delete="false" exclusive="false" />
	<!-- durable:是否持久化 exclusive: 仅创建者可以使用的私有队列,断开后自动删除 auto_delete: 当所有消费客户端连接断开后,是否自动删除队列 -->

4,交换器


	<!-- exchange -->
	<rabbit:direct-exchange name="test-mq-exchange"
		durable="true" auto-delete="false" id="test-mq-exchange" auto-declare="true">
		<rabbit:bindings>
			<rabbit:binding queue="test_queue_key2" key="test_queue_key2" />
			<rabbit:binding queue="test_queue_key" key="test_queue_key" />
			<rabbit:binding queue="test_queue_key3" key="test_queue_key3" />
		</rabbit:bindings>
	</rabbit:direct-exchange>

5,监听消费者



	<bean name="Consummer" class="com.mq.rabbitmq.Consummer" />
	<bean name="Consummer2" class="com.mq.rabbitmq.Consummer" />
	<bean name="Consummer3" class="com.mq.rabbitmq.Consummer" />
	<!-- 配置监听 消费者 -->
	<rabbit:listener-container
		connection-factory="connectionFactory" acknowledge="auto">
		<!-- queues 监听队列,多个用逗号分隔 ref 监听器 -->
		<rabbit:listener queues="test_queue_key2" ref="Consummer2" />
		<rabbit:listener queues="test_queue_key" ref="Consummer" />
		<rabbit:listener queues="test_queue_key3" ref="Consummer3" />
	</rabbit:listener-container>
	
	

6,Spring包扫描


	
	<context:component-scan base-package="com.mq.rabbitmq"></context:component-scan>

完整的applicationcontext.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans default-lazy-init="false" xmlns:p="http://www.springframework.org/schema/p"
	xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:rabbit="http://www.springframework.org/schema/rabbit" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd 
		 http://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-3.1.xsd
		http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd  ">

	<rabbit:connection-factory id="connectionFactory"
		host="127.0.0.1" username="admin" password="admin" port="5672"
		virtual-host="/" />
	<!-- 连接配置 -->
	<rabbit:admin connection-factory="connectionFactory" />

	<!-- spring template声明 -->
	<rabbit:template exchange="test-mq-exchange" id="amqpTemplate"
		connection-factory="connectionFactory" message-converter="messageConverter" />
	<bean id="messageConverter"
		class="org.springframework.amqp.support.converter.SimpleMessageConverter" />

	<!-- 标准的建立Queue的参数 -->
	<rabbit:queue-arguments id="amqpQueueArguments">
		<!-- 暂时没有 -->
	</rabbit:queue-arguments>
	
	<!-- queue -->
	<rabbit:queue id="test_queue_key" name="test_queue_key"  queue-arguments="amqpQueueArguments"
		durable="true" auto-delete="false" exclusive="false" />

	<rabbit:queue id="test_queue_key2" name="test_queue_key2"  queue-arguments="amqpQueueArguments"
		durable="true" auto-delete="false" exclusive="false" />
	<rabbit:queue id="test_queue_key3" name="test_queue_key3"  queue-arguments="amqpQueueArguments"
		durable="true" auto-delete="false" exclusive="false" />
	<!-- durable:是否持久化 exclusive: 仅创建者可以使用的私有队列,断开后自动删除 auto_delete: 当所有消费客户端连接断开后,是否自动删除队列 -->
	<!-- exchange -->
	<rabbit:direct-exchange name="test-mq-exchange"
		durable="true" auto-delete="false" id="test-mq-exchange" auto-declare="true">
		<rabbit:bindings>
			<rabbit:binding queue="test_queue_key2" key="test_queue_key2" />
			<rabbit:binding queue="test_queue_key" key="test_queue_key" />
			<rabbit:binding queue="test_queue_key3" key="test_queue_key3" />
		</rabbit:bindings>
	</rabbit:direct-exchange>

	<bean name="Consummer" class="com.mq.rabbitmq.Consummer" />
	<bean name="Consummer2" class="com.mq.rabbitmq.Consummer" />
	<bean name="Consummer3" class="com.mq.rabbitmq.Consummer" />
	<!-- 配置监听 消费者 -->
	<rabbit:listener-container
		connection-factory="connectionFactory" acknowledge="auto">
		<!-- queues 监听队列,多个用逗号分隔 ref 监听器 -->
		<rabbit:listener queues="test_queue_key2" ref="Consummer2" />
		<rabbit:listener queues="test_queue_key" ref="Consummer" />
		<rabbit:listener queues="test_queue_key3" ref="Consummer3" />
	</rabbit:listener-container>
	
	
	
	
	<context:component-scan base-package="com.mq.rabbitmq"></context:component-scan>
</beans>

生产者 

发送消息接口

package com.mq.rabbitmq;

public interface MqInt {
	
	
	    public void sendDataToQueue(String queueKey, Object object);
}

接口实现类

package com.mq.rabbitmq;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MqImpl implements MqInt {
	
	@Autowired
	private AmqpTemplate amqpTemplate;
	
	@Override
	public void sendDataToQueue(String queueKey, Object object) {
		amqpTemplate.convertAndSend(queueKey, object);
		
	}

}

监听 ------消费者

package com.mq.rabbitmq;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.beans.factory.annotation.Autowired;

public class Consummer implements MessageListener{

	
	@Autowired
	private AmqpTemplate amqpTemplate;
	public int count =1;
	@Override
	public void onMessage(Message message) {
		System.out.println(count+"-----------");
		count++;
		System.out.println(message);
	}

}

测试类

package test;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.mq.rabbitmq.MqImpl;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationcontext.xml" })
public class TestQueue {
	@Autowired
	MqImpl mqImpl;

	final String queue_key = "test_queue_key";
	final String queue_key2 = "test_queue_key2";
	final String queue_key3 = "test_queue_key3";

	@Test
	public void send() {
		Map<String, String> msg = new HashMap<String, String>();
		msg.put("data", "hello,rabbmitmq!");
		System.out.println("--+amqpTemplate");

		for (int i = 0; i < 200; i++) {
			
			mqImpl.sendDataToQueue(queue_key, msg);
		}

		System.out.println("------------------");
	}
}

可以登录localhost:5672/看交换器和queue的效果

猜你喜欢

转载自my.oschina.net/u/3647713/blog/1577321