RabbitMq

RabbitMq 消息队列: 用来存放消息的队列

安装,管理后台

1 安装 下载otp + rabbitmq

2 先安装otp, 再安装rabbitmq

3 访问http://127.0.0.1:15672

​ 如果无法访问:

​ 3.1 检查任务管理器中的服务, rabbitmq是否开启

​ 3.2 调整rabbit管理后台的配置

​ 在cmd模式下,进入rabbitmq的安装根目录切入sbin目录

​ 执行命令: rabbitmq-plugins enable rabbitmq_management

4 使用游客账号登录: guest guest

添加用户

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1GYXpJ11-1603278679953)(file:///C:\Users\admin\AppData\Roaming\Tencent\Users\1125400943\QQ\WinTemp\RichOle\6IDSYSJS1P}RT$TV4BH}OZG.png)]

img

RabbitMQ角色

RabbitMQ的用户角色分类
none、management、 policymaker、 monitoring、 administrator
none
不能访问management plugin

management

1.用户可以通过AMQP做的任何事外加:
2.列出自己可以通过AMQP登入的virtual hosts
3.查看自己的virtual hosts中的queues, exchanges和bindings
4.查看和关闭自己的channels和connections
5.查看有关自己的virtual hosts的 “全局”的统计信息,包含其他用户在这些virtual,
hosts中的活动。

administrator

policymaker和monitoring可以做的任何事外加:
创建和删除virtual hosts
查看、创建和删除users
查看创建和删除permissions
关闭其他用户的connections

端口

RabbitMQ会绑定一-些端口,安装完后,需要将这些端口添加至防火墙。
25672
用于RabbitMQ节点间和CLII具通信,配合4369使用。
15672
HTTP_ _API端口,管理员用户才能访问,用于管理RabbitMQ,需要启用management插件。
15674
基于WebSocket的STOMP客户端端口(当 插件Web STOMP启用的时候打开)
15675
基于WebSocket的MQTT客户端端口(当 插件Web MQTT启用的时候打开)

消息队列的好处

1 解耦

​ 技术层面的解耦: 下单 在同一个service中写, 商品,订单,消费记录. - service… 代码简洁,结构清晰了,可维护性更高了

​ 业务层面的解耦: 下单 – 暂停 – 系统处理能力有限 , 我有条不紊的

​ 事务 – 锁 – 数据库中的记录

MQ编码:

1 引入mq的jar

​ 添加rabbitmq相关的系统配置

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

系统配置文件:

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: lyj
    password: lyj

2 写mq的配置类

​ 创建队列 : Queue

​ 创建交换机 : DirectExchange(直连型交换机)

​ 将消息队列与交换机进行绑定 : Binding

新建mq的包
新建DirectRabbitConfig类, 一定要加上@Configuration标识为配置类

	
package com.bdqn.order.util.mq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DirectRabbitConfig {
    private static Logger log = LoggerFactory.getLogger(DirectRabbitConfig.class);
    @Autowired
    private CachingConnectionFactory connectionFactory;

    //队列 起名:operLogQueue
    @Bean
    public Queue operLogQueue() {
        return new Queue("operLogQueue",true);  //true 是否持久
    }

    //Direct交换机 起名:OperLogExchange
    @Bean
    DirectExchange OperLogExchange() {
        return new DirectExchange("OperLogExchange");
    }

    //绑定  将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
    @Bean
    Binding bindingDirect() {
        return BindingBuilder.bind(operLogQueue()).to(OperLogExchange()).with("OperLogRouting");
    }

    @Bean
    public RabbitTemplate rabbitTemplate(){
        //若使用confirm-callback或return-callback,必须要配置publisherConfirms或publisherReturns为true
        //每个rabbitTemplate只能有一个confirm-callback和return-callback,如果这里配置了,那么写生产者的时候不能再写confirm-callback和return-callback
        //使用return-callback时必须设置mandatory为true,或者在配置中设置mandatory-expression的值为true
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setPublisherReturns(true);
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMandatory(true);
//        /**
//         * 如果消息没有到exchange,则confirm回调,ack=false
//         * 如果消息到达exchange,则confirm回调,ack=true
//         * exchange到queue成功,则不回调return
//         * exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
//         */
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if(ack){
                    log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
                }else{
                    log.info("消息发送失败:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
                }
            }
        });
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message);
            }
        });
        return rabbitTemplate;
    }
}

3 发送消息

​ 消息的生产者, 发送一条新消息

@Autowired 
RabbitTemplate rabbitTemplate;

rabbitTemplate.convertAndSend("OperLogExchange","OperLogRouting", map);
三个参数: 1 : 交换机  2 消息队列绑定的路由键 3 消息的内容

发送消息的内容如果包含了自己定的封装类,如 UserInfo (实体, pojo),必须实现 implements Serializable接口

4 获取消息

​ 消息的消费者, 监听消息队列, 有新消息就获取, 并删除已获取的消息

// 在某个service上加上注解, 将某个service标识为消息队列的消费者
@RabbitListener(queues = "operLogQueue")

// 在这个service中还需绑定消息的处理方法,当消息队列中有新的消息时,将调用绑定的方法
@RabbitHandler
----------------------------------------------------
@Service
@RabbitListener(queues = "operLogQueue")
public class OperLogServiceImpl implements OperLogService {

    @Resource
    OperLogMapper operLogMapper;

    @Override
    public int addOperLog(OperLog log) {
        return operLogMapper.insertSelective(log);
    }

    @RabbitHandler
    public void addMqOperLog(Map map) {
        UserInfo u = (UserInfo)map.get("user");

        OperLog log = new OperLog();
        log.setOprType("登录");
        log.setOprName(u.getUserName() + "进行登陆");
        log.setCreateTime(new Date());

        operLogMapper.insertSelective(log);
    }
}



5 消息在消费过程中,出现异常了怎么办

5核心对象

1.Queue: 真正储存数据的地方

2.Exchange:接收请求,转存数据

3.Bind:收到请求后储存到哪里

4.消息生产者: 发送数据的应用

5.消息消费者:去除数据处理的应用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值