RabbitMQ的使用

RabbitMQ的使用

制作人:全心全意

RabbitMQ简介

MQ全称为Message Queue(消息队列),是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息来通信,而无需专用连接来链接它们。消息队列指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。

RabbitMQ是一个在AMQP基础上完成的,可复用的企业消息系统。遵循Mozilla Public License开源协议。
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品、不同的开发语言等条件的限制。

RabbitMQ基于Erlang实现

RabbitMQ优点
  性能很好,延时低
  吞吐量到万级,功能完备
  有良好的的管理界面和管理工具
  社区相对比较活跃
RabbitMQ缺点
  吞吐量相对低

 

安装RabbitMQ

#1.安装erlang solution
erlang官网:http://erlang.org
wget https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
yum -y install epel-release
rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
yum -y install erlang

#2.安装rabbit
yum -y install rabbitmq-server		#出错

#=====源码安装
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.8/rabbitmq-server-generic-unix-3.7.8.tar.xz
tar -xvf rabbitmq-server-generic-unix-3.7.8.tar.xz -C /usr/local/
vim /etc/profile
source /etc/profile
rabbitmq-plugins enable rabbitmq_management		
rabbitmq-server -detached		#后台启动

#3.开启rabbitmq的远程访问
vi /etc/rabbitmq/rabbitmq.config
[{rabbit,[{loopback_users,[]}]}]		//添加该行,新版本不需要,直接进行第4部

#4.开启web管理端访问(非必须,需先开启允许远程访问)
rabbitmq-plugins enable rabbitmq_management

#5.安装消息延迟插件
cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.3.5/plugins
wget https://dl.bintray.com/rabbitmq/community-plugins/rabbitmq_delayed_message_exchange-0.0.1.ez
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

#6.放行端口或关闭防火墙
firewalld-cmd --add-port=15672/tcp --permanent
firewalld-cmd --add-port=5672/tcp --permanent

#7.启动
service rabbitmq-server start

service rabbitmq-server restart

  

地址:http://IP:15672
默认用户名密码:guest

 

账户级别

  超级管理员:administrator,可以登录控制台,查看所有信息,可以对用户和策略进行操作。
  监控者:monitoring,可以登录控制台,可以查看节点的相关信息,比如进程数、内存和磁盘的使用情况。
  策略制定者:policymaker,可以登录控制台,指定策略,但是无法查看节点信息。
  普通管理员:management,仅能登录控制台。
  其他:无法登录控制台,一般指提供者和消费者。

  添加账号命令:(还可通过web页面进行管理)
    rabbitmqctl adduser zhangsan mima123 #添加zhangsan用户,密码为mima123
    rabbitmqctl set_user_tags zhangsan administrator #设置zhangsan用户为administrator级别

 

消息种类

  网址:https://www.rabbitmq.com/getstarted.html
  “Hello World!”:一个生产者对应一个消费者
  Work queues:一个生产者对应多个消费者
  Publish/Subscribe:引入交换机概念,生产者将消息发入交换机,由交换机分配到不同队列,不同队列对应不同消费者,两个消费者都能接收到消息(交换机类型:fanout)
  Routing:根据关键字(单词)发送到指定队列(交换机类型:direct)
  Topics:根据关键字(单词)发送到指定队列,允许使用通配符*和#号(*:任意一个单词,#:任意多个单词,关键词包含多个单词使用.分隔,例如:www.zhang)(交换机类型:topic)
  RPC:同步请求(有一些情况需要等待返回,不能异步),生产者发送消息指定唯一ID和返回结果的消息队列,生产者从返回消息队列中取得返回结果。

 

 

JAVA调用示例

工具类:

package zq5;

import org.apache.log4j.Logger;

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

public class ConnectionUtil {
	private static Logger logger = Logger.getLogger(ConnectionUtil.class);

	public static Connection getConnection() {
		try {
			Connection connection = null;
			// 定义一个连接工厂
			ConnectionFactory factory = new ConnectionFactory();
			// 设置服务端地址(域名地址/ip)
			factory.setHost("172.16.1.12");
			// 设置服务器端口号
			factory.setPort(5673);
			// 设置虚拟主机(相当于数据库中的库)
			factory.setVirtualHost("/zhangsan");
			// 设置用户名
			factory.setUsername("zhangsan");
			// 设置密码
			factory.setPassword("123456");
			connection = factory.newConnection();
			return connection;
		} catch (Exception e) {
			return null;
		}
	}
}

  

