SpringBoot 集成阿里云 RocketMQ 实战之快速入门

RocketMQ 是什么

Github 上关于 RocketMQ 的介绍:
RcoketMQ 是一款低延迟、高可靠、可伸缩、易于使用的消息中间件。具有以下特性:

支持发布/订阅(Pub/Sub)和点对点(P2P)消息模型
在一个队列中可靠的先进先出(FIFO)和严格的顺序传递
支持拉(pull)和推(push)两种消息模式
单一队列百万消息的堆积能力
支持多种消息协议,如 JMS、MQTT 等
分布式高可用的部署架构,满足至少一次消息传递语义
提供 docker 镜像用于隔离测试和云集群部署
提供配置、指标和监控等功能丰富的 Dashboard
对于这些特性描述,大家简单过一眼就即可,深入学习之后自然就明白了。

专业术语

Producer

消息生产者,生产者的作用就是将消息发送到 MQ,生产者本身既可以产生消息,如读取文本信息等。也可以对外提供接口,由外部应用来调用接口,再由生产者将收到的消息发送到 MQ。

Producer Group

生产者组,简单来说就是多个发送同一类消息的生产者称之为一个生产者组。在这里可以不用关心,只要知道有这么一个概念即可。

Consumer

消息消费者,简单来说,消费 MQ 上的消息的应用程序就是消费者,至于消息是否进行逻辑处理,还是直接存储到数据库等取决于业务需要。

Consumer Group

消费者组,和生产者类似,消费同一类消息的多个 consumer 实例组成一个消费者组。

Topic

Topic 是一种消息的逻辑分类,比如说你有订单类的消息,也有库存类的消息,那么就需要进行分类,一个是订单 Topic 存放订单相关的消息,一个是库存 Topic 存储库存相关的消息。

Message

Message 是消息的载体。一个 Message 必须指定 topic,相当于寄信的地址。Message 还有一个可选的 tag 设置,以便消费端可以基于 tag 进行过滤消息。也可以添加额外的键值对,例如你需要一个业务 key 来查找 broker 上的消息,方便在开发过程中诊断问题。

Tag

标签可以被认为是对 Topic 进一步细化。一般在相同业务模块中通过引入标签来标记不同用途的消息。

Broker

Broker 是 RocketMQ 系统的主要角色,其实就是前面一直说的 MQ。Broker 接收来自生产者的消息,储存以及为消费者拉取消息的请求做好准备。

Name Server

Name Server 为 producer 和 consumer 提供路由信息

Tag

标签可以被认为是对 Topic 进一步细化。一般在相同业务模块中通过引入标签来标记不同用途的消息。

Broker

Broker 是 RocketMQ 系统的主要角色,其实就是前面一直说的 MQ。Broker 接收来自生产者的消息,储存以及为消费者拉取消息的请求做好准备。

Name Server

Name Server 为 producer 和 consumer 提供路由信息

一、实战代码

1、添加依赖


  <!-- mq -->
<dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>ons-client</artifactId>
     <version>1.7.2.Final</version>
  </dependency>

2、配置属性类,和PropertyKeyConst一样,添加自己的属性


#mq com.aliyun.openservices.ons.api.PropertyKeyConst
aliyun.rabbitmq.AccessKey=key #设置自己的配置
aliyun.rabbitmq.SecretKey=key
aliyun.rabbitmq.ConsumerId=test_ConsumerId
aliyun.rabbitmq.ProducerId=test_ProducerId
aliyun.rabbitmq.Topic=test_topic
aliyun.rabbitmq.Tag=test_tag

package com.xyy.ec.order.business.mq;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
import java.util.Properties;
 
/**
 * @Auther: willow
 * @Date: 2018/9/14 11:09
 * @Description: see com.aliyun.openservices.ons.api.PropertyKeyConst
 */
@ConfigurationProperties(prefix = "aliyun.rabbitmq")
public class RabbitMqProperties extends Properties {
 
    /**
     * 消费模式,包括集群模式、广播模式
     */
    public static final String MessageModel = "MessageModel";
 
    /**
     * Producer的标识
     */
    public static final String ProducerId = "ProducerId";
 
    /**
     * Consumer的标识
     */
    public static final String ConsumerId = "ConsumerId";
    /**
     * AccessKey, 用于标识、校验用户身份
     */
    public static final String AccessKey = "AccessKey";
 
