RabbitMQ 消息中间件

基本概念

RabbitMQ是流行的开源消息队列系统,用erlang语言开发。RabbitMQ是AMQP(高级消息队列协议)的标准实现.AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

RabbitMQ主要是为了实现系统之间的双向解耦而实现的。当生产者大量产生数据时,消费者无法快速消费,那么需要一个中间层。保存这个数据。

通常我们谈到队列服务, 会有三个概念: 发消息者、队列、收消息者,RabbitMQ 在这个基本概念之上, 多做了一层抽象, 在发消息者和 队列之间, 加入了交换器 (Exchange). 这样发消息者和队列就没有直接联系, 转而变成发消息者把消息给交换器, 交换器根据调度策略再把消息再给队列。

RabbitMQ几个重要的结构概念:

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

消息队列的使用过程大概如下:

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

exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。

exchange交换机有四种类型:Direct, topic, Headers and Fanout

  • Direct:direct 类型的行为是"先匹配, 再投送". 即在绑定时设定一个 routing_key, 消息的routing_key 匹配时, 才会被交换器投送到绑定的队列中去.Direct Exchange是RabbitMQ默认的交换机模式,也是最简单的模式,根据key全文匹配去寻找队列。

  • Topic:按规则转发消息(最灵活)

    topic 和 direct 类似, 只是匹配上支持了"模式", 在"点分"的 routing_key 形式中, 可以使用两个通配符:*表示一个词. #表示零个或多个词.

  • Headers:设置header attribute参数类型的交换机。headers 也是根据规则匹配, 相较于 direct 和 topic 固定地使用 routing_key , headers 则是一个自定义匹配规则的类型.
    在队列与交换器绑定时, 会设定一组键值对规则, 消息中也包括一组键值对( headers 属性), 当这些键值对有一对, 或全部匹配时, 消息被投送到对应队列.

  • Fanout:转发消息到所有绑定队列,Fanout Exchange 消息广播的模式,不管路由键或者是路由模式,会把消息发给绑定给它的全部队列,如果配置了routing_key会被忽略。

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

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

理论知识有个大概的了解后我们来安装rabbitmq

先下载erlang:http://www.erlang.org/download.html

再下载rabbitmq: http://www.rabbitmq.com/install-windows.html

安装这里就不多介绍了

注意出现错误:ERROR: node with name "rabbit" already running on  说明服务已经运行了

只要开启插件就可以了,命令行输入:

D:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.5\sbin>rabbitmq-plugins.bat enable rabbitmq_management
The following plugins have been enabled:
  mochiweb
  webmachine
  rabbitmq_web_dispatch
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management

Applying plugin configuration to rabbit@xxx-PC... started 6 plugins.

验证是否安装成功

通过访问http://localhost:15672进行测试,默认的登陆账号为:guest,密码为:guest。

我们弄几个小demo测试验证下rabbitmq的机制

生产者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.Queue.DeclareOk;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * 
 * 生产者
 *
 */
public class ProducerTest {
	
	private static String host="127.0.0.1";
	private static int port=5672;
//	private static String username="guest";
//	private static String password="guest";
	
	
	public static void main(String[] args) throws IOException, TimeoutException{
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost(host);
//		connectionFactory.setPort(port);;
//		connectionFactory.setUsername(username);
//		connectionFactory.setPassword(password);
		Connection connection = connectionFactory.newConnection();
		Channel channel = connection.createChannel();
		/**
		 * 创建队列
		 *  
		 * queue表示队列名称
		 * durable是否持久化(true表示是,队列将在服务器重启时生存)
		 * exclusive是否是独占队列(创建者可以使用的私有队列,断开后自动删除)
		 * autoDelete当所有消费者客户端连接断开时是否自动删除队列
		 * arguments 队列的其他参数
		 */
		DeclareOk queueDeclare = channel.queueDeclare("test", false,false, false, null);
		String message="hello rabbitmq!";
		/**
		 * 发送消息到队列
		 * 
		 * exchange 交换机名称
		 * routingKey队列映射的路由key
		 * props消息的其他属性
		 * body发送信息的主体
		 */
		channel.basicPublish("", "test", null, message.getBytes("UTF-8"));
		System.out.println("producer send "+message);
		 
        channel.close();
        connection.close();

	}
}

