RocketMQ建议使用规范

目的

解决大型分布式互联网项目消息的使用

规范

一、设计原理

说明:

  1. NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。
  2. Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master可以部署多个。每个Broker与Name Server集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。
  3. Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可以集群部署。
  4. Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。

二、使用教程

1、严格顺序消息的发送与消费

要注意严格顺序消息发送端要向一个queue发送消息,消费端要配置为 ORDERLY 模式,这牺牲了集群的性能。

1、pom.xml配置

<dependency>
  <groupId>com.midea.jr.framework</groupId>
  <artifactId>framework.mq</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency> 


2、Message Producer 端Spring IOC xml配置
<bean id="messageProducer" class="com.midea.finance.framework.message.producer.MideaDefaultMQProducer">
    <property name="namesrvAddr" value="${rocketmq.namesrvAddr}" />
    <property name="producerGroup" value="FINANCE-SMS" /><!-- 这里只要保证集群之间不冲突,集群内部相同配置就可以了 -->
    <property name="retryAnotherBrokerWhenNotStoreOK" value="false" />
</bean> 


3、Message Producer 端代码
// 发送顺序消息,注意这里要持续向其中一个队列发送消息才是严格顺序消息
SendResult sr1 = messageProducer.send( new Message( "finance-sms", "message".getBytes() ), new MessageQueueSelector() {
    @Override
    public MessageQueue select( List<MessageQueue> mqs, Message msg, Object arg ) {
        Integer id = arg.hashCode();
        int index = id % mqs.size();
        return mqs.get( index );
    }
}, 1 ); 


4、Message Consumer 端Spring IOC xml配置
<bean id="defaultMQPushConsumerMessageSelector" class="com.midea.finance.framework.message.selector.DefaultMQPushConsumerMessageSelector">
    <property name="namesrvAddr" value="${rocketmq.namesrvAddr}" />
    <property name="consumerGroup" value="FINANCE-SMS" /><!-- 这里只要保证集群之间不冲突,集群内部相同配置就可以了 -->
    <property name="messageModel" value="CLUSTERING" /><!-- BROADCASTING、CLUSTERING -->
    <property name="messageListener" value="ORDERLY" /><!-- CONCURRENTLY、ORDERLY -->
    <property name="handlermap">
        <map>
            <entry key="finance-sms"><!-- 指定要订阅的topic -->
                <bean class="com.midea.finance.framework.message.handler.DefaultMQMessageHandler" /><!-- 这里需要根据自己的需求实现接口 -->
            </entry>
        </map>
    </property>
</bean> 


3、properties文件配置
rocketmq.namesrvAddr=10.16.68.136:9876;10.16.68.137:9876
2、普通顺序消息的发送与消费

1、pom.xml配置

<dependency>
  <groupId>com.midea.finance.framework</groupId>
  <artifactId>finance.framework.mq</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency> 


2、Message Producer 端Spring IOC xml配置
<bean id="messageProducer" class="com.midea.finance.framework.message.producer.MideaDefaultMQProducer">
    <property name="namesrvAddr" value="${rocketmq.namesrvAddr}" />
    <property name="producerGroup" value="FINANCE-SMS" /><!-- 这里只要保证集群之间不冲突,集群内部相同配置就可以了 -->
    <property name="retryAnotherBrokerWhenNotStoreOK" value="false" />
</bean> 


3、Message Producer 端代码
messageProducer.send( new Message( "finance-sms", "message".getBytes() ) ); 


4、Message Consumer 端Spring IOC xml配置
<bean id="defaultMQPushConsumerMessageSelector" class="com.midea.finance.framework.message.selector.DefaultMQPushConsumerMessageSelector">
    <property name="namesrvAddr" value="${rocketmq.namesrvAddr}" />
    <property name="consumerGroup" value="FINANCE-SMS" /><!-- 这里只要保证集群之间不冲突,集群内部相同配置就可以了 -->
    <property name="messageModel" value="CLUSTERING" /><!-- BROADCASTING、CLUSTERING -->
    <property name="messageListener" value="ORDERLY" /><!-- CONCURRENTLY、ORDERLY -->
    <property name="handlermap">
        <map>
            <entry key="finance-sms"><!-- 指定要订阅的topic -->
                <bean class="com.midea.finance.framework.message.handler.DefaultMQMessageHandler" /><!-- 这里需要根据自己的需求实现接口 -->
            </entry>
        </map>
    </property>
</bean> 


3、properties文件配置
rocketmq.namesrvAddr=10.16.68.136:9876;10.16.68.137:9876
3、非顺序消息的发送与消费

1、pom.xml配置

<dependency>  <groupId>com.midea.finance.framework</groupId>  <artifactId>finance.framework.mq</artifactId>  <version>0.0.1-SNAPSHOT</version></dependency> 