    /**
     * SecretKey, 用于标识、校验用户身份
     */
    public static final String SecretKey = "SecretKey";
 
    /**
     * 消息发送超时时间,如果服务端在配置的对应时间内未ACK,则发送客户端认为该消息发送失败。
     */
    public static final String SendMsgTimeoutMillis = "SendMsgTimeoutMillis";
 
    /**
     * 消息队列服务接入点
     */
    public static final String ONSAddr = "ONSAddr";
 
    /**
     * Name Server地址
     */
    public static final String NAMESRV_ADDR = "NAMESRV_ADDR";
 
    /**
     * 消费线程数量
     */
    public static final String ConsumeThreadNums = "ConsumeThreadNums";
 
    /**
     * 设置客户端接入来源,默认ALIYUN
     */
    public static final String OnsChannel = "OnsChannel";
 
    /**
     * 消息类型,可配置为NOTIFY、METAQ
     */
    public static final String MQType = "MQType";
    /**
     * 是否启动vip channel
     */
    public static final String isVipChannelEnabled = "isVipChannelEnabled";
 
    /**
     * 顺序消息消费失败进行重试前的等待时间 单位(毫秒)
     */
    public static final String SuspendTimeMillis = "suspendTimeMillis";
 
    /**
     * 消息消费失败时的最大重试次数
     */
    public static final String MaxReconsumeTimes = "maxReconsumeTimes";
 
    /**
     * 设置每条消息消费的最大超时时间,超过这个时间,这条消息将会被视为消费失败,等下次重新投递再次消费. 每个业务需要设置一个合理的值. 单位(分钟)
     */
    public static final String ConsumeTimeout = "consumeTimeout";
    /**
     * 设置事务消息的第一次回查延迟时间
     */
    public static final String CheckImmunityTimeInSeconds = "CheckImmunityTimeInSeconds";
 
    /**
     * 是否每次请求都带上最新的订阅关系
     */
    public static final String PostSubscriptionWhenPull = "PostSubscriptionWhenPull";
 
    /**
     * BatchConsumer每次批量消费的最大消息数量, 默认值为1, 允许自定义范围为[1, 32], 实际消费数量可能小于该值.
     */
    public static final String ConsumeMessageBatchMaxSize = "ConsumeMessageBatchMaxSize";
 
    /**
     * Consumer允许在客户端中缓存的最大消息数量,默认值为5000,设置过大可能会引起客户端OOM,取值范围为[100, 50000]
     * <p>
     * 考虑到批量拉取,实际最大缓存量会少量超过限定值
     * <p>
     * 该限制在客户端级别生效,限定额会平均分配到订阅的Topic上,比如限制为1000条,订阅2个Topic,每个Topic将限制缓存500条
     */
    public static final String MaxCachedMessageAmount = "maxCachedMessageAmount";
 
    /**
     * Consumer允许在客户端中缓存的最大消息容量,默认值为512 MiB,设置过大可能会引起客户端OOM,取值范围为[16, 2048]
     * <p>
     * 考虑到批量拉取,实际最大缓存量会少量超过限定值
     * <p>
     * 该限制在客户端级别生效,限定额会平均分配到订阅的Topic上,比如限制为1000MiB,订阅2个Topic,每个Topic将限制缓存500MiB
     */
    public static final String MaxCachedMessageSizeInMiB = "maxCachedMessageSizeInMiB";
 
    /**
     * MQ消息轨迹开关
     */
    public static final String MsgTraceSwitch = "MsgTraceSwitch";
    /**
     * Mqtt消息序列ID
     */
    public static final String MqttMessageId = "mqttMessageId";
 
    /**
     * Mqtt消息
     */
    public static final String MqttMessage = "mqttMessage";
 
    /**
     * Mqtt消息保留关键字
     */
    public static final String MqttPublishRetain = "mqttRetain";
 
    /**
     * Mqtt消息保留关键字
     */
    public static final String MqttPublishDubFlag = "mqttPublishDubFlag";
 
    /**
     * Mqtt的二级Topic,是父Topic下的子类
     */
    public static final String MqttSecondTopic = "mqttSecondTopic";
 
    /**
     * Mqtt协议使用的每个客户端的唯一标识
     */
    public static final String MqttClientId = "clientId";
 
    /**
     * Mqtt消息传输的数据可靠性级别
     */
    public static final String MqttQOS = "qoslevel";
 
 
    //my properties
 