消费者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.AMQP.Queue.DeclareOk;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.ShutdownSignalException;

/**
 * 
 * 消费者
 */
public class ConsumerTest {
	
	private static String host="localhost";
	private static int port=5672;
	private static String username="guest";
	private static String password="guest";
	
	
	public static void main(String[] args) throws IOException, TimeoutException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost(host);
//		connectionFactory.setPort(port);;
//		connectionFactory.setUsername(username);
//		connectionFactory.setPassword(password);
		Connection connection = connectionFactory.newConnection();
		Channel channel = connection.createChannel();
		/**
		 * 关注的队列 
		 * queue表示队列名称
		 * durable是否持久化(true表示是,队列将在服务器重启时生存)
		 * exclusive是否是独占队列(创建者可以使用的私有队列,断开后自动删除)
		 * autoDelete当所有消费者客户端连接断开时是否自动删除队列
		 * arguments 队列的其他参数
		 */
		DeclareOk queueDeclare = channel.queueDeclare("test", false,false, false, null);
		System.out.println("========consumer wait received message================");
		

//      //接收message方式一:
//      //DefaultConsumer类实现了Consumer接口,传入一个通道,如果通道中有消息,就会执行回调函数handleDelivery  delivery:传送,投递
//      DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
//          @Override
//          public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//              System.out.println(new String(body,"UTF-8"));
//          }
//      };
//      //自动回复队列应答 -- RabbitMQ中的消息确认机制
//      channel.basicConsume("test", true, defaultConsumer);

      //接收message方式二:
      QueueingConsumer queueingConsumer = new QueueingConsumer(channel);//QueueingConsumer extends DefaultConsumer
      channel.basicConsume("test",true,queueingConsumer);
      while(true){//一直执行,获取Delivery传递对象
          QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
          System.out.println(new String(delivery.getBody(),"UTF-8"));
      }

	}

}

运行后页面控制台会展示为

d187f82432a7f774fa146310b441a168ef0.jpg

实现多任务分发

生产者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

/**
 * 实现多任务分发
 *
 */
public class MoreTask {

	private static final String TASK_QUEUE_NAME = "task_queue";

	public static void main(String[] args) throws IOException, TimeoutException {
		ConnectionFactory factory = new ConnectionFactory();
		factory.setHost("localhost");
		Connection connection = factory.newConnection();
		Channel channel = connection.createChannel();
		channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
		// 分发信息
		for (int i = 0; i < 10; i++) {
			String message = "Hello RabbitMQ " + i;
			channel.basicPublish("", TASK_QUEUE_NAME,MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
			System.out.println("task send '" + message + "'");
		}
		channel.close();
		connection.close();
	}
}

分发不同的任务

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

/**
 * 实现多任务分发
 *
 */
public class Work1 {
	private static final String TASK_QUEUE_NAME = "task_queue";

	public static void main(String[] args) throws IOException, TimeoutException {
		final  ConnectionFactory factory = new ConnectionFactory();
		factory.setHost("localhost");
		Connection connection = factory.newConnection();
		final Channel channel = connection.createChannel();
		channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);

		System.out.println("Worker1  Waiting for messages");

		// 每次从队列获取的数量
		channel.basicQos(1);

		final Consumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope,
					AMQP.BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("Worker1  Received '" + message + "'");

			}
		};

		channel.basicConsume(TASK_QUEUE_NAME, true, consumer);

	}


}
import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;


/**
 * 实现多任务分发
 *
 */
public class Work2 {

	private static final String TASK_QUEUE_NAME = "task_queue";

	public static void main(String[] args) throws IOException, TimeoutException {
		ConnectionFactory factory = new ConnectionFactory();
		factory.setHost("localhost");
		Connection connection = factory.newConnection();
		final Channel channel = connection.createChannel();
		channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);