“Hello World!”演示:

Send类

package zq;

import java.io.IOException;

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

public class Send {
	private final static String QUEUE_NAME = "queue_hello";

	public static void main(String[] args) throws Exception {
		// 获取链接
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		Channel channel = connection.createChannel();

		/**
		 * 1:队列名称 2:是否持久化 3:是否独占模式 4:是否自动删除队列中的消息 5:其它额外参数
		 */
		// 创建队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		String message = "Hello World!";

		/**
		 * 1:交换机名 2:队列名 3:BasicProperties 4:消息字节数组
		 */
		// 发送消息
		channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
		System.out.println("发送:'" + message + "'");
		// 关闭链接
		channel.close();
		connection.close();
	}

}

  

Recv类:

package zq;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv {
	private final static String QUEUE_NAME = "queue_hello";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		Channel channel = connection.createChannel();

		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties,
					byte[] body) {
				String mess = new String(body);
				System.out.println("接收到的消息为:" + mess);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, true, consumer);
	}

}

  

Work queues演示

Send类:

package zq1;

import java.io.IOException;

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

public class Send {
	private final static String QUEUE_NAME = "queue_work";

	public static void main(String[] args) throws Exception {
		// 获取链接
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		Channel channel = connection.createChannel();

		/**
		 * 1:队列名称 2:是否持久化 3:是否独占模式 4:是否自动删除队列中的消息 5:其它额外参数
		 */
		// 创建队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		for (int i = 0; i < 20; i++) {
			String message = i + "queue_work";
			channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
			System.out.println("发送:'" + message + "'");
		}

		/**
		 * 1:交换机名 2:队列名 3:BasicProperties 4:消息字节数组
		 */
		// 发送消息

		// 关闭链接
		channel.close();
		connection.close();
	}

}

  

Recv类:

