SpringCloudAlibaba第四章(分布式事务RabbitMQ)

目录

 

1:什么是MQ

2:主流MQ中间间对比

3:RabbitMQ安装

4:RabbitMQ案例

4.1:添加用户、添加Virtual Hosts

4.1: 点对点发送(hello word模型)

4.2:一个生产者和多个消费者(Work Queues)

4.3:发布订阅模式

4.4:Rooting路由模式

4.5:Topics订阅模式

4.6:总结

5:springboot整合rabbitmq

6:springboot整合rabbitmq分布式事务

6.1:消息发送方

6.2:消息接收方

 

 


1:什么是MQ

MQ(Message Queue)消息队列,是基础数据结构中“先进先出”的一种数据机构。指把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队列拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息。

2:主流MQ中间间对比

 

3:RabbitMQ安装

https://www.cnblogs.com/yihuihui/p/9095130.html

4:RabbitMQ案例

 

4.1:添加用户、添加Virtual Hosts

添加用户和虚拟主机

=======================虚拟主机的作用========================

 

4.1: 点对点发送(hello word模型)

总结:点对点发送,发送者发送多少消息,接受者接受多少消息。发送消息到Queues

 

 

生产者:

package com.thit.mq;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Producter {



    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection= MqUtil.getconnection();


        //创建通道
        Channel channel=connection.createChannel();

        //设置创建的queue状态
        //参数1:队列名字
        //参数2:队列的持久化 true持久化  false不持久化  重启会消失
        //参数3:是否独占队列
        //参数4:true 消费完删除对列
        //参数5:传递的参数
        channel.queueDeclare("test1",true,false,false,null);


        //推送消息 消息设置持久化
        //1:交换机名字
        //2:对列名字
        //3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
        //4:发送消息
        for (int i=0;i<20;i++){
            channel.basicPublish("","test1", MessageProperties.PERSISTENT_TEXT_PLAIN,("第几次发送消息:"+i).getBytes());
        }

        //关闭通道
        MqUtil.close(connection,channel);

        System.out.println("发送消息结束");

    }


}

消费者:

package com.thit.mq;

import com.rabbitmq.client.*;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer1 {

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection= MqUtil.getconnection();
        //创建通道
        Channel channel=connection.createChannel();
        //一次消费一个消息
        channel.basicQos(1);
        //设置创建的queue状态
        //参数1:队列名字
        //参数2:队列的持久化 true持久化  false不持久化  重启会消失
        //参数3:是否独占队列
        //参数4:true 消费完删除对列
        //参数5:传递的参数
        channel.queueDeclare("test1",true,false,false,null);


        //消费消息
        //参数1:对垒名字
        //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
        channel.basicConsume("test1",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String a=new String(body);
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("111接收到的参数是:"+a);
                //消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
                //int b=10/0;
                //当确认参数是false的时候,手动确认
               channel.basicAck(envelope.getDeliveryTag(),false);

            }
        });

        //关闭通道
        //MqUtil.close(connection,channel);
        System.out.println("接受消息结束");

    }


}

 

4.2:一个生产者和多个消费者(Work Queues)

总结:消息平均分配,即使接受者空闲,也不能多干活,直接发送消息到Queues

您可能已经注意到,调度仍然无法完全按照我们的要求进行。例如,在有两名工人的情况下,当所有奇怪的消息都很重,甚至消息很轻时,一位工人将一直忙碌而另一位工人将几乎不做任何工作。好吧,RabbitMQ对此一无所知,并且仍将平均分配消息。

发生这种情况是因为RabbitMQ在消息进入队列(queues)时才调度消息。它不会查看使用者的未确认消息数。它只是盲目地将每第n条消息发送给第n个使用者

代码案例:生产者一个,消费者多个

生产者:

package com.thit.mq;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Producter {



    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection= MqUtil.getconnection();


        //创建通道
        Channel channel=connection.createChannel();

        //设置创建的queue状态
        //参数1:队列名字
        //参数2:队列的持久化 true持久化  false不持久化  重启会消失
        //参数3:是否独占队列
        //参数4:true 消费完删除对列
        //参数5:传递的参数
        channel.queueDeclare("test1",true,false,false,null);


        //推送消息 消息设置持久化
        //1:交换机名字
        //2:对列名字
        //3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
        //4:发送消息
        for (int i=0;i<20;i++){
            channel.basicPublish("","test1", MessageProperties.PERSISTENT_TEXT_PLAIN,("第几次发送消息:"+i).getBytes());
        }

        //关闭通道
        MqUtil.close(connection,channel);

        System.out.println("发送消息结束");

    }


}

