rabbitmq 五种模型

maven坐标

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.7.2</version>
</dependency>

在这里插入图片描述

简单的工具类


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

/**
 * @Author: czn
 * @Date 2021/2/6 14:46
 */
public class RabbitMQUtils {

    private static ConnectionFactory connectionFactory;

    static {
        connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.174.134");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/ems");
        connectionFactory.setUsername("ems");
        connectionFactory.setPassword("123");
    }
    public static Connection getConnection(){
        try {
            return connectionFactory.newConnection();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static void closeConnectionAndChanel(Channel channel,Connection conn){
        try {
            if (channel!=null) {
                channel.close();
            }
            if (conn!=null) {
                conn.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

1 简单队列/HelloWorld模式

一个生产者对应一个消费者

在这里插入图片描述

1.1生产者


import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.junit.Test;

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


public class Provider {

    @Test
    public void testSendMessage() throws IOException, TimeoutException {

        //1.创建mq的连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接mq主机
        connectionFactory.setHost("192.168.174.134");
        //设置端口号
        connectionFactory.setPort(5672);
        //设置连接那个虚拟机
        connectionFactory.setVirtualHost("/ems");
        //设置访问虚拟主机的用户名和密码
        connectionFactory.setUsername("ems");
        connectionFactory.setPassword("123");

        //获取连接对象
        Connection connection = connectionFactory.newConnection();

        //获取连接中的通道
        Channel channel = connection.createChannel();

        //通道绑定对应消息队列
        //参数1:队列名称,如果队列不存在自动创建
        //参数2:用来定义队列特性是否持久化
        //参数3:是否独占队列
        //参数4:是否在消费完成后自动删除队列
        channel.queueDeclare("hello", false, false, false, null);

        //发布消息
        //参数1:交换机名称
        //参数2:队列名称
        //参数3:传递消息额外设置
        //参数4:消息的具体内容
        channel.basicPublish("","hello",null,"emm".getBytes());
        channel.close();
        connection.close();


    }
}

1.2 消费者


import com.rabbitmq.client.*;

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


public class Customer {

    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建mq的连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置连接mq主机
        factory.setHost("192.168.174.134");
        //设置端口号
        factory.setPort(5672);
        //设置连接那个虚拟机
        factory.setVirtualHost("/ems");
        //设置访问虚拟主机的用户名和密码
        factory.setUsername("ems");
        factory.setPassword("123");

        //获取连接对象
        Connection connection = factory.newConnection();

        //获取连接中的通道
        Channel channel = connection.createChannel();

        //通道绑定
        channel.queueDeclare("hello", false, false, false, null);

        //消费消息
        //参数1:消费那个队列的消息,队列名称
        //参数2:开始消息的自动确认机制
        //参数3:消费时的回调接口
        channel.basicConsume("hello", 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));
            }
        });

        channel.close();
        connection.close();
    }

}

1.3 运行

在这里插入图片描述

2 work 模式

一个生产者对应多个消费者,但是一条消息只能有一个消费者获得消息

在这里插入图片描述

2.1轮询分配

2.1.1 生产者

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

import java.io.IOException;

public class Provider {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();

        Channel channel = connection.createChannel();

        channel.queueDeclare("work",true,false,false,null);

        for (int i = 0 ; i < 20 ; i++){
            channel.basicPublish("","work",null,(i+"===>hello work queue").getBytes());
        }

        RabbitMQUtils.closeConnectionAndChanel(channel,connection);
    }

}

2.1.2 消费者1

import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

/**
 * @Author: czn
 * @Date 2021/2/6 16:57
 */
public class Costomer1 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();

        Channel channel = connection.createChannel();

        channel.queueDeclare("work",true,false,false,null);

        channel.basicConsume("work",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));
            }
        });
    }
}

2.1.3消费者2

import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

public class Costomer2 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();

        Channel channel = connection.createChannel();

        channel.queueDeclare("work",true,false,false,null);

        channel.basicConsume("work",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));
            }
        });
    }
}

2.1.4 运行

消费者1
在这里插入图片描述
消费者2
在这里插入图片描述

2.2 公平分配(能者多劳)

2.2.1 消费者1


import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

/**
 * @Author: czn
 * @Date 2021/2/6 16:57
 */
