一、概念
1. 中间件:位于系统之间的服务
2. 消息中间件:消息队列MQ,用于接收消息、存储消息、转发消息的中间件
3. Rocket MQ: 分布式的消息中间件,生产者、消费者、队列都可以分布式
4. 基于Netty开发
二、RocketMQ使用
1. 在服务器上安装Rocket MQ
2. 启动rocket mq,即name server,启动之后监听端口,等待brokerproducerconsumer连接
3. 启动broker, 设置对应的name server,broker用于收取和存储消息
4. 手动/自动创建Topic
5. 消费者代码
public class Consumer { public static void main(String[] args) throws InterruptedException, MQClientException { //声明并初始化一个consumer //需要一个consumer group名字作为构造方法的参数,这里为consumer1 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer1"); //同样也要设置NameServer地址 consumer.setNamesrvAddr("10.1.54.121:9876;10.1.54.122:9876"); //这里设置的是一个consumer的消费策略 //CONSUME_FROM_LAST_OFFSET 默认策略,从该队列最尾开始消费,即跳过历史消息 //CONSUME_FROM_FIRST_OFFSET 从队列最开始开始消费,即历史消息(还储存在broker的)全部消费一遍 //CONSUME_FROM_TIMESTAMP 从某个时间点开始消费,和setConsumeTimestamp()配合使用,默认是半个小时以前 consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); //设置consumer所订阅的Topic和Tag,*代表全部的Tag consumer.subscribe("TopicTest", "*"); //设置一个Listener,主要进行消息的逻辑处理 consumer.registerMessageListener(new MessageListenerConcurrently() { @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { System.out.println(Thread.currentThread().getName() + " Receive New Messages: " + msgs); //返回消费状态 //CONSUME_SUCCESS 消费成功 //RECONSUME_LATER 消费失败,需要稍后重新消费 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); //调用start()方法启动consumer consumer.start(); System.out.println("Consumer Started."); } }
6. 生产者代码
public class Producer { public static void main(String[] args) throws MQClientException, InterruptedException { //声明并初始化一个producer //需要一个producer group名字作为构造方法的参数,这里为producer1 DefaultMQProducer producer = new DefaultMQProducer("producer1"); //设置NameServer地址,此处应改为实际NameServer地址,多个地址之间用;分隔 //NameServer的地址必须有,但是也可以通过环境变量的方式设置,不一定非得写死在代码里 producer.setNamesrvAddr("10.1.54.121:9876;10.1.54.122:9876"); //调用start()方法启动一个producer实例 producer.start(); //发送10条消息到Topic为TopicTest,tag为TagA,消息内容为“Hello RocketMQ”拼接上i的值 for (int i = 0; i < 10; i++) { try { Message msg = new Message("TopicTest",// topic "TagA",// tag ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET)// body ); //调用producer的send()方法发送消息 //这里调用的是同步的方式,所以会有返回结果 SendResult sendResult = producer.send(msg); //打印返回结果,可以看到消息发送的状态以及一些相关信息 System.out.println(sendResult); } catch (Exception e) { e.printStackTrace(); Thread.sleep(1000); } } //发送完消息之后,调用shutdown()方法关闭producer producer.shutdown(); } }
三、架构和名词
1. NameServer:名称服务器,为Producer和Consumer提供路由信息,用于管理Broker节点信息,记录Broker与Topic的对应关系
2. ConsumerGroup:消费同一类消息的多个 consumer 实例组成一个消费者组
3. Topic:消息的逻辑分类,物理实现上,一个Topic由多个队列组成
4. Message:消息,指定topic,有消息内容
5. Tag:标签,是对Topic的进一步细化,可以用来过滤
6. Broker:消息服务器,就是MQ,分为Master和Slave节点,每个Broker与所有NameServer集群中所有节点建立连接,定时注册Topic到所有的NameServer
7. Producer与一个NameServer建立长连接,定期从NameServer获取Topic信息,向Broker发送消息
8. Consumer与一个NameServer建立长连接,定期从NameServer获取Topic信息,从Broker消费消息
四、特性
1. 发布/订阅,点对点(P2P)
2. 消息优先级:Rocket MQ没有特意支持消息优先级,但可以配置优先级不同的两个队列
3. 消息顺序:Rocket MQ严格保证消息顺序,先进先出
4. 消息过滤:生产端和消费端都可以过滤,各有优缺点
5. 消息持久化:Rocket MQ以文件形式持久化
6. 消息可靠性:避免消息丢失,需要生产者、消费者和MQ队列都保证
7. 消息延迟:Rocket MQ使用长轮询pull方式,保证实时
8. 消息堆积:因为需要削峰填谷,需要支持消息堆积,亿级别的消息堆积能力
9. 消息重试:消费失败后,重新再消费一次
10. 每个消息必须投递一次
11. 不运行重复的消息,需要业务保证幂等
12. 队列大小,定期删除数据
13. 定时消息
14. 事务机制
五、消费者的消费模式
1. 集群消费:一条消息只会被投递到一个consumer group下面的一个实例
2. 广播消费:一条消息会被投递到一个consumer group下面的所有实例
六、消费者获取消息的模式
1. 推送模式:能及时消费
2. 拉取模式:可以主动控制拉取时机
七、Rocket MQ和其他消息队列比较(ActiveMQ, RabbitMQ, ZeroMQ, Kafka),为什么选择Rocket MQ?
1. 严格的顺序消息
2. 亿级消息堆积能力
3. Pull/Push消费模式
4. 历经多次天猫双十一海量消息考验
参考:
https://www.cnblogs.com/lizhangyong/p/8978855.html
https://www.cnblogs.com/buyige/p/9378102.html
https://blog.csdn.net/tototuzuoquan/article/details/78325192