消费者多个:

package com.thit.mq;

import com.rabbitmq.client.*;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer1 {

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection= MqUtil.getconnection();
        //创建通道
        Channel channel=connection.createChannel();
        //一次消费一个消息
        channel.basicQos(1);
        //设置创建的queue状态
        //参数1:队列名字
        //参数2:队列的持久化 true持久化  false不持久化  重启会消失
        //参数3:是否独占队列
        //参数4:true 消费完删除对列
        //参数5:传递的参数
        channel.queueDeclare("test1",true,false,false,null);


        //消费消息
        //参数1:对垒名字
        //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
        channel.basicConsume("test1",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String a=new String(body);
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("111接收到的参数是:"+a);
                //消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
                //int b=10/0;
                //当确认参数是false的时候,手动确认
               channel.basicAck(envelope.getDeliveryTag(),false);

            }
        });

        //关闭通道
        //MqUtil.close(connection,channel);
        System.out.println("接受消息结束");

    }


}

 

4.3:发布订阅模式

总结:类型是:Fanout,每一个消费者都能接受到相同的消息

1:生产者发送消息到交换机(ExChange)

2:交换机负责把广播发送到不同的对列(queues,队列名字不能相同),队列绑定指定交换机

3:不同的消费者在队列接收到消息

代码案例:生产者1个,消费者多个

生产者:

package com.thit.mq2;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Producter2 {



    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection= MqUtil.getconnection();

        //创建通道
        Channel channel=connection.createChannel();

        //创建交换机
        //参数1:交换机名字
        //参数2:交换机广播类型  固定值
        channel.exchangeDeclare("exchange1","fanout");


        //推送消息 消息设置持久化
        //1:交换机名字
        //2:路由key
        //3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
        //4:发送消息
        for (int i=0;i<20;i++){
            channel.basicPublish("exchange1","", MessageProperties.PERSISTENT_TEXT_PLAIN,("第几次发送消息:"+i).getBytes());
        }

        //关闭通道
        MqUtil.close(connection,channel);

        System.out.println("发送消息结束");

    }


}

消费者:

package com.thit.mq2;

import com.rabbitmq.client.*;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer3 {



    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection= MqUtil.getconnection();

        //创建通道
        Channel channel=connection.createChannel();


        //创建交换机
        //参数1:交换机名字
        //参数2:交换机广播类型  固定值
        channel.exchangeDeclare("exchange1","fanout");


        //设置创建的queue状态
        //参数1:队列名字
        //参数2:队列的持久化 true持久化  false不持久化  重启会消失
        //参数3:是否独占队列
        //参数4:true 消费完删除对列
        //参数5:传递的参数
        channel.queueDeclare("c1",false,false,false,null);

      // String aname= channel.queueDeclare().getQueue();

        //绑定队列和交换机
        //参数1:队列名字
        //参数2:交换机名字
        //参数3:路由key
        channel.queueBind("c1","exchange1","");

        //消费消息
        //参数1:对垒名字
        //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
        channel.basicConsume("c1",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String a=new String(body);


                System.out.println("111接收到的参数是:"+a);
                //消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
                //int b=10/0;
                //当确认参数是false的时候,手动确认
              //1 channel.basicAck(envelope.getDeliveryTag(),false);

            }
        });
        //关闭通道
        //MqUtil.close(connection,channel);
        System.out.println("接受消息结束");
    }
}



package com.thit.mq2;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer4 {

    public static void main(String[] args) throws IOException, TimeoutException {
        {

            Connection connection= MqUtil.getconnection();

            //创建通道
            Channel channel=connection.createChannel();


            //创建交换机
            //参数1:交换机名字
            //参数2:交换机广播类型  固定值
            channel.exchangeDeclare("exchange1","fanout");


            //设置创建的queue状态
            //参数1:队列名字
            //参数2:队列的持久化 true持久化  false不持久化  重启会消失
            //参数3:是否独占队列
            //参数4:true 消费完删除对列
            //参数5:传递的参数
            channel.queueDeclare("c2",false,false,false,null);

            //绑定队列和交换机
            //参数1:队列名字
            //参数2:交换机名字
            //参数3:路由key
            channel.queueBind("c2","exchange1","");

            //消费消息
            //参数1:对垒名字
            //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
            channel.basicConsume("c2",false,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    super.handleDelivery(consumerTag, envelope, properties, body);
                    String a=new String(body);
//                    try {
//                        TimeUnit.SECONDS.sleep(2);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }

                    System.out.println("111接收到的参数是:"+a);
                    //消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
                    //int b=10/0;
                    //当确认参数是false的时候,手动确认
                    channel.basicAck(envelope.getDeliveryTag(),false);

                }
            });

            //关闭通道
            //MqUtil.close(connection,channel);
            System.out.println("接受消息结束");

        }
    }

}