2、Message Producer 端Spring IOC xml配置
<bean id="messageProducer" class="com.midea.finance.framework.message.producer.MideaDefaultMQProducer">
    <property name="namesrvAddr" value="${rocketmq.namesrvAddr}" />
    <property name="producerGroup" value="FINANCE-SMS" /><!-- 这里只要保证集群之间不冲突,集群内部相同配置就可以了 -->
    <property name="retryAnotherBrokerWhenNotStoreOK" value="false" />
</bean> 


3、Message Producer 端代码
messageProducer.send( new Message( "finance-sms", "message".getBytes() ) ); 


4、Message Consumer 端Spring IOC xml配置
<bean id="defaultMQPushConsumerMessageSelector" class="com.midea.finance.framework.message.selector.DefaultMQPushConsumerMessageSelector">
    <property name="namesrvAddr" value="${rocketmq.namesrvAddr}" />
    <property name="consumerGroup" value="FINANCE-SMS" /><!-- 这里只要保证集群之间不冲突,集群内部相同配置就可以了 -->
    <property name="messageModel" value="CLUSTERING" /><!-- BROADCASTING、CLUSTERING -->
    <property name="messageListener" value="CONCURRENTLY" /><!-- CONCURRENTLY、ORDERLY -->
    <property name="handlermap">
        <map>
            <entry key="finance-sms"><!-- 指定要订阅的topic -->
                <bean class="com.midea.finance.framework.message.handler.DefaultMQMessageHandler" /><!-- 这里需要根据自己的需求实现接口 -->
            </entry>
        </map>
    </property>
</bean> 


3、properties文件配置
rocketmq.namesrvAddr=10.16.68.136:9876;10.16.68.137:9876

 

4、Pull消费消息

pull consumer 需要根据业务场景自己进行封装,暂不推荐使用。

/**
 * PullConsumer,订阅消息
 */
public class PullConsumer {
 
 
    //Java缓存
    private static final Map<MessageQueue, Long> offseTable = new HashMap<MessageQueue, Long>();
  
  
    public static void main(String[] args) throws MQClientException {
        DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("PullConsumerGroup");
        consumer.setNamesrvAddr("127.0.0.1:9876");
        consumer.start();
        //拉取订阅主题的队列,默认队列大小是4
        Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("TopicTestMapBody");
        for (MessageQueue mq : mqs) {
            System.out.println("Consume from the queue: " + mq);
            SINGLE_MQ:while(true){
                try {
                      
                    PullResult pullResult = consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                    List<MessageExt> list=pullResult.getMsgFoundList();
                    if(list!=null&&list.size()<100){
                        for(MessageExt msg:list){
                            System.out.println(SerializableInterface.deserialize(msg.getBody()));
                        }
                    }
                    System.out.println(pullResult.getNextBeginOffset());
                    putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                     
                    switch (pullResult.getPullStatus()) {
                    case FOUND:
                        // TODO
                        break;
                    case NO_MATCHED_MSG:
                        break;
                    case NO_NEW_MSG:
                        break SINGLE_MQ;
                    case OFFSET_ILLEGAL:
                        break;
                    default:
                        break;
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
             }
        }
  
        consumer.shutdown();
    }
  
  
    private static void putMessageQueueOffset(MessageQueue mq, long offset) {
        offseTable.put(mq, offset);
    }
  
  
    private static long getMessageQueueOffset(MessageQueue mq) {
        Long offset = offseTable.get(mq);
        if (offset != null){
            System.out.println(offset);
            return offset;
        }
        return 0;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本文档旨在描述 本文档旨在描述 本文档旨在描述 本文档旨在描述 本文档旨在描述 本文档旨在描述 本文档旨在描述 RocketMQ RocketMQ RocketMQRocketMQRocketMQRocketMQ的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 的多个关键特性实现 原理 ,并对 消息中间件 消息中间件 消息中间件 消息中间件 消息中间件 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 遇到的各种问题进行总结,阐述 RocketMQ RocketMQ RocketMQRocketMQRocketMQ 如何解决这些问题。 如何解决这些问题。 如何解决这些问题。 如何解决这些问题。 文中主要引用了 文中主要引用了 文中主要引用了 文中主要引用了 JMSJMSJMS规范规范与 CORBA CORBA CORBA CORBA NotificationNotificationNotificationNotification Notification NotificationNotification 规范规范为我们设计系统指明了 ,规范为我们设计系统指明了 ,规范为我们设计系统指明了 ,规范为我们设计系统指明了 ,规范为我们设计系统指明了 ,规范为我们设计系统指明了 ,规范为我们设计系统指明了 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 方向,但是仍有不少问题规范没提及对于 消息中间件 消息中间件 又至关重要。 又至关重要。 又至关重要。 RocketMQRocketMQ RocketMQRocketMQRocketMQ并不遵循任何规范,但是参考了 并不遵循任何规范,但是参考了 并不遵循任何规范,但是参考了 并不遵循任何规范,但是参考了 并不遵循任何规范,但是参考了 并不遵循任何规范,但是参考了 并不遵循任何规范,但是参考了 并不遵循任何规范,但是参考了 各种规范与 各种规范与 同类 产品的 产品的 设计 思想 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值