package zq1;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv {
	private final static String QUEUE_NAME = "queue_work";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		channel.basicQos(1);

		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties,
					byte[] body) throws IOException{
				String mess = new String(body);
				System.out.println("1接收到的消息为:" + mess);
				try {
					Thread.sleep(1000);

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

Recv1类:

package zq1;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;

import zq2.ConnectionUtil;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv1 {
	private final static String QUEUE_NAME = "queue_work";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		// 消费者预取的消费数量
		channel.basicQos(1); // 没处理完1条消息,不会接收新的消息
		// (不使用默认是轮循,使用此项会根据机器处理速度来分配)

		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String mess = new String(body);
				System.out.println("2接收到的消息为:" + mess);
				try {
					Thread.sleep(200);

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// 手动返回回执确认
				/**
				 * 1:回执确认消息的编号 2:是否批量确认,一般为false,不批量确认
				 */
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

Publish/Subscribe演示

Send类:

package zq2;

import java.io.IOException;

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

public class Send {
	private final static String EXCHANGE_NAME = "exchange_fanout";

	public static void main(String[] args) throws Exception {
		// 获取链接
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		Channel channel = connection.createChannel();

		// 声明exchange(交换机存在直接使用,不存在会创建)
		// 注意:在消费者没有启动的情况下,发送的消息会丢失
		channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
		/**
		 * 交换机类型 fanout
		 */

		// 消息内容
		String message = "Publish/Subscrib";
		channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
		System.out.println("发送:" + message);

		/**
		 * 1:交换机名 2:队列名 3:BasicProperties 4:消息字节数组
		 */

		// 关闭链接
		channel.close();
		connection.close();
	}

}

  

Recv类:

package zq2;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv {
	private final static String QUEUE_NAME = "queue_fanout1";

	private final static String EXCHANGE_NAME = "exchange_fanout";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		// 声明队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		// 绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");

		// 声明消费者预取的消息数量
		channel.basicQos(1);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String mess = new String(body);
				System.out.println("1接收到的消息为:" + mess);
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

Recv1类:

package zq2;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;

import zq1.ConnectionUtil;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv1 {
	private final static String QUEUE_NAME = "queue_fanout2";
	private final static String EXCHANGE_NAME = "exchange_fanout";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		// 声明队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		// 绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");

		// 消费者预取的消费数量
		channel.basicQos(1);

		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String mess = new String(body);
				System.out.println("2接收到的消息为:" + mess);

				// 手动返回回执确认
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

Routing演示

Send类:

package zq3;

import java.io.IOException;

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

public class Send {
	private final static String EXCHANGE_NAME = "exchange_direct";

	public static void main(String[] args) throws Exception {
		// 获取链接
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		Channel channel = connection.createChannel();

		// 声明exchange(交换机存在直接使用,不存在会创建)
		// 注意:在消费者没有启动的情况下,发送的消息会丢失
		channel.exchangeDeclare(EXCHANGE_NAME, "direct");
		/**
		 * 交换机类型 direct
		 */

		// 消息内容
		// info和error为关键字,关键字可自定义
		String message = "Routing";
		channel.basicPublish(EXCHANGE_NAME, "zhangsan", null, message.getBytes());
		System.out.println("发送:" + message);

		/**
		 * 1:交换机名 2:队列名 3:BasicProperties 4:消息字节数组
		 */

		// 关闭链接
		channel.close();
		connection.close();
	}

}

  

Recv类:

package zq3;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv {
	private final static String QUEUE_NAME = "queue_direct1";

	private final static String EXCHANGE_NAME = "exchange_direct";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		// 声明队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		// 绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error");

		// 声明消费者预取的消息数量
		channel.basicQos(1);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String mess = new String(body);
				System.out.println("1接收到的消息为:" + mess);
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

Recv1类:

package zq3;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;

import zq1.ConnectionUtil;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv1 {
	private final static String QUEUE_NAME = "queue_direct2";
	private final static String EXCHANGE_NAME = "exchange_direct";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		// 声明队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		// 绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error");
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "info");
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "zhangsan");

		// 消费者预取的消费数量
		channel.basicQos(1);

		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String mess = new String(body);
				System.out.println("2接收到的消息为:" + mess);

				// 手动返回回执确认
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

Topics演示

Send类:

package zq4;

import java.io.IOException;

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

public class Send {
	private final static String EXCHANGE_NAME = "exchange_direct";

	public static void main(String[] args) throws Exception {
		// 获取链接
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		Channel channel = connection.createChannel();

		// 声明exchange(交换机存在直接使用,不存在会创建)
		// 注意:在消费者没有启动的情况下,发送的消息会丢失
		channel.exchangeDeclare(EXCHANGE_NAME, "topic");
		/**
		 * 交换机类型 direct
		 */

		// 消息内容
		// info和error为关键字,关键字可自定义
		String message = "Routing";
		channel.basicPublish(EXCHANGE_NAME, "zhangsan", null, message.getBytes());
		System.out.println("发送:" + message);

		/**
		 * 1:交换机名 2:队列名 3:BasicProperties 4:消息字节数组
		 */

		// 关闭链接
		channel.close();
		connection.close();
	}

}

  

Recv类:

package zq4;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv {
	private final static String QUEUE_NAME = "queue_direct1";

	private final static String EXCHANGE_NAME = "exchange_direct";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		// 声明队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		// 绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error");

		// 声明消费者预取的消息数量
		channel.basicQos(1);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String mess = new String(body);
				System.out.println("1接收到的消息为:" + mess);
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

Recv1类:

package zq4;

import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;

import zq1.ConnectionUtil;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Recv1 {
	private final static String QUEUE_NAME = "queue_direct2";
	private final static String EXCHANGE_NAME = "exchange_direct";

	public static void main(String[] args) throws Exception {
		// 获取到连接以及mq通道
		Connection connection = ConnectionUtil.getConnection();
		// 从链接中创建通道
		final Channel channel = connection.createChannel();

		// 声明队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		// 绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error");
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "info");
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "zhangsan");

		// 消费者预取的消费数量
		channel.basicQos(1);

		channel.queueDeclare(QUEUE_NAME, false, false, false, null);

		DefaultConsumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTage, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String mess = new String(body);
				System.out.println("2接收到的消息为:" + mess);

				// 手动返回回执确认
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		// 创建一个消费者(监听器)
		// 2:是否确认收到消息,手动确认需要加代码
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}

}

  

RPC演示

RpcServer类:

package zq5;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;

public class RpcServer {
	private static final String RPC_QUEUE_NAME = "rpc_queue";

	public static void main(String[] args) {
		Connection connection = null;
		try {
			connection = ConnectionUtil.getConnection();
			Channel channel = connection.createChannel();

			// 创建队列
			channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
			channel.basicQos(1);
			QueueingConsumer consumer = new QueueingConsumer(channel);
			// 消费者监听队列
			channel.basicConsume(RPC_QUEUE_NAME, false, consumer);
			while (true) {
				// 接收并处理消息
				QueueingConsumer.Delivery delivery = consumer.nextDelivery();
				String message = new String(delivery.getBody());
				System.out.println("服务端接收:" + message);

				// 确认收到消息
				channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);

				// 取出消息的correlationld
				AMQP.BasicProperties properties = delivery.getProperties();
				String correlationld = properties.getCorrelationId();

				// 创建具有与接收消息相同的correlationld的消息属性
				AMQP.BasicProperties replyProperties = new AMQP.BasicProperties().builder().correlationId(correlationld)
						.build();
				// properties.getReplyTo():获取回调队列名
				channel.basicPublish("", properties.getReplyTo(), replyProperties, "1111111".getBytes());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

  

RpcClient类:

package zq5;

import java.util.UUID;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;

public class RpcClient {
	private static final String RPC_QUEUE_NAME = "rpc_queue";

	public static void main(String[] args) {
		Connection connection = null;
		Channel channel = null;
		try {
			connection = ConnectionUtil.getConnection();
			channel = connection.createChannel();
			// 创建回调队列
			String callbackQueue = channel.queueDeclare().getQueue();

			// 消费者从回调队列中接收服务端传送的消息
			QueueingConsumer consumer = new QueueingConsumer(channel);
			// 监听队列
			channel.basicConsume(callbackQueue, true, consumer);

			// 创建带有correlationld的消息属性
			String correlationld = UUID.randomUUID().toString();
			AMQP.BasicProperties basicProperties = new AMQP.BasicProperties().builder().correlationId(correlationld)
					.replyTo(callbackQueue).build();
			String message = "hello rabbitmq rpc";
			channel.basicPublish("", RPC_QUEUE_NAME, basicProperties, message.getBytes());
			System.out.println("客户端发送的消息:" + message + ",correaltionld=" + correlationld);

			// 接收回调消息
			while (true) {
				QueueingConsumer.Delivery delivery = consumer.nextDelivery();
				String receivedCorrelationld = delivery.getProperties().getCorrelationId();
				if (correlationld.equals(receivedCorrelationld)) {
					System.out.println(
							"客户端接收的回调消息:" + new String(delivery.getBody()) + ",conrrealtionld=" + correlationld);
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

  

 SpringBoot集成RabbitMQ

引入依赖

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-amqp</artifactId>
	</dependency>

  

配置:application.properties

	server.port = 8082
	spring.application.name=spring-boot-rabbitmq
	spring.rabbitmq.host=172.16.1.1
	spring.rabbitmq.port=5672
	spring.rabbitmq.virtual-host=/zhangsan
	spring.rabbitmq.username=admin
	spring.rabbitmq.password=123456

  

RabbitmqConfig类(实例化):

package zq6;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitmqConfig {
	public static final String QUEUE_T = "test_q";
		
	@Bean(QUEUE_T)
	public Queue QUEUE_T() {
		Queue queue = new Queue(QUEUE_T);
		return queue;
	}
}

  

HelloReceiver类(消费者):

package zq6;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = "test_q") // 指定监听序列
public class HelloReceiver {

	@RabbitHandler
	public void process(String hello) {
		System.out.println("Receiver:" + hello);
	}
}

  

HelloSender(生产者):

package zq6;

import java.text.SimpleDateFormat;
import java.util.Date;

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

@Component
public class HelloSender {
	@Autowired
	private AmqpTemplate rabbitTemplate;

	public void send() {
		String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
		String context = "hello" + date;
		System.out.println("Send:" + context);
		this.rabbitTemplate.convertAndSend("test_q",context);
	}
}

  

App类(启动类):

package zq6;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}

  

测试类:

package zq6;


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import zq6.HelloSender;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitMqHelloTest {
	@Autowired
	private HelloSender helloSender;
	
	@Test
	public void hello()throws Exception{
		helloSender.send();
	}
}

  

测试类的依赖:

	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
	</dependency>

  

 

posted @ 2021-04-07 10:00  全心全意_运维  阅读(134)  评论(0编辑  收藏  举报