4.4:Rooting路由模式

总结:类型是:Direct,每一个消费者都能接受到相同的消息,但是根据key路由

生产者:

package com.thit.mq3;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Producter3 {
    
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection= MqUtil.getconnection();

        //创建通道
        Channel channel=connection.createChannel();

        //创建交换机
        //参数1:交换机名字
        //参数2:交换机广播类型  固定值direct 路由模式
        channel.exchangeDeclare("exchange3","direct");
        
        //自定义key的值
        String  key="demo";

        //推送消息 消息设置持久化
        //1:交换机名字
        //2:路由key
        //3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
        //4:发送消息
        for (int i=0;i<1;i++){
            channel.basicPublish("exchange3",key, MessageProperties.PERSISTENT_TEXT_PLAIN,
                    ("路由key第几次发送消息:"+i+":key的值是:"+key).getBytes());
        }
        //关闭通道
        MqUtil.close(connection,channel);
        System.out.println("发送消息结束");

    }
    
}

消费者:

package com.thit.mq3;

import com.rabbitmq.client.*;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer5 {

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection= MqUtil.getconnection();

        //创建通道
        Channel channel=connection.createChannel();


        //创建交换机
        //参数1:交换机名字
        //参数2:交换机广播类型  固定值
        channel.exchangeDeclare("exchange3","direct");


        //设置创建的queue状态
        //参数1:队列名字
        //参数2:队列的持久化 true持久化  false不持久化  重启会消失
        //参数3:是否独占队列
        //参数4:true 消费完删除对列
        //参数5:传递的参数
        //channel.queueDeclare("c5",false,false,false,null);

        String aname= channel.queueDeclare().getQueue();

        //绑定队列和交换机
        //参数1:队列名字
        //参数2:交换机名字
        //参数3:路由key
        channel.queueBind(aname,"exchange3","demo1");
        channel.queueBind(aname,"exchange3","demo2");
        channel.queueBind(aname,"exchange3","demo3");


        //消费消息
        //参数1:对垒名字
        //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
        channel.basicConsume(aname,true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String a=new String(body);


                System.out.println("111接收到的参数是:"+a);


               // channel.basicAck(envelope.getDeliveryTag(),false);

            }
        });

        //关闭通道
        //MqUtil.close(connection,channel);

        System.out.println("接受消息结束");

    }


}


package com.thit.mq3;

import com.rabbitmq.client.*;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer6 {

    public static void main(String[] args) throws IOException, TimeoutException {
        {

            Connection connection= MqUtil.getconnection();

            //创建通道
            Channel channel=connection.createChannel();


            //创建交换机
            //参数1:交换机名字
            //参数2:交换机广播类型  固定值
            channel.exchangeDeclare("exchange3","direct");


            //设置创建的queue状态
            //参数1:队列名字
            //参数2:队列的持久化 true持久化  false不持久化  重启会消失
            //参数3:是否独占队列
            //参数4:true 消费完删除对列
            //参数5:传递的参数
            //channel.queueDeclare("c6",false,false,false,null);

            String aname= channel.queueDeclare().getQueue();


            //绑定队列和交换机
            //参数1:队列名字
            //参数2:交换机名字
            //参数3:路由key
            channel.queueBind(aname,"exchange3","demo3");

            //消费消息
            //参数1:对垒名字
            //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
            channel.basicConsume(aname,true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    super.handleDelivery(consumerTag, envelope, properties, body);
                    String a=new String(body);

                    System.out.println("111接收到的参数是:"+a);

                    //channel.basicAck(envelope.getDeliveryTag(),false);

                }
            });

            //关闭通道
            //MqUtil.close(connection,channel);

            System.out.println("接受消息结束");

        }
    }


}

 

4.5:Topics订阅模式

总结:类型是:Topic,每一个消费者都能接受到相同的消息,根据key的正则表达式路由

代码案例:

生产者:

