RabbitMQ工作模式

RabbitMQ工作模式

6种工作模式:简单模式、Work queues工作队列模式、Publish/Subscribe 发布与订阅模式、Routing 路由模式、Topics 主题模式、RPC 远程调用模式

简单模式

单个生产者,单个消费者。
在这里插入图片描述
p:表示生产者,消息发送者。
c:表示消费者,消息接收者,会一直等待消息到来。
中间黄色部分:queue,消息队列,p向里面投递消息,c从里面取消息。
代码示例
pom文件添加依赖:

 <!--rabbitmq -->
    <dependency>
      <groupId>com.rabbitmq</groupId>
      <artifactId>amqp-client</artifactId>
      <version>5.3.0</version>
    </dependency>
    <!--json -->
    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.8.5</version>
    </dependency>

生产者:

package com.cshg.rabbitmq.helloworld;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {

    public static void main(String[] args) throws IOException,TimeoutException{
      	Connection conn = RabbitUtil.getConn();
        //创建通信通道,相当于TCP的虚拟连接
        Channel channel = conn.createChannel();
        //第一个参数:队列名称
        //第二个参数:是否持久化 false就是不持久化,mq停掉数据就会消失
        //第三个参数:是否队列私有化,false代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才可以一直使用
        //第四个参数:是否自动删除,false代表连接停掉后不自动删除这个队列
        //其他额外参数,null
        channel.queueDeclare("helloworld",false,false,false,null);
        String message = "辉辉大哥";
        channel.basicPublish("","helloworld",null,message.getBytes());
        RabbitUtil.close(conn,channel);
        System.out.println("==========数据发送成功========");
    }
}

消费者

package com.cshg.rabbitmq.helloworld;

import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * Created by  on 2020/12/27.
 */
public class Consumer {

    public static void main(String[] args) throws IOException,TimeoutException {
        Connection conn = RabbitUtil.getConn();
        //创建通信通道,相当于TCP的虚拟连接
        Channel channel = conn.createChannel();
        channel.queueDeclare("helloworld",false,false,false,null);
        //创建一个消息消费者
        //第一个参数:队列名
        //第二个参数:是否自动确认收到消息,false代表手动编程来确认消息,这是MQ的推荐做法
        //第三个参数:要传入defaultConsumer的实现类
        channel.basicConsume("helloworld",false,new Reciver(channel));
    }
}
class  Reciver extends DefaultConsumer{
    private Channel channel;

    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());
        envelope.getDeliveryTag();
        //false只确认签收当前的消息 设置为true则代表签收消费者所有为签收的消息
        channel.basicAck(envelope.getDeliveryTag(),false);

    }
}

连接工具类

package com.cshg.rabbitmq.utils;

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

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

/**
 * Created by 王辉Acer on 2020/12/28.
 */
public class RabbitUtil {

    public static Connection getConn() throws IOException,TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置主机信息
        connectionFactory.setHost("192.168.0.11");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        connectionFactory.setVirtualHost("wanghui1228");
        //获得TCP的长连接
        Connection conn = connectionFactory.newConnection();
        return conn;
    }
    public static void close(Connection conn, Channel channel) throws IOException,TimeoutException {
        channel.close();
        conn.close();
    }
}

工作队列模式(Work queues)

单个生产者,多个消费者。
在这里插入图片描述
代码示例
工具类RabbitUtil同上。
生产者

package com.cshg.rabbitmq.workqueues;

import com.cshg.rabbitmq.constant.RabbitConstant;
import com.cshg.rabbitmq.utils.RabbitUtil;
import com.google.gson.Gson;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

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

/**
 * Created by  on 2020/12/28.
 */
public class Producer {
    public static void main(String[] args) throws IOException,TimeoutException {
        Connection conn = RabbitUtil.getConn();
        //创建通信通道,相当于TCP的虚拟连接
        Channel channel = conn.createChannel();
        //第一个参数:队列名称
        //第二个参数:是否持久化 false就是不持久化,mq停掉数据就会消失
        //第三个参数:是否队列私有化,false代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才可以一直使用
        //第四个参数:是否自动删除,false代表连接停掉后不自动删除这个队列
        //其他额外参数,null
        channel.queueDeclare(RabbitConstant.QUEUE_WORKQUEUES,false,false,false,null);
        Salary salary = null;
        String json = null;
        for(int i = 1 ; i <= 100 ; i++) {
            salary = new Salary("员工" + i, "13900000" + i, "成功发放8000元");
            json = new Gson().toJson(salary);
            channel.basicPublish("" , RabbitConstant.QUEUE_WORKQUEUES , null , json.getBytes());
        }
        RabbitUtil.close(conn,channel);
        System.out.println("==========数据发送成功========");
    }

}

消费者1

package com.cshg.rabbitmq.workqueues;

import com.cshg.rabbitmq.constant.RabbitConstant;
import com.cshg.rabbitmq.utils.RabbitUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * Created by  on 2020/12/28.
 */
public class Consumer1 {

