RabbitMq
消息中间件
1、安装
- docker pull rabbitmq:3.7.7-management
- docker run -d --name rabbitmq3.7.7 -p 5672:5672 -p 15672:15672 --hostname myRabbitmq rabbitmq:3.7.7-management
用户管理界面为:ip:15672 用户名密码为guest
2、RabbitMq模型
7种
3、第一种模型-HelloWorld
1)、准备
- 创建用户:用户名、密码、确认密码、权限
- 创建虚拟主机
- 为用户绑定虚拟主机
2)、导入pom依赖
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.9.0</version>
</dependency>
3)、编写生产者
@Test
public void testSend() throws IOException, TimeoutException {
Connection connection = null;
Channel channel = null;
try{
connection = RabbitmqUtil.getConnection();
channel = connection.createChannel();
channel.queueDeclare("helloworldqueue1",false,false,false,null);
//发布消息
//参数1:交换机名称
//参数2:队列名称
//参数3:额外参数
//参数4:消息内容
channel.basicPublish("","helloworldqueue1",MessageProperties.PERSISTENT_TEXT_PLAIN,"hello rabbitmq!".getBytes());
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭通道,关闭连接
RabbitmqUtil.close(channel,connection);
}
}
效果:
4)、编写消费者
public static void main(String[] args) throws IOException {
final Channel channel;
Connection connection;
try{
connection = RabbitmqUtil.getConnection();
channel = connection.createChannel();
channel.basicConsume("helloworldqueue1",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}catch (Exception e){
e.printStackTrace();
}finally {
//RabbitmqUtil.close(channel,connection);
}
}
5)、工具类如下
public class RabbitmqUtil {
private static Connection connection;
static{
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("119.29.228.75");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/helloworld");
connectionFactory.setUsername("helloworld");
connectionFactory.setPassword("123");
try {
//获取连接
connection = connectionFactory.newConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
return connection;
}
public static void close(Channel channel,Connection connection){
try{
if(channel != null)
channel.close();
if(connection != null)
connection.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
4、第二种模型-Work Queues
一个生产者,多个消费者。
- 消费者循环处理消息。
会有问题,处理的慢的消费者,会拖慢整体速度。
如何做成能者多劳?
消费者如下
public static void main(String[] args) throws IOException {
final Channel channel;
Connection connection;
try{
connection = RabbitmqUtil.getConnection();
channel = connection.createChannel();
channel.basicQos(1);
channel.basicConsume("helloworldqueue1",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}catch (Exception e){
e.printStackTrace();
}finally {
//RabbitmqUtil.close(channel);
}
}
关键点:
- channel.basicQos(1); 设置每次只拿一个消息
- channel.basicConsume(“helloworldqueue1”,false,new DefaultConsumer(channel){…}) 第二个参数false,关闭自动确认消息已经消费完成
- channel.basicAck(envelope.getDeliveryTag(),false); 手动确认消息已经消费完成,队列中移除该消息
5、第三种模型-广播模型
生产者----交换机----(多个(队列 + 消费者))
- 每个消费者都会获得每一条消息
1)、生产者
@Test
public void test(){
Connection connection = null;
Channel channel = null;
try{
connection = RabbitmqUtil.getConnection();
channel = connection.createChannel();
//绑定交换机 参数1:交换机名字 没有会自动创建 参数2:类型(fanout固定为广播类型)
channel.exchangeDeclare("ex1","fanout");
//发布消息
//参数1:交换机名称
//参数2:队列名称
//参数3:额外参数
//参数4:消息内容
for (int i = 0; i < 10; i++) {
channel.basicPublish("ex1","",null,(i + "fanout message!").getBytes());
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭通道,关闭连接
RabbitmqUtil.close(channel,connection);
}
}
2)、消费者
public static void main(String[] args) {
Connection connection = null;
Channel channel = null;
try{
connection = RabbitmqUtil.getConnection();
channel = connection.createChannel();
//绑定交换机 参数1:交换机名字 没有会自动创建 参数2:类型(fanout固定为广播类型)
channel.exchangeDeclare("ex1","fanout");
//创建临时队列,拿到名字
String queue = channel.queueDeclare().getQueue();
//绑定交换机和队列
channel.queueBind(queue,"ex1","");
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1-" + new String(body));
}
});
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭通道,关闭连接
//RabbitmqUtil.close(channel,connection);
}
}
public static void main(String[] args) {
Connection connection = null;
Channel channel = null;
try{
connection = RabbitmqUtil.getConnection();
channel = connection.createChannel();
//绑定交换机 参数1:交换机名字 没有会自动创建 参数2:类型(fanout固定为广播类型)
channel.exchangeDeclare("ex1","fanout");
//创建临时队列,拿到名字
String queue = channel.queueDeclare().getQueue();
//绑定交换机和队列
channel.queueBind(queue,"ex1","");
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2-" + new String(body));
}
});
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭通道,关闭连接
//RabbitmqUtil.close(channel,connection);
}
}
结果:
6、SpringBoot集成RabbitMq
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
编写配置文件
spring:
application:
name: springboot_rabbitmq
rabbitmq:
host: 119.29.228.75
port: 5672
username: demo
password: 123
virtual-host: /demo
6.1、hello world模型
编写生产者
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
rabbitTemplate.convertAndSend("demo01","demo01string");
}
编写消费者
//注册组件
@Component
//接收demo01队列的消息
@RabbitListener(queuesToDeclare = @Queue(value = "demo01",durable = "false",autoDelete = "true"))
public class MyCustomer {
@RabbitHandler
public void recieve01(String message){
System.out.println("message:" + message);
}
}
6.2、work queue模型
生产者
@Test
void testWork(){
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("work","workMessage" + i);
}
}
消费者
@Component
public class WorkCustomer {
@RabbitListener(queuesToDeclare = @Queue("work"))
public void recieve01(String message){
System.out.println("recieve01 message:" + message);
}
@RabbitListener(queuesToDeclare = @Queue("work"))
public void recieve02(String message){
System.out.println("recieve02 message:" + message);
}
}
6.3、fanout模型
生产者
@Test
void testFanout(){
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("logs","","fanout消息" + i);
}
}
消费者
@Component
public class FanoutCustomer {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//绑定临时队列
exchange = @Exchange(type = "fanout",value = "logs")//绑定交换机
)
})
public void recieve01(String message){
System.out.println("message1: " + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//绑定临时队列
exchange = @Exchange(type = "fanout",value = "logs")//绑定交换机
)
})
public void recieve02(String message){
System.out.println("message2: " + message);
}
}
6.4、Route模型
生产者
@Test
void testRoute(){
for (int i = 0; i < 10; i++) {
//debug : 路由key
rabbitTemplate.convertAndSend("routeEx","debug","Route消息" + i);
}
}
消费者
@Component
public class RouteCustomer {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "routeEx",type = "direct"),
key = {"error","info"}//指定接收哪些路由key的消息
)
})
public void receive01(String message){
System.out.println("message1:" + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "routeEx",type = "direct"),
key = {"debug"}
)
})
public void receive02(String message){
System.out.println("message2:" + message);
}
}
6.5、Topic动态路由模式
动态路由的路由key:
- *代表一个
- #代表任意个(包括0)
- eg:
*.user.*
user.#
生产者
@Test
void testTopic(){
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("topicEx","org.user.like","Topic消息" + i);
}
}
消费者
@Component
public class TopicCustomer {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "topicEx",type = "topic"),
key = {"#.user.#"}
)
})
public void recieve01(String message){
System.out.println("message1: " + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "topicEx",type = "topic"),
key = {"*.user.*"}
)
})
public void recieve02(String message){
System.out.println("message2: " + message);
}
}
7、MQ的应用场景
7.1、异步处理
串行、并行
消息队列
7.2、应用解耦
订单系统调用库存系统接口
订单系统发消息,库存系统消费
7.3、流量削峰
用户请求->消息中间件->秒杀场景
8、集群
https://www.cnblogs.com/yeyongjian/p/13234354.html