		System.out.println("Worker1  Waiting for messages");

		// 每次从队列获取的数量
		channel.basicQos(1);

		final Consumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope,
					AMQP.BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("Worker2  Received '" + message + "'");
			}
		};

		channel.basicConsume(TASK_QUEUE_NAME, true, consumer);

	}

}

验证结果

task send 'Hello RabbitMQ 0'
task send 'Hello RabbitMQ 1'
task send 'Hello RabbitMQ 2'
task send 'Hello RabbitMQ 3'
task send 'Hello RabbitMQ 4'
task send 'Hello RabbitMQ 5'
task send 'Hello RabbitMQ 6'
task send 'Hello RabbitMQ 7'
task send 'Hello RabbitMQ 8'
task send 'Hello RabbitMQ 9'

Worker1  Waiting for messages
Worker1  Received 'Hello RabbitMQ 0'
Worker1  Received 'Hello RabbitMQ 2'
Worker1  Received 'Hello RabbitMQ 4'
Worker1  Received 'Hello RabbitMQ 6'
Worker1  Received 'Hello RabbitMQ 8'

Worker1  Waiting for messages
Worker2  Received 'Hello RabbitMQ 1'
Worker2  Received 'Hello RabbitMQ 3'
Worker2  Received 'Hello RabbitMQ 5'
Worker2  Received 'Hello RabbitMQ 7'
Worker2  Received 'Hello RabbitMQ 9'

817e79d3a5f7412c533b7a0710de362c103.jpg

 

发布与订阅

订阅者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

/**
 * 
 * 订阅者
 */
public class Subscribe {

	private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
       final Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");

        //产生一个随机的队列名称
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, EXCHANGE_NAME, "");//对队列进行绑定

        System.out.println("Subscribe2 Waiting for messages");
        final Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("Subscribe2 Received '" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);//队列会自动删除
    }

}

发布者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;


/**
 * 发布者
 *
 */
public class Publish {
	
	private static final String EXCHANGE_NAME = "logs";
	
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory=new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection=factory.newConnection();
        Channel channel=connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");//fanout表示分发,所有的消费者得到同样的队列信息
        //分发信息
        for (int i=0;i<5;i++){
            String message="Hello World"+i;
            channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes());
            System.out.println("Publish Sent '" + message + "'");
        }
        channel.close();
        connection.close();
    }
}

 

验证结果:

Publish Sent 'Hello World0'
Publish Sent 'Hello World1'
Publish Sent 'Hello World2'
Publish Sent 'Hello World3'
Publish Sent 'Hello World4'

Subscribe1 Waiting for messages
Subscribe1 Received 'Hello World0'
Subscribe1 Received 'Hello World1'
Subscribe1 Received 'Hello World2'
Subscribe1 Received 'Hello World3'
Subscribe1 Received 'Hello World4'

Subscribe2 Waiting for messages
Subscribe2 Received 'Hello World0'
Subscribe2 Received 'Hello World1'
Subscribe2 Received 'Hello World2'
Subscribe2 Received 'Hello World3'
Subscribe2 Received 'Hello World4'

3f77394cc6b8bf33db942581502be8f56df.jpg

 

通过多个路由key 来实现交换机的不同分发

发送端代码

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;


public class RoutingSendDirect {

	private static final String EXCHANGE_NAME = "direct_logs";
	
    // 路由关键字
    private static final String[] routingKeys = new String[]{"info" ,"warning", "error"};
    
    
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");//注意是direct
        //发送信息
        for (String routingKey:routingKeys){
            String message = "RoutingSendDirect Send the message level:" + routingKey;
            channel.basicPublish(EXCHANGE_NAME,routingKey,null,message.getBytes());
            System.out.println("RoutingSendDirect Send"+routingKey +"':'" + message);
        }
        channel.close();
        connection.close();
    }

}

消费者1


