rabbitmq工作模式之简单模式、work queues

rabbitmq工作模式之简单模式、work queues

  • 1、基础工作
    • 1.1、创建用户和虚拟机
      • 1.1.1、创建用户
      • 1.1.2、创建虚拟机
    • 1.2、基础类
      • 1.2.1、常量类
      • 1.2.2、基础类
      • 1.2.3、pom依赖
  • 2、简单模式
    • 2.1、消费者
    • 2.2、生产者
    • 2.3、运行测试
  • 3、work queues
    • 3.1、消费者
    • 3.2、生产者
    • 3.3、短信实体类
    • 3.4、运行测试

1、基础工作

由于目前编写的代码无法给我们自动创建用户和虚拟机,所以需要我们自己先手动创建一下用户和虚拟机。

1.1、创建用户和虚拟机

1.1.1、创建用户

创建用户

rabbitmq工作模式之简单模式、work queues_第1张图片

用户创建成功如下图所示

rabbitmq工作模式之简单模式、work queues_第2张图片

1.1.2、创建虚拟机

rabbitmq工作模式之简单模式、work queues_第3张图片

创建完虚拟机之后,发现虚拟机还没有指定的用户,给它添加用户

rabbitmq工作模式之简单模式、work queues_第4张图片

添加用户

rabbitmq工作模式之简单模式、work queues_第5张图片

用户和虚拟机绑定成功之后如下图所示:

rabbitmq工作模式之简单模式、work queues_第6张图片

1.2、基础类

1.2.1、常量类

这是一个常量类,定义着队列的名称

public class RabbitConstant {
    public static final String QUEUE_HELLO_WORLD = "QUEUE_HELLO_WORLD";
    public static final String QUEUE_SMS = "QUEUE_SMS";
    public static final String QUEUE_EXCHANGE_WEATHER = "QUEUE_EXCHANGE_WEATHER";
    public static final String QUEUE_EXCHANGE_WEATHER_ROUTING = "QUEUE_EXCHANGE_WEATHER_ROUTING";
    public static final String QUEUE_BAI_DU = "QUEUE_BAI_DU";
    public static final String QUEUE_SIN_LANG = "QUEUE_SIN_LANG";
    public static final String QUEUE_EXCHANGE_WEATHER_TOPIC = "QUEUE_EXCHANGE_WEATHER_TOPIC";
}

1.2.2、基础类

public class RabbitUtils {
    private static ConnectionFactory connectionFactory = new ConnectionFactory();

    static {
        // 连接rabbitmq的ip地址
        connectionFactory.setHost("192.168.231.132");
        // 5672是RabbitMQ的默认端口号
        connectionFactory.setPort(5672);
        // 连接rabbitmq中的那一个用户  用户名名称
        connectionFactory.setUsername("ale");
        // 连接rabbitmq中的那一个用户  用户名密码
        connectionFactory.setPassword("ale123");
        // 使用rabbit的时候需要连接一个虚拟机,虚拟机里面存放的是交换机以及队列
        // 对于不同的租户同一个rabbitmq提供的交换机或者队列都是独立的(也就是不同的虚拟机)
        connectionFactory.setVirtualHost("ale_virtual");
    }
    public static Connection getConnection() throws IOException, TimeoutException {
        Connection conn = null;
        conn = connectionFactory.newConnection();
        return conn;
    }
}

1.2.3、pom依赖

<dependency>
    <groupId>com.rabbitmqgroupId>
    <artifactId>amqp-clientartifactId>
    <version>5.3.0version>
dependency>

<dependency>
    <groupId>com.google.code.gsongroupId>
    <artifactId>gsonartifactId>
    <version>2.8.5version>
dependency>

2、简单模式

简单模式呢,就是一个生产者一个消费者,生产者生产出消息放到队列中,然后消费者去队列里面拿,如下图所示:

rabbitmq工作模式之简单模式、work queues_第7张图片

2.1、消费者

public class Consumer {

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


        // 获取TCP长连接
        Connection conn = RabbitUtils.getConnection();
        // 创建通信“通道”,相当于TCP中的虚拟连接
        Channel channel = conn.createChannel();

        // 创建队列,声明并创建一个队列,如果队列已存在,则使用这个队列
        // 第一个参数:队列名称ID
        // 第二个参数:是否持久化,false对应不持久化数据,MQ停掉数据就会丢失
        // 第三个参数:是否队列私有化,false则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用,其他消费者不让访问
        // 第四个:是否自动删除,false代表连接停掉后不自动删除掉这个队列
        // 其他额外的参数, null
        channel.queueDeclare(RabbitConstant.QUEUE_HELLO_WORLD,false, false, false, null);

        // 从MQ服务器中获取数据
        // 创建一个消息消费者
        // 第一个参数:队列名
        // 第二个参数代表是否自动确认收到消息,false代表手动编程来确认消息,这是MQ的推荐做法
        // 第三个参数要传入DefaultConsumer的实现类
        channel.basicConsume(RabbitConstant.QUEUE_HELLO_WORLD, false, new Reciver(channel));


    }
}


class  Reciver extends DefaultConsumer {

    private Channel channel;
    //重写构造函数,Channel通道对象需要从外层传入,在handleDelivery中要用到
    public Reciver(Channel channel) {
        super(channel);
        this.channel = channel;
    }

    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

