RabbitMQ使用入门

本文详细介绍了如何在Docker中部署RabbitMQ,包括下载镜像、启动容器、端口映射以及处理可能出现的问题。同时,文章也展示了在SpringBoot应用中如何配置RabbitMQ,包括添加依赖、设置MQ配置、创建生产者回调、配置交换机和队列。此外,还提到了安全设置,如添加用户和分配角色,以及如何卸载RabbitMQ。
摘要由CSDN通过智能技术生成

 1.环境准备

1.1 docker中配置

下载镜像:docker pull rabbitmq:management

创建实例并启动:

docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -p 25672:25672 rabbitmq:management

 The container name "/rabbitmq" is already in use by container "d1932f0cfb1b355a0df768e86a5c175eb02810f6d0ab42ff0945ba5bccbc144c"

如果报错上面问题,运行命令docker ps -a 检查一下是否存在容器中,可以运行命令docker rm 加容器id删除后重新运行启动命令

注: 4369 -- erlang发现口 5672 --client端通信口

15672 -- 管理界面ui端口 25672 -- server间内部通信口

1.2 或使用安装包安装并配置

安装Erlang、Socat、RabbitMQ(提前准备好安装包到指定解压目录)

执行安装命令:

rpm -ivh erlang-21.3.8.9-1.el7.x86_64.rpm

rpm -ivh socat-1.7.3.2-1.el6.lux.x86_64.rpm 

rpm -ivh  rabbitmq-server-3.8.1-1.el7.noarch.rpm
#如果rabbitmq安装报错,在线安装socat
yum install -y socat

安装成功后rabbitmq命令存放在:/usr/lib/rabbitmq/lib/rabbitmq_server-3.8.1/sbin

启用管理插件

rabbitmq-plugins enable rabbitmq_management

RabbitMQ启停命令

# 第一次启动时会比较慢
systemctl start rabbitmq-server.service

systemctl status rabbitmq-server.service

systemctl restart rabbitmq-server.service

systemctl stop rabbitmq-server.service 

查看进程

ps -ef | grep rabbitmq

rabbitmq启动时会监听三个端口号:

5672: 其他程序和rabbitmq交互的端口[比如:java程序需要使用rabbitmq,就和此端口建立连接]

15672:rabbitmq的后台管理系统的端口号[rabbitmq的客户端]

25672:集群环境搭建的端口号

测试

在web浏览器中输入地址:http://虚拟机ip:15672/

输入默认账号: guest : guest,默认不允许远程连接

解决:

增加管理员账号:

adminrabbitmqctl add_user admin admin

 

 

 

如果新增慢,然后报错新增失败,解决方案: //查询当前主机的名称
cat /etc/hostname
//将主机名称和本机的ip 127.0.0.1绑定映射存到hosts文件中
vim /etc/hosts
127.0.0.1    查询到的主机名称
//然后再次添加用户
rabbitmqctl add_user admin admin

给账号分配角色: # 角色:
# 1、超级管理员(administrator):所有权限
# 2、监控者(monitoring): 登录控制台、查看mq信息权限
# 3、策略制定者(policymaker):登录控制台、管理policy权限
# 4、普通管理者(management):只能登录控制台
rabbitmqctl set_user_tags admin administrator

修改角色密码: rabbitmqctl change_password admin 123456

查看用户列表:rabbitmqctl list_users

测试,使用新建账号登录

overview:概览

connections:无论生产者还是消费者,都需要与RabbitMQ建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况

channels:通道,建立连接后,会形成通道,消息的投递获取依赖通道。

Exchanges:交换机,用来实现消息的路由

Queues:队列,即消息队列,消息存放在队列中,等待消费,消费后被移除队列。

端口:

5672: rabbitMq的编程语言客户端连接端口

15672:rabbitMq管理界面端口

25672:rabbitMq集群的端口

卸载过程步骤

1、停止rabbitmq服务

systemctl stop rabbitmq-server

2、卸载erlang 查看erlang安装的相关列表

yum list|grep erlang

卸载erlang所有内容

yum -y remove erlang-*

删除erlang目录

rm -rf /usr/lib64/erlang

3、卸载rabbitmq 查看rabbitmq安装的相关列表

yum list|grep rabbitmq

卸载rabbitmq所有内容

yum -y remove rabbitmq-server.noarch

查找并删除rabbitmq相关目录

find / -name rabbit*

依次删除对应目录:rm -rf 路径 例如:

rm -rvf /var/lib/rabbitmq
rm -rvf /usr/lib/rabbitmq
rm -rvf /var/log/rabbitmq

2.项目模块中

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
spring:
   rabbitmq: #mq配置
    host: 192.168.36.131
    port: 5672
    username: wangbaomin
    password: abcd1234
    virtual-host: /srb
    # 生产者确认回调:确保消息可以到达交换机/队列
    publisher-confirm-type: simple
    publisher-returns: true

2.1 业务类新建配置类创建生产者回调 (引入同样的依赖)

@Configuration
@Slf4j
public class MqConfig {
    //生产者回调
    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init(){
        //setReturnCallback点进去,ReturnCallback点进去,查看实现类中有且仅有一个抽象方法,称为函数式接口,隐式转换为lambda表达式让代码看起来比较简洁

        //消息未到达队列的回调
        rabbitTemplate.setReturnCallback((Message message, int replyCode,
                                          String replyText, String exchange, String routingKey)->{
        //未到达队列可以记录日志分析错误原因
            // mq的消息可以是对象、集合、字符串:可以将字节数组转为base64的字符串传递
            log.error("消息未到达队列: replyCode={} ,replyText={} , " +
                    "exchange={} , routingKey={}, message={}",replyCode,replyText,exchange,routingKey, new String(Base64.getEncoder().encode(message.getBody())));

        });
        //消息是否到达交换机的回调
        rabbitTemplate.setConfirmCallback((@NonNull CorrelationData correlationData, boolean ack, @Nullable String cause)->{

            if(!ack){
                //消息未到达交换机
                log.error("消息未到达交换机:{}",cause);
            }
        });

    }