import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class ReceiveLogsDirect1 {
	// 交换器名称
    private static final String EXCHANGE_NAME = "direct_logs";
    
    // 路由关键字
    private static final String[] routingKeys = new String[]{"info" ,"warning"};

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换器
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        //获取匿名队列名称
        String queueName=channel.queueDeclare().getQueue();

        //根据路由关键字进行绑定
        for (String routingKey:routingKeys){
            channel.queueBind(queueName,EXCHANGE_NAME,routingKey);
            System.out.println("ReceiveLogsDirect1 exchange:"+EXCHANGE_NAME+"," +
                    " queue:"+queueName+", BindRoutingKey:" + routingKey);
        }
        
        System.out.println("ReceiveLogsDirect1  Waiting for messages");
        
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("ReceiveLogsDirect1 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        
        channel.basicConsume(queueName, true, consumer);
    }

}

消费者2

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;


public class ReceiveLogsDirect2 {
	
	// 交换器名称
    private static final String EXCHANGE_NAME = "direct_logs";
    // 路由关键字
    private static final String[] routingKeys = new String[]{"error"};

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换器
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        //获取匿名队列名称
        String queueName = channel.queueDeclare().getQueue();
        //根据路由关键字进行多重绑定
        for (String severity : routingKeys) {
            channel.queueBind(queueName, EXCHANGE_NAME, severity);
            System.out.println("ReceiveLogsDirect2 exchange:"+EXCHANGE_NAME+", queue:"+queueName+", BindRoutingKey:" + severity);
        }
        
        System.out.println("ReceiveLogsDirect2 Waiting for messages");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws UnsupportedEncodingException {
                String message = new String(body, "UTF-8");
                System.out.println("ReceiveLogsDirect2 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }


}

运行结果:


RoutingSendDirect Sendinfo':'RoutingSendDirect Send the message level:info
RoutingSendDirect Sendwarning':'RoutingSendDirect Send the message level:warning
RoutingSendDirect Senderror':'RoutingSendDirect Send the message level:error

ReceiveLogsDirect1 Received 'info':'RoutingSendDirect Send the message level:info'
ReceiveLogsDirect1 Received 'warning':'RoutingSendDirect Send the message level:warning'

ReceiveLogsDirect2 Received 'error':'RoutingSendDirect Send the message level:error'

98b32a746b94ca478e17c5b6cf28ca5a106.jpg

 

Topics模糊匹配

* :可以替代一个词

#:可以替代0或者更多的词

发送者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class TopicSend {
	private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = null;
        Channel channel = null;
        try{
            ConnectionFactory factory=new ConnectionFactory();
            factory.setHost("localhost");
            connection=factory.newConnection();
            channel=connection.createChannel();

            //声明一个匹配模式的交换机
            channel.exchangeDeclare(EXCHANGE_NAME,"topic");
            //待发送的消息
            String[] routingKeys=new String[]{
                    "quick.orange.rabbit",
                    "lazy.orange.elephant",
                    "quick.orange.fox",
                    "lazy.brown.fox",
                    "quick.brown.fox",
                    "quick.orange.male.rabbit",
                    "lazy.orange.male.rabbit"
            };
            //发送消息
            for(String severity :routingKeys){
                String message = "From "+severity+" routingKey' s message!";
                channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
                System.out.println("TopicSend Sent '" + severity + "':'" + message + "'");
            }
        }catch (Exception e){
            e.printStackTrace();
            if (connection!=null){
                channel.close();
                connection.close();
            }
        }finally {
            if (connection!=null){
                channel.close();
                connection.close();
            }
        }
    }
}

消费者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;


public class ReceiveLogsTopic1 {