    public static final  String Topic="";
 
    public static final  String Tag="";
 
   
 
}

3、mq主配置文件

package com.xyy.ec.order.business.mq;
 
import com.aliyun.openservices.ons.api.MessageListener;
import com.aliyun.openservices.ons.api.bean.ConsumerBean;
import com.aliyun.openservices.ons.api.bean.OrderConsumerBean;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.aliyun.openservices.ons.api.bean.Subscription;
import com.aliyun.openservices.ons.api.order.MessageOrderListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import java.util.HashMap;
import java.util.Map;
 
 
/**
 * @Auther: willow
 * @Date: 2018/9/14 11:06
 * @Description: see ProducerImpl
 */
@Configuration
@EnableConfigurationProperties(RabbitMqProperties.class)
public class RocketMQProducerConfiguration {
 
 
    @Autowired
    public RabbitMqProperties properties;
 
 
     /**
     * mq 生产者
      * @param
     * @return
     */
    @Bean(initMethod="start",destroyMethod="shutdown")
    public ProducerBean producerBean(){
        ProducerBean producerBean=new ProducerBean();
        producerBean.setProperties(properties);
        return  producerBean;
    }
 
 
 
    /**
     * 消费者
     * @return
     */
    @Bean(initMethod = "start", destroyMethod = "shutdown")
    public OrderConsumerBean getConsumer() {
        OrderConsumerBean consumerBean = new OrderConsumerBean();
        consumerBean.setProperties(properties);
        Subscription subscription = new Subscription();
        subscription.setTopic(properties.get("Topic").toString());
        subscription.setExpression(properties.get("Tag").toString());
        Map<Subscription, MessageOrderListener> map = new HashMap();
        map.put(subscription, new OrderMessageListener()); //添加监听器
        consumerBean.setSubscriptionTable(map);
        return  consumerBean;
    }
}

4、mq生产者

package com.xyy.ec.order.business.mq;
 
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.SendResult;
import com.aliyun.openservices.ons.api.exception.ONSClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
 
/**
 * @Auther: hamer
 * @Date: 2018/9/14 14:07
 * @Description:
 */
@Component
public class AliMQService {
 
    private static final Logger logger = LoggerFactory.getLogger(AliMQService.class);
 
    @Autowired
    private Producer producer;
    @Autowired
    public RabbitMqProperties properties;
 
    // 发送消息
    public void sendMessage(String body){
        try {
            Message msg = new Message(properties.get("Topic").toString(), properties.get("Tag").toString(), body.getBytes("UTF-8"));
            SendResult sendResult = producer.send(msg);
            if (sendResult != null) {
                logger.info("消息发送成功:"+body+"result"+ sendResult.toString());
            }
        } catch (ONSClientException e) {
            logger.info("消息发送失败:", e);
            // 出现异常意味着发送失败,为了避免消息丢失,建议缓存该消息然后进行重试。
        }catch (Exception e){
            e.printStackTrace();
            logger.error("发送失败,Topic:{},Tag:{}body为{}",new Object[]{properties.get("Topic").toString(), properties.get("Tag").toString(),body});
        }
    }
}

5、mq 消费者

package com.xyy.ec.order.business.mq;
 
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.order.ConsumeOrderContext;
import com.aliyun.openservices.ons.api.order.MessageOrderListener;
import com.aliyun.openservices.ons.api.order.OrderAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;
 
 
/**
 * mq 订单消费者
 */
@Component
public class OrderMessageListener implements MessageOrderListener {
	
	private static final Logger logger = LoggerFactory.getLogger(OrderMessageListener.class);
	
 
	public OrderAction consume(Message message, ConsumeOrderContext context) {
		String data = null;
		try {
			byte[] body = message.getBody();
			data=new String(body,"UTF-8");
			logger.info("####消费成功"+data);
			return OrderAction.Success;
		} catch (DuplicateKeyException e) {
			//重复消费, 此时是订单orderNo重复,此处应返回成功
			logger.warn("重复消费,主键重复,异常为{},订单号为:{},message:{}",e);
			return OrderAction.Suspend;
		}catch (Exception e) {
			e.printStackTrace();
		 //	logger.error("消费失败,异常为{},订单号为:{},message为:{}",e,orderNo,message);
			return OrderAction.Suspend;
		}
    }
 
 
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值