RocketMq 基础

目录

1、收发消息

2、顺序消息

3、修改nameserver端口

4、rocketmq-console打包

5、集群部署

6、路径配置

7、一些疑问


1、收发消息

1、启动nameserver和broker之后(为了可视化方便还可以启动console)

2、maven依赖

    <dependencies>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.1.0-incubating</version>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-common</artifactId>
            <version>4.1.0-incubating</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.36.Final</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>

3、生产者

import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;

public class ProducerMain {
    public static void main(String[] args) {
        //需要一个producer group名字作为构造方法的参数,这里为producer1
        DefaultMQProducer producer = new DefaultMQProducer("producer1");
        //设置NameServer地址,此处应改为实际NameServer地址,多个地址之间用;分隔
        //NameServer的地址必须有,但是也可以通过环境变量的方式设置,不一定非得写死在代码里
        producer.setNamesrvAddr("127.0.0.1:9876");
        producer.setVipChannelEnabled(false);
        //为避免程序启动的时候报错,添加此代码,可以让rocketMq自动创建topickey
        producer.setCreateTopicKey("AUTO_CREATE_TOPIC_KEY");
        try {
            producer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < 10; i++) {
            try {
                Message message = new Message("TopicTest", "Tag1",
                        ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
                SendResult sendResult = producer.send(message);
                System.out.println(sendResult.toString());
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        producer.shutdown();
    }
}

4、消费者

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class ConsumerMain {
    public static void main(String[] args) {
        //设置消费者组
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_LRW_DEV_SUBS");
        consumer.setVipChannelEnabled(false);
        consumer.setNamesrvAddr("127.0.0.1:9876");
        //设置消费者端消息拉取策略,表示从哪里开始消费
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

        //设置消费者拉取消息的策略,*表示消费该topic下的所有消息,也可以指定tag进行消息过滤
        try {
            consumer.subscribe("TopicTest", "*");
        } catch (MQClientException e) {
            e.printStackTrace();
        }

        //消费者端启动消息监听,一旦生产者发送消息被监听到,就打印消息,和rabbitmq中的handlerDelivery类似
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                for (MessageExt messageExt : msgs) {
                    System.out.println(messageExt.toString());
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });

        //调用start()方法启动consumer
        try {
            consumer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
        System.out.println("Consumer Started....");
    }
}

5、控制台

因为在生产者使用完之后会调用shutdown,所以在控制台是查询不到当前生产组的生产者内容;

6、报错

org.apache.rocketmq.client.exception.MQClientException: No route info of this ***

命令行手动创建Topic就好了

>mqadmin updateTopic -n localhost:9876 -b localhost:10911 -t TopicTest

7、DefaultMQPullConsumer

import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.consumer.PullResultExt;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class PullConsumer {
    private static final Map<MessageQueue, Long> offsetTable = new HashMap<MessageQueue, Long>();

    public static void main(String[] args) {
        DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("pullConsumer");
        consumer.setNamesrvAddr("127.0.0.1:9876");
        try {
            consumer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
        try {
            Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("TopicTest");
            for(MessageQueue mq:mqs) {
                System.out.println("Consume from the queue: " + mq);
                //	long offset = consumer.fetchConsumeOffset(mq, true);
                //	PullResultExt pullResult =(PullResultExt)consumer.pull(mq, null, getMessageQueueOffset(mq), 32);
                //消息未到达默认是阻塞10秒,private long consumerPullTimeoutMillis = 1000 * 10;
                PullResultExt pullResult = null;
                try {
                    pullResult = (PullResultExt)consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                } catch (RemotingException e) {
                    e.printStackTrace();
                } catch (MQBrokerException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                switch (pullResult.getPullStatus()) {
                    case FOUND:
                        List<MessageExt> messageExtList = pullResult.getMsgFoundList();
                        for (MessageExt m : messageExtList) {
                            System.out.println(new String(m.getBody()));
                        }
                        break;
                    case NO_MATCHED_MSG:
                        break;
                    case NO_NEW_MSG:
                        break ;
                    case OFFSET_ILLEGAL:
                        break;
                    default:
                        break;
                }
            }
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }


    private static void putMessageQueueOffset(MessageQueue mq, long offset) {
        offsetTable.put(mq, offset);
    }

    private static long getMessageQueueOffset(MessageQueue mq) {
        Long offset = offsetTable.get(mq);
        if (offset != null)
            return offset;
        return 0;
    }
}

2、顺序消息

顺序消费分为全局顺序和局部顺序,全局顺序就只有一个orderId,局部顺序就是多个orderId(同一个orderId内保证顺序)

Producer

//需要一个producer group名字作为构造方法的参数,这里为producer1
        DefaultMQProducer producer = new DefaultMQProducer("producer1");

        //设置NameServer地址,此处应改为实际NameServer地址,多个地址之间用;分隔
        //NameServer的地址必须有,但是也可以通过环境变量的方式设置,不一定非得写死在代码里
        producer.setNamesrvAddr("127.0.0.1:9876;127.0.0.1:12345");
        producer.setVipChannelEnabled(false);

        //为避免程序启动的时候报错,添加此代码,可以让rocketMq自动创建topickey
        producer.setCreateTopicKey("TopicTest");
        try {
            producer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < 10; i++) {
            try {
                Message message = new Message("TopicTest", "Order", "20200311",
                        ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
                SendResult sendResult = producer.send(message, new MessageQueueSelector() {
                    public MessageQueue select(List<MessageQueue> list, Message message, Object o) {
                        Integer id = (Integer) o;
                        int index = id % list.size();
                        return list.get(index);
                    }
                }, 1);
                System.out.println(sendResult.toString());
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        producer.shutdown();

consumer

//设置消费者组
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer1");
        consumer.setVipChannelEnabled(false);
        consumer.setNamesrvAddr("127.0.0.1:9876;127.0.0.1:12345");
        //设置消费者端消息拉取策略,表示从哪里开始消费
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //设置消费者拉取消息的策略,*表示消费该topic下的所有消息,也可以指定tag进行消息过滤
        try {
            consumer.subscribe("TopicTest", "*");
        } catch (MQClientException e) {
            e.printStackTrace();
        }
        //消费者端启动消息监听,一旦生产者发送消息被监听到,就打印消息,和rabbitmq中的handlerDelivery类似
        consumer.registerMessageListener(new MessageListenerOrderly() {
            public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
                for (MessageExt messageExt : list) {
                    System.out.println(new String(messageExt.getBody()));
                }
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });
        //调用start()方法启动consumer
        try {
            consumer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
        System.out.println("Consumer Started....");

3、修改nameserver端口

start mqnamesrv.cmd -c nameserver.properties

启动breoker:

start mqbroker.cmd -n 127.0.0.1:12345 autoCreateTopicEnable=true

4、rocketmq-console打包

去掉test

5、集群部署

nameserver集群:有自己的独立配置(端口不同即可),参考3

broker集群:这里举例最简单的master无slave模式,修改响应的配置文件即可

 所属集群名字
brokerClusterName=DefaultCluster
 broker名字,他的slave也叫broker-a
brokerName=broker-a
 0 表示 Master,>0 表示 Slave
brokerId=0
 删除文件时间点,默认凌晨 4点
deleteWhen=04
 文件保留时间,默认 48 小时
fileReservedTime=48
 Broker的角色,ASYNC_MASTER异步复制,SYNC_MASTER 同步双写,SLAVE从机
brokerRole=ASYNC_MASTER
 刷盘方式,ASYNC_FLUSH异步刷盘,SYNC_FLUSH同步刷盘
flushDiskType=ASYNC_FLUSH
 Broker 对外服务的监听端口(如果是同一台机器部署集群,跨度要大一点。配置10911后10912默认也被占用)
listenPort=10911
 存储路径
storePathRootDir=/data/rocketmq/store/rootdir-a-m
 commitLog 存储路径
storePathCommitLog=/data/rocketmq/store/commitlog-a-m
 nameServer地址,分号分割
namesrvAddr=127.0.0.1:12345;127.0.0.1:9876
 是否允许Broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true

 检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
 消费队列存储路径存储路径
storePathConsumeQueue=/usr/local/rocketmq/store/broker-a/consumequeue
 消息索引存储路径
storePathIndex=/usr/local/rocketmq/store/broker-a/index
 checkpoint 文件存储路径
storeCheckpoint=/usr/local/rocketmq/store/checkpoint
 abort 文件存储路径
abortFile=/usr/local/rocketmq/store/abort
 限制的消息大小
maxMessageSize=65536
 发消息线程池数量
sendMessageThreadPoolNums=128
 拉消息线程池数量
pullMessageThreadPoolNums=128
 commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
 ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000

broker指定配置文件:

start mqbroker.cmd -c ../conf/2m-noslave/broker-b.properties

6、路径配置

broker的存储路径参考4

日志路径修改一下即可

rocket-console的日志同理修改项目的

7、一些疑问

rocketmq-console启动后会占用C盘的空间(至少3g),为啥?什么占用的,在哪设置

生产消息时候指定的生产者组,在rocketmq-console生产者中却检索不到,为啥?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值