	private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        //声明一个匹配模式的交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");
        String queueName = channel.queueDeclare().getQueue();
        //路由关键字
        String[] routingKeys = new String[]{"*.orange.*"};
        //绑定路由
        for (String routingKey : routingKeys) {
            channel.queueBind(queueName, EXCHANGE_NAME, routingKey);
            System.out.println("ReceiveLogsTopic1 exchange:" + EXCHANGE_NAME + ", queue:" + queueName + ", BindRoutingKey:" + routingKey);
        }
        System.out.println("ReceiveLogsTopic1 Waiting for messages");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("ReceiveLogsTopic1 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }

}

消费者

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class ReceiveLogsTopic2 {

	private static final String EXCHANGE_NAME = "topic_logs";

	public static void main(String[] argv) throws IOException, TimeoutException {
		ConnectionFactory factory = new ConnectionFactory();
		factory.setHost("localhost");
		Connection connection = factory.newConnection();
		Channel channel = connection.createChannel();
		// 声明一个匹配模式的交换器
		channel.exchangeDeclare(EXCHANGE_NAME, "topic");
		String queueName = channel.queueDeclare().getQueue();
		// 路由关键字
		String[] routingKeys = new String[] { "*.*.rabbit", "lazy.#" };
		// 绑定路由关键字
		for (String bindingKey : routingKeys) {
			channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
			System.out.println("ReceiveLogsTopic2 exchange:" + EXCHANGE_NAME
							+ ", queue:" + queueName + ", BindRoutingKey:"
							+ bindingKey);
		}

		System.out.println("ReceiveLogsTopic2 Waiting for messages");

		Consumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope,
					AMQP.BasicProperties properties, byte[] body)
					throws UnsupportedEncodingException {
				String message = new String(body, "UTF-8");
				System.out.println("ReceiveLogsTopic2 Received '"+ envelope.getRoutingKey() + "':'" + message + "'");
			}
		};
		channel.basicConsume(queueName, true, consumer);
	}

}

测试结果:

TopicSend Sent 'quick.orange.rabbit':'From quick.orange.rabbit routingKey' s message!'
TopicSend Sent 'lazy.orange.elephant':'From lazy.orange.elephant routingKey' s message!'
TopicSend Sent 'quick.orange.fox':'From quick.orange.fox routingKey' s message!'
TopicSend Sent 'lazy.brown.fox':'From lazy.brown.fox routingKey' s message!'
TopicSend Sent 'quick.brown.fox':'From quick.brown.fox routingKey' s message!'
TopicSend Sent 'quick.orange.male.rabbit':'From quick.orange.male.rabbit routingKey' s message!'
TopicSend Sent 'lazy.orange.male.rabbit':'From lazy.orange.male.rabbit routingKey' s message!'


ReceiveLogsTopic1 exchange:topic_logs, queue:amq.gen-9wNDsKnUVA0Z43iL-feEhA, BindRoutingKey:*.orange.*
ReceiveLogsTopic1 Waiting for messages
ReceiveLogsTopic1 Received 'quick.orange.rabbit':'From quick.orange.rabbit routingKey' s message!'
ReceiveLogsTopic1 Received 'lazy.orange.elephant':'From lazy.orange.elephant routingKey' s message!'
ReceiveLogsTopic1 Received 'quick.orange.fox':'From quick.orange.fox routingKey' s message!'

ReceiveLogsTopic2 exchange:topic_logs, queue:amq.gen-TpWQo52Q4Ve123mMGRlIlw, BindRoutingKey:*.*.rabbit
ReceiveLogsTopic2 exchange:topic_logs, queue:amq.gen-TpWQo52Q4Ve123mMGRlIlw, BindRoutingKey:lazy.#
ReceiveLogsTopic2 Waiting for messages
ReceiveLogsTopic2 Received 'quick.orange.rabbit':'From quick.orange.rabbit routingKey' s message!'
ReceiveLogsTopic2 Received 'lazy.orange.elephant':'From lazy.orange.elephant routingKey' s message!'
ReceiveLogsTopic2 Received 'lazy.brown.fox':'From lazy.brown.fox routingKey' s message!'
ReceiveLogsTopic2 Received 'lazy.orange.male.rabbit':'From lazy.orange.male.rabbit routingKey' s message!'

86fdb028d2e082e0f8cafa69e5e1271bc78.jpg

 

 

转载于:https://my.oschina.net/saulc/blog/3009332

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值