package com.thit.mq4;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Producter4 {
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection= MqUtil.getconnection();
        //创建通道
        Channel channel=connection.createChannel();

        //创建交换机
        //参数1:交换机名字
        //参数2:fanout 交换机广播类型 大家都接收到消息
        //参数2:direct 路由模式  指定路由
        //参数2:topic 动态路由模式 动态匹配路由
        channel.exchangeDeclare("exchange4","topic");


        //自定义key的值

        String  key="user.huyiju.test";

        //推送消息 消息设置持久化
        //1:交换机名字
        //2:路由key
        //3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
        //4:发送消息
        for (int i=0;i<1;i++){
            channel.basicPublish("exchange4",key, MessageProperties.PERSISTENT_TEXT_PLAIN,
                    ("路由key第几次发送消息:"+i+":key的值是:"+key).getBytes());
        }

        //关闭通道
        MqUtil.close(connection,channel);
        System.out.println("发送消息结束");
    }
}

消费者:

package com.thit.mq4;

import com.rabbitmq.client.*;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer7 {
    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection= MqUtil.getconnection();

        //创建通道
        Channel channel=connection.createChannel();
        //创建交换机
        //参数1:交换机名字
        //参数2:交换机广播类型  固定值
        channel.exchangeDeclare("exchange4","topic");


        //设置创建的queue状态
        //参数1:队列名字
        //参数2:队列的持久化 true持久化  false不持久化  重启会消失
        //参数3:是否独占队列
        //参数4:true 消费完删除对列
        //参数5:传递的参数
        //channel.queueDeclare("c5",false,false,false,null);

        String aname= channel.queueDeclare().getQueue();

        //绑定队列和交换机
        //参数1:队列名字
        //参数2:交换机名字
        //参数3:路由key
        channel.queueBind(aname,"exchange4","user.*.#");



        //消费消息
        //参数1:对垒名字
        //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
        channel.basicConsume(aname,true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String a=new String(body);


                System.out.println("111接收到的参数是:"+a);


               // channel.basicAck(envelope.getDeliveryTag(),false);

            }
        });
        
        //关闭通道
        //MqUtil.close(connection,channel);

        System.out.println("接受消息结束");

    }


}



package com.thit.mq4;

import com.rabbitmq.client.*;
import com.thit.util.MqUtil;

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

/**
 * @author :huyiju
 * @date :2020-05-28 19:03
 * 直接发送对列
 * 1对1 消费消息
 */
public class Customer8 {
    public static void main(String[] args) throws IOException, TimeoutException {
        {

            Connection connection= MqUtil.getconnection();

            //创建通道
            Channel channel=connection.createChannel();


            //创建交换机
            //参数1:交换机名字
            //参数2:交换机广播类型  固定值
            channel.exchangeDeclare("exchange4","topic");


            //设置创建的queue状态
            //参数1:队列名字
            //参数2:队列的持久化 true持久化  false不持久化  重启会消失
            //参数3:是否独占队列
            //参数4:true 消费完删除对列
            //参数5:传递的参数
            //channel.queueDeclare("c6",false,false,false,null);

            String aname= channel.queueDeclare().getQueue();


            //绑定队列和交换机
            //参数1:队列名字
            //参数2:交换机名字
            //参数3:路由key
            channel.queueBind(aname,"exchange4","user.huyiju.#");

            //消费消息
            //参数1:对垒名字
            //参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息  消息会丢失
            channel.basicConsume(aname,true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    super.handleDelivery(consumerTag, envelope, properties, body);
                    String a=new String(body);

                    System.out.println("111接收到的参数是:"+a);

                    //channel.basicAck(envelope.getDeliveryTag(),false);

                }
            });

            //关闭通道
            //MqUtil.close(connection,channel);

            System.out.println("接受消息结束");

        }
    }

}

4.6:总结

5:springboot整合rabbitmq

1:pom

 <!--springboot的rabbit的mq-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

 

2:代码案例

生产者:

 //注入rabbitTemplate

    @Autowired
    RabbitTemplate RabbitTemplate;

    /**
     * 一对一
     * 一对多
     * 消费合集等于发送方
     * 消费者轮流消费
     * @param id
     * @return
     */

    public int mq1(int id) {
        CorrelationData cData = new CorrelationData("huyiju001");
        Users users = new Users();
        users.setId(2);
        users.setName("张三");
        String message = JSON.toJSONString(users);
        for (int a = 0; a < 1; a++) {

            RabbitTemplate.convertAndSend("mq88", message + ":" + a);
        }
        return 0;
    }


    /**
     * 广播模式
     * @param id
     * @return
     * 多个接受者  接受相同的数据
     */
    public int mq2(int id) {
        Users users = new Users();
        users.setId(1);
        users.setName("李四");

        String message = JSON.toJSONString(users);
        for (int a = 0; a < 5; a++) {
            //参数1:交换机名字
            //参数2:路由key名字
            //参数3:发送的消息
            RabbitTemplate.setConfirmCallback(confirmCallback);
            RabbitTemplate.setReturnCallback(returnCallback);
            RabbitTemplate.convertAndSend("hexchange1",null,message + ":" + a);
        }
        return 0;
    }


    /**
     * 广播模式
     * @param id
     * @return
     * 多个接受者  根据key接受数据
     */
    public int mq3(int id) {
        Users users = new Users();
        users.setId(5);
        users.setName("天天");

        String message = JSON.toJSONString(users);
        for (int a = 0; a < 4; a++) {
            //参数1:交换机名字
            //参数2:路由key名字
            //参数3:发送的消息

            RabbitTemplate.convertAndSend("hexchange4","user.test",message + ":" + a);
        }
        return 0;
    }