        String message = new String(body);
        System.out.println("消费者接收到的消息:"+message);

        System.out.println("消息的TagId:"+envelope.getDeliveryTag());
        // false只确认签收当前的消息,设置为true的时候则代表签收该消费者所有未签收的消息
        channel.basicAck(envelope.getDeliveryTag(), false);
    }
}

2.2、生产者

public class Producer {

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


        //获取TCP长连接
        Connection conn = RabbitUtils.getConnection();
        //创建通信“通道”,相当于TCP中的虚拟连接
        Channel channel = conn.createChannel();

        //创建队列,声明并创建一个队列,如果队列已存在,则使用这个队列
        //第一个参数:队列名称ID
        //第二个参数:是否持久化,false对应不持久化数据,MQ停掉数据就会丢失
        //第三个参数:是否队列私有化,false则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用,其他消费者不让访问
        //第四个:是否自动删除,false代表连接停掉后不自动删除掉这个队列,true代表连接停掉后自动删除这个队列
        //其他额外的参数, null
        channel.queueDeclare(RabbitConstant.QUEUE_HELLO_WORLD,false, false, false, null);

        String message = "Ale,Hello World";
        // 四个参数
        // exchange 交换机,暂时用不到,在后面进行发布订阅时才会用到,简单模式会使用默认的交换机
        // 队列名称,这里在程序运行后,队列会自己创建
        // 额外的设置属性
        // 最后一个参数是要传递的消息字节数组
        channel.basicPublish("", RabbitConstant.QUEUE_HELLO_WORLD, null,message.getBytes());
        // 这里关闭连接的意思是我们不关心消息是否能发送到,只需要发送成功就行
        channel.close();
        conn.close();
        System.out.println("===发送成功===");

    }
}

2.3、运行测试

先运行消费者,再运行生产者
生产者会在控制台输出消费成功,如下图所示:

rabbitmq工作模式之简单模式、work queues_第8张图片

消费者会在控制台输出,打印出生产者生产的消息,如下图所示:

rabbitmq工作模式之简单模式、work queues_第9张图片

3、work queues

工作队列的模式就是一个生产者多个消费者,这里我们模仿乘客买票下订单,订单系统需要往一个队列里面放很多条短信,然后多个消费者去队列里面轮询去拿,如下图所示:

rabbitmq工作模式之简单模式、work queues_第10张图片

3.1、消费者

这里定义了三个消费者:
消费者1

public class SMSSender1 {

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


        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        //如果不写basicQos(1),则自动MQ会将所有请求平均发送给所有消费者
        //basicQos,MQ不再对消费者一次发送多个请求,而是消费者处理完一个消息后(确认后),在从队列中获取一个新的
        //处理完一个再取下一个
        channel.basicQos(1);

        channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String jsonSMS = new String(body);
                System.out.println("SMSSender1-短信发送成功:" + jsonSMS);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }
}

消费者2

public class SMSSender2 {

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


        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        //如果不写basicQos(1),则自动MQ会将所有请求平均发送给所有消费者
        //basicQos,MQ不再对消费者一次发送多个请求,而是消费者处理完一个消息后(确认后),在从队列中获取一个新的
        //处理完一个再取下一个
        channel.basicQos(1);

        channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String jsonSMS = new String(body);
                System.out.println("SMSSender2-短信发送成功:" + jsonSMS);

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

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

消费者3

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


        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        //如果不写basicQos(1),则自动MQ会将所有请求平均发送给所有消费者
        //basicQos,MQ不再对消费者一次发送多个请求,而是消费者处理完一个消息后(确认后),在从队列中获取一个新的
        //处理完一个再取下一个
        channel.basicQos(1);

        channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String jsonSMS = new String(body);
                System.out.println("SMSSender3-短信发送成功:" + jsonSMS);

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }
}

3.2、生产者

public class OrderSystem {

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = RabbitUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        for(int i = 1 ; i <= 100 ; i++) {
            SMS sms = new SMS("乘客" + i, "13900000" + i, "您的车票已预订成功");
            String jsonSMS = new Gson().toJson(sms);
            channel.basicPublish("" , RabbitConstant.QUEUE_SMS , null , jsonSMS.getBytes());
        }
        System.out.println("发送数据成功");
        channel.close();
        connection.close();
    }
}

3.3、短信实体类

public class SMS {

    private String name;
    private String mobile;
    private String content;

    public SMS(String name, String mobile, String content) {
        this.name = name;
        this.mobile = mobile;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

3.4、运行测试

本来工作队列模式的默认是三个消费者轮询去取数据的,但是我上面的代码里加了如下一行代码,这行代码的意思就是,我消费完成一条消息之后再去取下一条,然后运行的结果就如下所示:

// 处理完一个再取下一个
channel.basicQos(1);

生产者截图:

rabbitmq工作模式之简单模式、work queues_第11张图片


消费者运行截图
消费者1

rabbitmq工作模式之简单模式、work queues_第12张图片

消费者2

rabbitmq工作模式之简单模式、work queues_第13张图片

消费者3

rabbitmq工作模式之简单模式、work queues_第14张图片

你可能感兴趣的:(rabbitmq,中间件,rabbitmq,mq)