RabbitMq

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值