消费者队列模式:多个消费者不能重复消费,两个消费者

package com.thit.springbootmq1;//package com.thit.SpringBootMq;



import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;

@Component
@RabbitListener(queuesToDeclare = @Queue("mq88")) //消费者注解 没有创建
//@RabbitListener(queues = "mq2") //没有对列 会报错  需要初始化创建

public class SCustomer1 {

    @RabbitHandler
    public void receive(Message message1, Channel channel, String meaage) throws IOException {
        try {


            System.out.println("1接收消息次数");
            String json = new String(message1.getBody());

            System.out.println("11接收到的消息是:"+meaage);
            System.out.println("11接收到的消息是:"+json);

            int a=10/0;

            //1:模拟数据库操作,此可能执行失败,需要将消费的消息重新放回队列

            //2:当确认参数是false的时候,手动确认,没有出错,手动删除消息哦

           channel.basicAck(message1.getMessageProperties().getDeliveryTag(),false);
        }catch (Exception e){
            System.out.println("1消息接收方程序出错~,需要将消息返回给队列:");
            // 1:处理消息失败,将消息重新放回队列
            channel.basicNack(message1.getMessageProperties().getDeliveryTag(), false,true);

            //2:或者将失败的消息插入消费者的数据库,落地处理
            //insertDb(meaage);
        }



    }


}





package com.thit.springbootmq1;//package com.thit.SpringBootMq;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
@RabbitListener(queuesToDeclare = @Queue("mq88")) //消费者注解 没有创建
//@RabbitListener(queues = "mq2") //没有对列 会报错  需要初始化创建

public class SCustomer2 {

    @RabbitHandler
    public void receive(Message message1, Channel channel, String meaage) throws IOException {
        try {


            System.out.println("2接收消息次数");
            String json = new String(message1.getBody());

            System.out.println("22接收到的消息是:"+meaage);

            //int a=10/0;

            //1:模拟数据库操作,此可能执行失败,需要将消费的消息重新放回队列

            //2:当确认参数是false的时候,手动确认,没有出错,手动删除消息哦

            channel.basicAck(message1.getMessageProperties().getDeliveryTag(),false);
        }catch (Exception e){
            System.out.println("2消息接收方程序出错~,需要将消息返回给队列:");
            // 1:处理消息失败,将消息重新放回队列
            channel.basicNack(message1.getMessageProperties().getDeliveryTag(), false,true);

            //2:或者将失败的消息插入消费者的数据库,落地处理
            //insertDb(meaage);
        }



    }



}

消费者广播模式:多个消息者重复得到相同的数据,两个消费者

package com.thit.springbootmq;

import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component

public class SCustomer3 {
//type = "topic" 根据key正则表达式
//type = "direct"  根据key
// type = "fanout"  扇区 都会接受


    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,//临时对列
                    exchange = @Exchange(value = "hexchange4",
                            type = "topic" ),//type = "topic" 根据key正则表达式

                    key = {"user.test"}
            )
    })
    public void listerQueue1(String message){
        System.out.println("消费者1:" + message);
        System.out.println("======================");
    }


    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,//临时对列
                    exchange = @Exchange(value = "hexchange4",type = "topic"),
                    key = {"user.#"}
                    )
    })
    public void listerQueue2(String message)
    {

        System.out.println("消费者2:" + message);
    }




}

 

6:springboot整合rabbitmq分布式事务

6.1:消息发送方

操作数据库,发送数据到mq,如果数据库事务失败,不发送数据,事务成功,发送数据到mq,如果发送mq失败,需要有临时流水表,定时任务,重新发送,知道数据发送到mq。

6.2:消息接收方

消息接收到数据,入库,如是事务提交成功,则确认消息消费。如果事务入库失败。则不要确认消息,等待在此消费。或者将消息插入数据库,返回消息接受成功,后续的插入数据库的消息在进行处理。

 

 

 

 

 

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值