    //配置交换机
    @Bean
    public Exchange smsExchange(){
        return ExchangeBuilder.topicExchange(SrbConst.SMS_EXCHANGE)//交换机的名字,配合常量使用
                .ignoreDeclarationExceptions()
                .durable(true)
                .build();
    }

    @Bean
    public MessageConverter messageConverter(){
        //json字符串转换器
        return new Jackson2JsonMessageConverter();
    }
}

2.2 配置模块中配置交换机队列名称的常量类

public interface SrbConst {
    String SMS_EXCHANGE = "sms.exchange";
    String SMS_QUEUE = "sms.queue";
    String SMS_ROUTING_KEY = "sms.send";
    String SMS_DEAD_EXCHANGE = "sms.dead.exchange";
    String SMS_DEAD_QUEUE = "sms.dead.queue";
    String SMS_DEAD_ROUTING_KEY = "sms.dead.msg";
}


@Data
public class SmsDto {
    @ApiModelProperty("手机号码")
    private String mobile;
    @ApiModelProperty("短信类型:1注册、2登录、3充值成功、4提款成功")
    private Integer type;
    @ApiModelProperty("短信模板需要的参数列表")
    private List<String> params;

}

2.3 短信模块中配值交换机、队列、死信交换机、死信队列、json字符串转换器

@Configuration
public class MqConfig {

    //交换机,队列,死信交换机,死信队列的配置类

    @Bean
    public Exchange smsExchange(){
        return ExchangeBuilder.topicExchange(SrbConst.SMS_EXCHANGE)
                .ignoreDeclarationExceptions()
                .build();
    }

    @Bean
    public Queue smsQueue(){
        return QueueBuilder.durable(SrbConst.SMS_QUEUE)
                .deadLetterExchange(SrbConst.SMS_DEAD_EXCHANGE)
                .deadLetterRoutingKey(SrbConst.SMS_DEAD_ROUTING_KEY)
                .build();
    }

    @Bean
    public Binding smsBinding(Exchange smsExchange, Queue smsQueue){
        return BindingBuilder.bind(smsQueue).to(smsExchange)
                .with(SrbConst.SMS_ROUTING_KEY)
                .noargs();
    }


    //死信交换机 死信队列
    @Bean
    public Exchange deadExchange(){
        return ExchangeBuilder.topicExchange(SrbConst.SMS_DEAD_EXCHANGE)
                .ignoreDeclarationExceptions()
                .build();
    }

    @Bean
    public Queue deadQueue(){
        return QueueBuilder.durable(SrbConst.SMS_DEAD_QUEUE)
                .build();

    }

    @Bean
    public Binding deadBinding(Exchange deadExchange,Queue deadQueue){
       return BindingBuilder.bind(deadQueue).to(deadExchange)
                .with(SrbConst.SMS_ROUTING_KEY)
                .noargs();
    }

    @Bean
    public MessageConverter messageConverter(){
        //json字符串转换器
        return new Jackson2JsonMessageConverter();
    }
}

2.4消息模块中创建消息消费队列监听器

@Component
public class MqListener {
    @Resource
    private SmsService smsService;

    @RabbitListener(queues = {SrbConst.SMS_QUEUE})
    public void sMsSendListener(Message message , Channel channel, SmsDto smsDto) throws IOException {

        //发送信息
        //
        try {
            smsService.sendSrbSms(smsDto);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            if(message.getMessageProperties().isRedelivered()){
                //如果消息是重新投递 再次消费失败 丢弃消息到绑定的死信队列中
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
            }else{
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
            }
        }

    }
}

2.5定义业务层方法实现发送消息

 @Override
    public void sendSrbSms(SmsDto smsDto) {
        String mobile = smsDto.getMobile();
        Integer type = smsDto.getType();
        List<String> params = smsDto.getParams();
        String s = params.get(0);
        String message = null;
        switch (type){
            case 1:
                message="zc";
                break;
            case 2:
                message="dl";
                break;
            case 3:
                message="cz";
                break;
            case 4:
                message="tx";
                break;
            default:
                message="qt";
                break;
        }
        sendMessage(message+s,mobile);
    }



    public void sendMessage(String sixBitRandom ,String phoneNum){
        String host = SmsProperties.HOST;
        String path = SmsProperties.PATH;
        String method = SmsProperties.METHOD;
        String appcode = SmsProperties.APPCODE;
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求,定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        String codeMess = "code:"+ sixBitRandom;
        bodys.put("content", codeMess );
        bodys.put("phone_number", phoneNum);
        bodys.put("template_id", "CST_ptdie100");

        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //获取response的body
            //System.out.println(EntityUtils.toString(response.getEntity()));
            String responseMessage = EntityUtils.toString(response.getEntity());
            System.out.println(responseMessage);//{"status":"OK","request_id":"TIDb9678a03bb664c648e13dcc0ea4b034a"}
            Map map = JSON.parseObject(responseMessage, Map.class);
            String status = map.get("status").toString();
            System.out.println(status);
            if ("OK".equals(status)){
                System.out.println("短信发送成功!");
            }else {
                System.out.println("短信发送失败!");
                throw new SrbException(ResultEnum.ALIYUN_SMS_ERROR);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new SrbException(ResultEnum.ALIYUN_SMS_ERROR);
        }
    }
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值