RabbitMQ六种模式+整合springboot

认识消息队列

1、同步调用与异步调用?

同步调用:A服务调用B服务,需要等待B服务执行完毕的返回值,A服务才可以继续往下执行

同步调用实例:REST(Ribbin\Feign)和RPC(Dubbo)

异步调用:A服务调用B服务,而无需等待B服务的执行结果,也就是说在B服务执行的同时A服务可以继续往下执行

异步调用实例:消息队列

2、消息队列概念?

消息队列是一个存放消息的容器,是应用程序之间的通信方法,只需要读写出入队列的消息来进行通信,无需专用连接来链接它们。

3、消息队列优缺点?

优点:

①解耦

②异步

③削峰

缺点:

①系统可用性降低

②系统复杂性提高

③数据一致性问题

RabbitMQ

1、rabbitmq的逻辑结构

逻辑结构包含:用户、虚拟主机、队列

2、rabbitmq启动事项

需要进入rabbitmq的sbin目录
cd rabbitmq_server-3.7.0/sbin

./rabbitmq-server   //启动rabbitmq

ps aux|grep rabbit  //查看进程(查看rabbitmq进程是否启动)

./rabbitmq-plugins enable rabbitmq_management  //启动rabbitmq的管理系统插件

netstat -tlnp   //查看放行的端口
firewall-cmd --add-port=15672/tcp --permanent   //放行15672端口
firewall-cmd --add-port=5672/tcp --permanent   //放行5672端口
systemctl stop firewalld  //也可以直接关闭防火墙

ifconfig  //查看当前虚拟机ip地址
查出的地址:15672   //对应的rabbitmq地址

注意:.表示执行该文件,./表示执行当前目录下的某个文件

3、rabbitmq用户管理(命令行方式)

./rabbitmqctl add_user tao 123456   //添加用户,用户名为tao,密码为123456

./rabbitmqctl set_user_tags tao administrator  //设置用户权限为administrator

4、rabbitmq的六种模式

①简单模式

生产者将消息发送到队列,一个消费者从队列中取消息,一条消息对应一个消费者

②工作模式

多个消费者尝试接收同一条消息,但是最终只能有一个消费者获取到

③订阅模式

多个消费者同时获取同一条消息,生产者将消息发送到交换机,消费者将自己对应的队列注册到交换机。当生产者发送消息后,所有注册的队列的消费者都可以接收到消息

④路由模式

生产者将消息发送到交换机,消费者的队列在将自己绑定到交换机的时候设置一个key,生产者发送key格式的消息,对应key格式的消费者才能接收消息

⑤Topic模式

⑥RPC模式

5、rabbitmq消息的可靠性(事务、消息确认机制、return机制)

开启事务,会严重导致处理效率低下。

消息确认机制:确认消息是否从发送者发送到交换机

return机制:确认消息是否从交换机分发到队列

6、rabbitmq的消息延迟实现

延迟队列:消息进入到队列后,延迟指定时间才能被消费者消费。

rabbitmq队列不支持延迟队列功能, 但是可以通过TTL(Time To Live)特性模拟延迟队列的功能。

TTL:存活时间(可以设置队列或消息的存活时间,一般设置队列的存活时间)

注:A服务将消息发送到死信队列,消息超时之后,死信队列将消息发送到queue2队列,被B服务消费

delay_exchange:交换机

delay_queue1:死信队列(key为k1)

delay_queue2:消息队列(key为k2)

springboot整合rabbitmq

1、步骤

①导入依

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

②配置application.yml文件

server:
  port: 9001
spring:
  application:
    name: producer
  rabbitmq:
    host: 192.168.224.129
    port: 5672
    virtual-host: host1
    username: tao
    password: 123456

③发送消息(生产者服务)

@Service
public class TestService {

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMsg(String msg){
        //1.发送消息到队列
        amqpTemplate.convertAndSend("queue1",msg);
//        //2.发送消息到交换机(订阅)
//        amqpTemplate.convertAndSend("ex1","",msg);
//
//        //3.发送消息到交换机(路由)
//        amqpTemplate.convertAndSend("ex2","a",msg);
    }
}