    public static void main(String[] args) throws Exception {
        Connection conn = RabbitUtil.getConn();
        final Channel channel = conn.createChannel();

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

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

        channel.basicConsume(RabbitConstant.QUEUE_WORKQUEUES, false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String json = new String(body);
                System.out.println("consumer-工资发放成功:" + json);

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

消费者2

package com.cshg.rabbitmq.workqueues;

import com.cshg.rabbitmq.constant.RabbitConstant;
import com.cshg.rabbitmq.utils.RabbitUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * Created by on 2020/12/28.
 */
public class Consumer2 {

    public static void main(String[] args) throws Exception {
        Connection conn = RabbitUtil.getConn();
        final Channel channel = conn.createChannel();

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

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

        channel.basicConsume(RabbitConstant.QUEUE_WORKQUEUES, false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String json = new String(body);
                System.out.println("consumer-工资发放成功:" + json);

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

消费者3

package com.cshg.rabbitmq.workqueues;

import com.cshg.rabbitmq.constant.RabbitConstant;
import com.cshg.rabbitmq.utils.RabbitUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * Created by on 2020/12/28.
 */
public class Consumer3 {

    public static void main(String[] args) throws Exception {
        Connection conn = RabbitUtil.getConn();
        final Channel channel = conn.createChannel();

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

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

        channel.basicConsume(RabbitConstant.QUEUE_WORKQUEUES, false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String json = new String(body);
                System.out.println("consumer-工资发放成功:" + json);

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

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

发布订阅模式
在这里插入图片描述
P:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机)
C:消费者,消息的接收者,会一直等待消息到来
Queue:消息队列,接收消息、缓存消息
E:交换机(Exchange)。一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有常见以下3种类型:
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定routing key 的队列
Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与 Exchange 绑定,或者没有符合路由规则的队列,那么消息会丢失。
发布/订阅模式应用场景
发布订阅模式,使用的是广播类型的交换机,因此,所有的消费者所获得的消息是相同的,特别适合“数据提供商和应用商”。如中国气象局提供“天气预报”等数据发送至交换机中,百度、网易、搜狐等门户接入,通过队列绑定到该交换机,获取气象局的天气预报。
代码示例
以后补上。。。
小结
1.交换机需要和队列进行绑定,绑定之后,一个消息可以被多个消费者收到。
2.发布订阅模式与工作队列模式的区别:
①工作队列模式不需要定义交换机,而发布订阅模式需要定义交换机。
②工作队列模式是面向队列发送消息(底层使用默认的交换机),发布订阅模式是面向交换机发送消息。
③工作队列模式不需要设置队列与交换机的绑定(底层设置队列绑定默认的交换机),发布订阅模式需要设置队列和交换机的绑定。
路由模式
在这里插入图片描述
说明:
①队列与交换机的绑定,要指定一个 RoutingKey(路由key),不能是任意绑定了。
②消息的发送方在向 Exchange 发送消息时,也必须指定消息的 RoutingKey。
③Exchange 不再把消息交给每一个绑定的队列,而是根据消息的 Routing Key 进行判断,只有队列的Routingkey 与消息的 Routing key 完全一致,才会接收到消息。
P:生产者,向 Exchange 发送消息,发送消息时,会指定一个routing key。
E:Exchange(交换机),接收生产者的消息,然后把消息递交给与 routing key 完全匹配的队列。
C1:消费者,其所在队列指定了需要 routing key 为 error 的消息。
C2:消费者,其所在队列指定了需要 routing key 为 info、error、warning 的消息。
小结
Routing 模式要求队列在绑定交换机时要指定 routing key,消息会转发到符合 routing key 的队列。
通配符模式(Topics)
说明
Topic 类型与 Direct 相比,都是可以根据 RoutingKey 把消息路由到不同的队列。只不过 Topic 类型Exchange 可以让队列在绑定 Routing key 的时候使用通配符。
Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert
通配符规则:# 匹配一个或多个词,* 匹配不多不少恰好1个词,例如:item.# 能够匹配 item.insert.abc 或者 item.insert,item.* 只能匹配 item.insert。
小结
Topic 主题模式可以实现 Pub/Sub 发布与订阅模式和 Routing 路由模式的功能,只是 Topic 在配置routing key 的时候可以使用通配符,显得更加灵活。
工作模式总结
1.简单模式 HelloWorld
一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)。
2.工作队列模式 Work Queue
一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)。
3.发布订阅模式
需要设置类型为 fanout 的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列。
4.路由模式
需要设置类型为 direct 的交换机,交换机和队列进行绑定,并且指定 routing key,当发送消息到交换机后,交换机会根据 routing key 将消息发送到对应的队列。
5.通配符模式
需要设置类型为 topic 的交换机,交换机和队列进行绑定,并且指定通配符方式的 routing key,当发送消息到交换机后,交换机会根据 routing key 将消息发送到对应的队列。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ提供了6种工作模式,包括简单模式、work queues、Publish/Subscribe发布与订阅模式、Routing路由模式、Topics主题模式、RPC远程调用模式(不太符合MQ)。这些模式分别具有不同的特点和使用场景。简单模式是最基本的模式,消息发送到队列中被消费者接收。工作队列模式是多个消费者共同消费一个队列中的消息。Publish/Subscribe发布与订阅模式中,生产者将消息发送到交换机,然后交换机将消息广播给所有绑定的队列。Routing路由模式是生产者选择将消息发送到特定的路由键上,消费者通过绑定队列和路由键来接收消息。Topics主题模式类似于Routing模式,但是可以使用通配符进行匹配路由键。RPC远程调用模式用于远程调用服务,不太符合消息队列的特点。 可以看出,这些模式在消息的传输、消费者的数量、消息的路由等方面有所不同。工作队列模式不需要定义交换机,而发布/订阅模式需要定义交换机。发布/订阅模式是面向交换机发送消息,而工作队列模式是面向队列发送消息(底层使用默认交换机)。发布/订阅模式需要设置队列和交换机的绑定,而工作队列模式不需要设置,实际上工作队列模式会将队列绑定到默认的交换机。 综上所述,RabbitMQ工作模式包括简单模式、work queues、Publish/Subscribe发布与订阅模式、Routing路由模式、Topics主题模式、RPC远程调用模式。每种模式在实际应用中有不同的用途和特点,可以根据具体需求选择合适的工作模式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [RabbitMQ工作模式](https://blog.csdn.net/weixin_42440154/article/details/124689685)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [RabbitMQ六种工作模式详解](https://blog.csdn.net/qq_44760609/article/details/125084962)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值