祝大家新年快乐,牛年大吉。
1 前言
消息中间件是我们系统中常用的一个组件,在我们的业务中也有很多的应用场景,我们可以使用其实现业务的异步处理、系统间的解耦以及流量削峰。现在有很多个消息中间件(RocketMq、RabbitMq、Kafka等等),在本篇文章中主要介绍RocketMq的一些基础知识,这也是我工作中用的比较多的消息中间件。
RocketMq是阿里开源的一个低延迟、高性能、高可靠、支持分布式的消息中间件。该项目使用java语言进行编写,现已贡献给Apache基金会。
2 特性
RocketMQ提供了丰富的特性,简单列举如下,详细说明课查看其官方文档。
- 订阅与发布
- 顺序消息
- 消息过滤
- 消息可靠性
- 至少一次
- 事务消息
- 定时消息
- 消息重试
- 流量控制
- 死信队列
3 架构
RocketMq的架构如上图所示,其由NameServer、Broker、Producer和Consumer四部分组成,这四部分均支持集群部署。
3.1 NameServer
NameServer是一个简单的Topic路由注册中心,其角色类似Dubbo中的Zookeeper,支持Broker的动态注册与发现。
NameServer几乎是无状态的,集群中的各个节点之间无任何通信的独立节点,每一个节点都记录完整的路由信息。
NameServer主要提供Broker管理和路由信息管理两个功能,当Broker启动时会将自身的信息注册到NameServer集群中并定时上报Topic路由信息,之后NameServer会通过心跳监测剔除非存活的Broker节点。Producer和Consumer从NameServer中获取Broker集群的路由信息进行消息的发送和消费。
3.2 Broker
Broker提供消息中转的角色,负责消息的存储、转发。
当Broker启动时会与NameServer中的所有服务建立连接,将自己的信息进行注册。并定时的上报自己的Topic路由信息。
Broker支持一主多从,但只有一个从服务会参与消息的读负载。
3.3 Producer
Producer是消息生产者。负责将业务系统产生的消息通过MQ负载均衡模块投递到对应的Broker服务器,投递过程低延迟并支持快速失败。
RocketMQ提供同步、异步、顺序、单向发送的方式。
3.4 Consumer
Consumer是消息消费者。支持以push推和pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
3.5 通信机制
NameServer、Broker、Producer及Consumer四者之间的通信过程如下:
Broker启动后需要完成一次将自己注册到NameServer的操作,随后每隔30s时间定时向NameServer上报Topic路由信息。- 消息生产者作为客户端发送消息时候,需要根据消息的
Topic从本地缓存的TopicPublishInfoTable获取路由信息。如果没有则从NameServer上拉去并进行更新,同时Producer会默认每隔30s从NameServer拉去一次路由信息。 - 消息生产者从获取到的路由信息中选择一个队列进行发送消息;
Broker作为消息的接收者会将收到的消息进行存储。 - 消息消费者同生产这一样获取路由信息,并通过客户端的负载均衡选择其中的某一个或者几个消息队列来拉去消息并进行消费。
RocketMQ中自定义了通信协议并在Netty的基础之上扩展了通信模块。我们在之后的文章中再进行详细说明。
4 RocketMq的安装及使用
4.1 安装
RocketMq的安装比较简单的,过程如下:
// 在git上下载并解压安装包,地址为:https://github.com/apache/rocketmq/tags
// 启动NameServer
nohup sh bin/mqnamesrv &
// 启动Broker
nohup sh bin/mqbroker -n localhost:9876 &
至此我们的RocketMq便启动成功了,为了更方便的使用和查看消息我们安装一个RocketMq的控制台,项目地址如下:
github.com/apache/rock…
大家自行下载进行编译和启动,启动后的控制台内容如下
4.2 使用
上面我们已经安装好了RocketMq,接下来我们介绍下使用rocketmq-client进行消息的发送和消费。
创建一个Maven项目并添加依赖:
<!-- https://mvnrepository.com/artifact/org.apache.rocketmq/rocketmq-client -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.8.0</version>
</dependency>
消息生产者代码如下
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("TEST_TOPIC_PRODUCER_ONE");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message message = new Message("TEST_TOPIC", null, "Hello RocketMQ".getBytes());
SendResult sendResult = producer.send(message);
System.out.printf("%s%n", sendResult);
producer.shutdown();
}
消息消费者如下:
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("TEST_TOPIC_CONSUMER_ONE");
consumer.setNamesrvAddr("localhost:9876");
consumer.subscribe("TEST_TOPIC", "*");
consumer.registerMessageListener(new MessageListenerConcurrently() {
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
System.out.println("Receive new message: " + msgs);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
至此RocketMq的基本使用已经结束了,这里我们只是介绍了普通消息的使用,我们在后面的文章会详细的介绍RocketMq中的各种消息的使用及其使用场景。
5 总结
我们今天的内容到此就结束了,在本文中介绍了下RocketMq的基础知识及客户端的基本使用,希望大家能通过本文能够了解RocketMq的架构及其组成部分的作用和通信过程。
更多内容请关注后续的文章。