public class Costomer3 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        final Channel channel = connection.createChannel();
        //每次只能消费一个消息
        channel.basicQos(1);
        channel.queueDeclare("work",true,false,false,null);
        //参数1:队列名
        // 参数2:消息自动确认 true 消费者自动向rabbitmq确认消息消费 false不会自动确认消息
        channel.basicConsume("work",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                try{
                    Thread.sleep(2000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("消费者1:"+new String(body));
                //参数1:确认队列中那个具体消息
                // 参数2:是否开启多个消息同时确定
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}

2.2.2 消费者4


import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

/**
 * @Author: czn
 * @Date 2021/2/6 16:57
 */
public class Costomer4 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        final Channel channel = connection.createChannel();
        channel.basicQos(1);
        channel.queueDeclare("work",true,false,false,null);
        channel.basicConsume("work",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者4:"+new String(body));
                //手动确认
                // 参数1:手动确认标识
                // 参数2:false 每次确认一个
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}

2.2.3 生产者


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

import java.io.IOException;

/**
 * @Author: czn
 * @Date 2021/2/6 16:50
 */
public class Provider {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("work",true,false,false,null);
        for (int i = 0 ; i < 20 ; i++){
            channel.basicPublish("","work",null,(i+"===>hello work queue").getBytes());
        }
        RabbitMQUtils.closeConnectionAndChanel(channel,connection);
    }

}

2.2.4 运行

消费者3(睡眠2s)
在这里插入图片描述

消费者4
在这里插入图片描述

3 fanout广播模式/发布/订阅模式

一个消费者将消息首先发送到交换器,交换器绑定多个队列,然后被监听该队列的消费者所接收并消费.

在这里插入图片描述

3.1 生产者


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

import java.io.IOException;

public class Provider {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        // 将通道声明指定交换机
        // 参数1:交换机名称 如果没有则自动创建
        // 参数2:交换机类型
        channel.exchangeDeclare("logs", "fanout");

        // 发消息
        channel.basicPublish("logs","",null,"fanout message".getBytes());

        //释放资源
        RabbitMQUtils.closeConnectionAndChanel(channel,connection);
    }
}

3.2 消费者1,2,3


import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

public class Costomer1 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();

        //通道绑定交换机
        channel.exchangeDeclare("logs","fanout");

        //绑定临时队列
        String queueName = channel.queueDeclare().getQueue();

        //绑定交换机和队列
        channel.queueBind(queueName,"logs","");

        //消费消息
        channel.basicConsume(queueName,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));
            }
        });

    }
}

3.3 运行

当生产者发布消息时,三个消费者都同时消费了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4 Routing 路由模式

在Fanout模式中,一条消息,会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange.

在这里插入图片描述

4.1 生产者


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

import java.io.IOException;

public class Provider {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        // 参数1:交换机名称
        // 参数2:交换机类型
        channel.exchangeDeclare("logs_direct","direct");
        // 发送消息
        String routingKey = "warning";
        channel.basicPublish("logs_direct",routingKey,null,("direct模型 route key:["+routingKey+"]发送的消息").getBytes());
        RabbitMQUtils.closeConnectionAndChanel(channel,connection);
    }
}

4.2 消费者1


import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

public class Customer1 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        //声明交换机和交换机类型
        channel.exchangeDeclare("logs_direct","direct");
        //创建临时队列
        String queue = channel.queueDeclare().getQueue();
        //基于route key绑定队列和交换机
        channel.queueBind(queue,"logs_direct","error");
        //获取消费的消息
        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));
            }
        });

    }
}

4.3 消费者2


import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

public class Customer2 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        //声明交换机和交换机类型
        channel.exchangeDeclare("logs_direct","direct");
        //创建临时队列
        String queue = channel.queueDeclare().getQueue();
        //基于route key绑定队列和交换机
        channel.queueBind(queue,"logs_direct","info");
        channel.queueBind(queue,"logs_direct","error");
        channel.queueBind(queue,"logs_direct","warning");
        //获取消费的消息
        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));
            }
        });

    }
}

4.4 运行

生产者分别运行 info,error,warning

消费者1
在这里插入图片描述
消费者2
在这里插入图片描述

5 Topic

Topic类型的Exchange与Direct相比,都是可以根据Routingkey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key的时候使用通配"符!这种模型Routingkey一般都是由一个或多个单词组成,3个单词之间以.分割,例如: item.insert

  • 符号#: 表示匹配一个或多个词,
  • 符号*: 表示匹配一个词.

在这里插入图片描述

5.1 生产者

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

import java.io.IOException;

public class Provider {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare("topics","topic");
        //发布消息
        String routekey = "user.save.delete";
        channel.basicPublish("topics",routekey,null,("topic动态路由["+routekey+"]").getBytes());

        RabbitMQUtils.closeConnectionAndChanel(channel,connection);
    }
}

5.2 消费者1


import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;


public class Customer1 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare("topics","topic");
        //创建临时队列
        String queue = channel.queueDeclare().getQueue();
        //绑定队列及交换机
        channel.queueBind(queue,"topics","user.*");

        //消费消息
        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));
            }
        });
    }
}

5.3 消费者2


import com.rabbitmq.client.*;
import utils.RabbitMQUtils;

import java.io.IOException;

/**
 * @Author: czn
 * @Date 2021/2/7 11:11
 */
public class Customer2 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare("topics","topic");
        //创建临时队列
        String queue = channel.queueDeclare().getQueue();
        //绑定队列及交换机
        channel.queueBind(queue,"topics","user.#");

        //消费消息
        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));
            }
        });
    }
}

5.4 运行

生产者分别运行 user.sava.delete , user.save

消费者1
在这里插入图片描述
消费者2
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值