rocketmq里面的角色:
rocketmq里面有nameserver,master,broker三种角色
producer(生产者,生产者代码需要自己编写)和consumer(消费者,消费者代码需要自己编写)都需要访问
nameserver,已得知消息存放在的位置,nameserver就相当于分发的作用
master其实也是broker,只是他比较特别,一台master下面可以连着多台broker,消息其实是存于master和broker上
生产消息的过程:
producer生成消息,然后连接上nameserver,发送消息,nameserver会把消息存到负载比较小的master上,
master可以同步(或者异步)的方式把数据写到他下面连着的多台broker上
实际演示:
本教程是在虚拟机的环境下启动rocketmq,且虚拟机的linux系统必须安装 jdk,如没有安装可参看博主写的另一篇教程
如下图:下载rocketmq
上传到linux,关于上传,在那篇教程里也有提及,可参考
这里我上传到目录:/usr/local/other
解压
命令:unzip mq -d /usr/local/other/mq压缩包名称
解压之后如图:
进入rocketmq-4.2.0/bin目录
修改nameserver的配置文件,内存都改成256m 命令:vim runserver.sh
启动 nameserver,命令:nohup ./mqnamesrv &
修改broker的配置文件,内存改成256m 命令:vim runbroker.sh
启动broker
命令:nohup sh mqbroker -n "192.168.56.100:9876" -c ../conf/2m-noslave/broker-a.properties > broker.out &
(192.168.56.100是虚拟机linux的IP,端口号默认是9876,配置里可以改)
查看nameserver管理着哪些broker
命令:./mqadmin clusterList -n 192.168.56.100:9876
为了让producer发送消息到mq集群,关闭虚拟机防火墙:
命令:systemctl stop firewalld.service (否则会报rout找不到信息的错误)
下面是producer的java代码:
package rocketmq; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; public class Producer { public static void main(String[] args) throws Exception{ /** * group是producer所属组的名字,这些组里的producer就有相同的名字,比如都是订单处理 * 发单条消息没什么用,发分布式事务的消息时有用 */ DefaultMQProducer producer = new DefaultMQProducer("group"); producer.setNamesrvAddr("192.168.56.100:9876"); producer.start(); //和nameserver建立远程连接 for (int i = 0; i < 100; i++) { Message m = new Message("orders", ("order"+i).getBytes()); SendResult result = producer.send(m); System.out.println(m + "send out"); System.out.println(result); Thread.sleep(500); } producer.shutdown(); } }右键运行就会发送消息到mq的集群(现在集群里只启动了一台nameserver和一台master)
消费之前先看是否生成了这一个消息topic:
查看是否生成了orders这个topic
命令:./mqadmin topicList -n 192.168.56.100:9876
./mqadmin 会列出所有命令,如果不会用:./mqadmin help xxx命令
下面是consumer端的java代码:
package rocketmq; import java.util.List; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.MessageSelector; 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.common.consumer.ConsumeFromWhere; import org.apache.rocketmq.common.message.MessageExt; public class PushConsumer { public static void main(String[] args) throws Exception { DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumers"); consumer.setNamesrvAddr("192.168.56.100:9876"); consumer.subscribe("orders", MessageSelector.byTag(null)); // 没用tag, 这里传null // 可能监听上去集群上已经与很多消息了,如果这些消息也算监听到的就设置下面的参数,否则从刚监听上去开始算 consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); consumer.registerMessageListener(new MessageListenerConcurrently() { // 这个方法会被集群调用,所以list参数会被消息填满 @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext con) { MessageExt m = list.get(0); System.out.println(new String(m.getBody())); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); consumer.start(); } }
右键运行,就会消费刚才创建的消息
以上消费方式为push的方式,也就是消费者会往集群上注册监听器,只要集群上有订阅的消息就会发给consumer去处理
rocketmq里的消费信息方式?
1.主动拉的方式,consumer连上去,拿消息 ( 用得少,得知道topic, 如果是特定消息还要知道消息位置在第几条 )
2.push cusomer
cusomer启动之后,往集群上注册了一个监听器(观察者模式),当特定的消息比如topic为orders的消息来了
就监听到,就传给consumer处理