这个问题也可以是为什么要使用消息队列,一个东西的诞生,必然是业务的需要。消息队列的主要作用有:
比较容易理解的作用有秒杀系统,当大量请求涌入的时候,可以用消息队列来先存储为消息,并根据系统的承载能力将消息分发给系统进行消费。
这里理解下所谓的消息,因为我以前一直不理解消息是啥东西,其实可以简单理解把JSON数据封装成一个包,然后发送到其他系统,或者可以理解为方法调用时传入的参数,只不过现在只要封装成消息扔给消息队列就行,消息队列把消息给监听了相关主题(Topic)的消费者进行消费。
RocketMQ主要有四个基础部分:
Name Server是注册中心,每个Broker(代理)启动时都会讲自己的信息注册到Name Server上。另外Name Server也是Topic的记录者。所有的Topic都会经过Broker注册到Name Server上,当消费端需要消费数据时,就会从Name Server中获取Topic数据,找到需要从哪个Broker中的哪个队列进行消息的拉取消费,从这里我们也可以大致知道Broker的作用。
namesrv是一个几乎无状态节点,可集群部署,节点间不同步。
Broker是MQ的数据存储关键,当Producer把消息发送到对应的Broker时,Broker会将信息进行存储,放置到日志文件中(commitlog)中。
Broker可以使用Master-Slave模式进行部署,一个Master可以对应多个Slave,一个Slave只能对应一个Master。
每个Broker与Name Server集群中的所有节点建立长连接,定时(默认每隔30s)注册Topic信息到所有的Name Server。Name Server时定时扫描所有存活的Broker连接,如果Name Server超过2分钟没有收到心跳。则Name Server断开与Broker的连接。
Producer作用很简单,根据Name Server中提供的Topic数据,找到需要发送到哪个Broker中,然后发送消息。
Producer于Name Server集群中的其中一个节点建立长连接,定期从Name Server获取Topic路由信息,并向提供Topic服务的Borker-Matser建立长连接,且定时向Master发送心跳。
Producer完全无状态,可集群部署。
Producer每隔 30s(由 ClientConfig 的 pollNameServerInterval 设置)从Name Server获取所有的Topic队列的最新情况,这意味着如果Broker不可用,Producer最多 30s 能够感知,在此期间内发送Broker的所有消息都会失败。
Producer每隔 30s(由 ClientConfig 的 heartbeatBrokerInterval 决定)向所有关联的Broker发送心跳,Broker每隔 10s 扫描所有存活的连接,如果Broker在 2分钟 内没有收到心跳数据,则关闭与Producer的连接。
Consumer即消费者,根据Topic到Broker中拉取数据,进行消费。
Consumer与Name Server集群中的其中一个节点(随机选择)建立长连接,定期从Name Server取Topic路由信息,并向提供Topic服务的Broker-Master、Broker-Slave建立长连接,且定时向Broker-Master、Broker-Slave发送心跳。Consumer既可以从Broker-Slave中订阅消息,也可以从Broker-Slave中订阅消息,订阅规则由Broker配置决定。
Consumer每隔 30s 从Name Server获取Topic的最新队列情况,这意味着Broker不可用时,Consumer最多需要30s才能感知到。
Consumer每隔 30s(由 ClientConfig 中 heartbeatBrokerInterval 决定)向所有关联的broker发送心跳,Broker每隔10s扫描所有存活的连接,若某个连接2分钟内没有发送心跳数据,则关闭连接;并向该Consumer Group的所有Consumer发出通知,Group内的Consumer重新分配Broker,然后继续消费。
当Consumer得到Master宕机通知后,转向Slave消费,Slave不能保证Master的消息100%同步,因此会有少量的消息丢失。但是一旦Master恢复,未同步的消息会被最终消费掉。
简单的流程为:Name Server启动 -> Broker启动并注册到Name Server -> Producer启动注册到Name Server,并从Name Server拉取Topic信息 -> Producer与提供Topic的Broker建立长连接 -> Producer生产消息到某个Topic中 -> Consumer启动注册到Name Server,并从Name Server拉取Topic信息 -> Consumer与提供Topic的Broker建立长连接 -> Consumer订阅消息,启动定时任务定时从Topic拉取消息进行消费
可参考此文章 https://blog.csdn.net/hsl_1990_08_15/article/details/80077552
若按照文章流程安装依旧出现 提示‘错误: 找不到或无法加载主类 xxxxxx’ ,则需检查rocketmq 和 Java 路径上是否有空格,如果把RocketMQ放在C:/Program Files/rocketmq4.4.0 这种路径下是不行的,至少我本地不行,如果你可以就不用变动了,一切为了写出Hello World不用纠结太多,但如果出问题的话就尽量保证路径上没有空格。
如果改变rocketmq的目录还是报错的话,就尝试将JDK也放在没有空格的路径下(注意修改Java环境变量)
此处利用Maven项目来写RocketMQ的Hello World,利用ProducerTest发送消息,ConsumerTest消费消息。
启动命令行,cd到 rocketmq/bin 目录下,输入 ./mqnamesrv 启动Name Server服务器
启动命令行,cd到 rocketmq/bin 目录下,输入 ./mqbroker -n 127.0.0.1:9876 启动Broker服务器并指定 Name Server 地址
-c 指令为指定加载的配置文件,可以不加
启动后,可在 C:\Users\Dell\logs\rocketmqlogs 目录下查看到Broker以及rocketmq其他组件相应的日志。 *此处的Dell为你Windows登录的用户名
引入RocketMQ依赖
新建生产者 ProducerTest:
新建消费者ConsumerTest:
生产者:
消费者:
如果出现:
org.apache.rocketmq.client.exception.MQClientException: No route info of this topic, TopicTest2
See http://rocketmq.apache.org/docs/faq/ for further details.
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendDefaultImpl(DefaultMQProducerImpl.java:610)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.send(DefaultMQProducerImpl.java:1223)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.send(DefaultMQProducerImpl.java:1173)
at org.apache.rocketmq.client.producer.DefaultMQProducer.send(DefaultMQProducer.java:214)
at com.podago.demo.mq.ProducerTest.main(ProducerTest.java:29)
可以使用rocket-console手动添加topic,rocket-console的启动请查看上文安装配置提及的文章。
点击Commit添加,再执行进行尝试
参考文献:
简书:https://www.jianshu.com/p/2838890f3284 作者:@彦帧