④接收消息(消费者服务)

@Service
//@RabbitListener(queues = {"queue1","queue2"})
@RabbitListener(queues = {"queue1"})
public class ReceiveMsgService {
    
    @RabbitHandler
    public void receiveMsg(String msg){
        System.out.println("接收Msg:"+msg);
    }
}

2、使用rabbitmq传递对象

rabbitmq是消息队列,发送和接收都是字符串、字节数据或者序列化对象。

①使用序列化对象传递(对象实现Serializable接口,可以直接传递对象)

生产者
@Service
public class TestService {

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMsg(String msg){
        amqpTemplate.convertAndSend("queue1",goods);
    }
}
消费者
@Service
@RabbitListener(queues = {"queue1"})
public class ReceiveMsgService {

    @RabbitHandler
    public void receiveMsg(Goods goods){
        System.out.println("接收Msg:"+goods);
    }
}

②使用序列化数组传递(对象也需要实现Serializable接口)

生产者
@Service
public class TestService {

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMsg(Goods goods){
        byte[] bytes= SerializationUtils.serialize(goods);
        amqpTemplate.convertAndSend("queue1",bytes);
    }
}
消费者
@Service
@RabbitListener(queues = {"queue1"})
public class ReceiveMsgService {

    @RabbitHandler
    public void receiveMsg(byte[] bytes){
        Goods goods = (Goods)SerializationUtils.deserialize(bytes);
        System.out.println("接收Msg:"+goods);
    }
}

③使用Json字符串传递

生产者
@Service
public class TestService {

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMsg(Goods goods) throws JsonProcessingException{
        ObjectMapper objectMapper = new ObjectMapper();
        String string = objectMapper.writeValueAsString(goods);
        amqpTemplate.convertAndSend("queue1",string );
    }
}
消费者
@Service
@RabbitListener(queues = {"queue1"})
public class ReceiveMsgService {

    @RabbitHandler
    public void receiveMsg(String string) throws JsonProcessingException{
        ObjectMapper objectMapper = new ObjectMapper();
        Goods goods = objectMapper.reaValue(string,Goods.class);
        System.out.println("接收Msg:"+goods);
    }
}

3、springboot中的队列和交换机创建or绑定

@Configuration
public class RabbitMQConfiguration {

    //创建队列queue9
    @Bean
    public Queue queue9() {
        return new Queue("queue9");
    }
    //创建队列queue10
    @Bean
    public Queue queue10() {
        return new Queue("queue10");
    }

    //创建订阅模式交换机
    @Bean
    public FanoutExchange ex5(){
        return new FanoutExchange("ex5");
    }
    //创建路由模式交换机
    @Bean
    public DirectExchange ex6(){
        return new DirectExchange("ex6");
    }

    //绑定队列queue9到订阅模式交换机
    @Bean
    public Binding bindingQueue9(Queue queue9, Queue queue10, DirectExchange ex6){
        return BindingBuilder.bind(queue9).to(ex6).with("k1");
    }
    //绑定队列queue10到订阅模式交换机
    @Bean
    public Binding bindingQueue10(Queue queue9, Queue queue10, DirectExchange ex6){
        return BindingBuilder.bind(queue10).to(ex6).with("k1");
    }
}

4、springboot中实现消息确认机制与return监听机制

server:
  port: 9001
spring:
  application:
    name: producer
  rabbitmq:
    host: 192.168.224.129
    port: 5672
    virtual-host: host1
    username: tao
    password: 123456
    publisher-confirm-type: simple //使用return监听机制
    publisher-returns: true //开启消息确认模式

接收是否消息确认、return机制的返回信息

@Component
public class PublisherConfireAndReturnConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {

    Logger logger = LoggerFactory.getLogger(PublisherConfireAndReturnConfig.class);

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void initMethod(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String s) {
        if(ack){
            logger.info("--------消息发送(到交换机)成功");
        }else{
            logger.warn("--------消息发送(到交换机)失败");
        }
    }

    @Override
    public void returnedMessage(Message message, int i, String s, String s1, String s2) {
        logger.info("~~~~~~~~消息发送到交换机但未分发到队列!!!");
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值