RocketMQ 基本知识介绍、下载、安装、测试、集群

源码  rocketmq/docs/cn at master · apache/rocketmq · GitHub

一、 初始RocketMQ
1. 介绍

  1. RocketMQ是一款分布式、队列模型的消息中间件,是阿里巴巴集团自主研发的专业消息中间件,借鉴参考了JMS规范的MQ实现,更参考了优秀的开源消息中间件KAFKA,实现了业务消峰、分布式事务的优秀框架。
  2. 其底层代码编写清晰优秀,采用Netty NIO框架进行数据通信
  3. 摒弃了Zookeeper,内部使用更轻量级的NameServer进行网络路由,提高服务性能,并且支持消息失败重试机制。
  4. 天然支持集群模型,消费者负载均衡、水平扩展能力,支持广播模式和集群模式。
  5. 采用零拷贝的原理、顺序写盘、支持亿级消息堆积能力。
  6. 提供丰富的消息机制,如顺序消息、事务消息等。
  7. 目前 RocketMQ 已经成为Apache 顶级项目 。 在阿里内部, RocketMQ很好地服务了集团大大小小上千个应用,在每年的双十一当天,更有不可思议的万亿级消息通过 RocketMQ 流转(在 2017 年的双十一当天,整个阿里巴巴集团通过 RocketMQ 流转的线上消息达到了 万亿级,峰值 TPS 达到 5600 万),在阿里中台策略上发挥着举足轻重的作用 。此外, RocketMQ 是使用 Java语言开发的,比起 Kafka 的 Scala语言和 RabbitMQ 的 Erlang 语 言,更容易找 到技术人员进行定制开发 。

2.配置环境

本文讲解下载并安装单机版RocketMq,win10 环境。
要求:

  1. Linux/Unix/Mac/(本博客 是基于Windows 开发)
  2. 64bit JDK 1.8+;
  3. Maven 3.2.x

3.功能概括图

多协议接入

  1. 支持 MQTT 协议:支持主动推送模型,多级 Topic 模型支持一次触达 1000万+ 终端,可广泛应用于物联网和社交即时通信场景。
  2. 支持 TCP 协议:区别于 HTTP 简单的接入方式,提供更为专业、可靠、稳定的 TCP 协议的 SDK 接入。

特色功能

  1. 事务消息:实现类似 X/Open XA 的分布事务功能,以达到事务最终一致性状态。
  2. 定时(延时)消息:允许消息生产者指定消息进行定时(延时)投递,最长支持40天。
  3. 大消息:目前默认支持最大 256KB 消息,华北2 地域支持最大 4MB 消息。
  4. 消息轨迹:通过消息轨迹,用户能清晰定位消息从发布者发出,经由 MQ 服务端,投递给消息订阅者的完整链路,方便定位排查问题。
  5. 广播消费:允许一个 Consumer ID 所标识的所有 Consumer 都会各自消费某条消息一次。
  6. 顺序消息:允许消息消费者按照消息发送的顺序对消息进行消费。
  7. 重置消费进度:根据时间重置消费进度,允许用户进行消息回溯或者丢弃堆积消息

消息收发模型:

二、 MQ基本概念:

1. 九大属性

  1. Message:消息,消息队列中信息传递的载体。
  1. Message ID:消息的全局唯一标识,由 MQ 系统自动生成,唯一标识某条消息。
  2. Message Key:消息的业务标识,由**消息生产者(Producer)设置**,唯一标识某个业务逻辑。三级消息类型
  3. Topic:消息主题,一级消息类型,通过 Topic 对消息进行分类。
  4. Tag:消息标签,二级消息类型,用来进一步区分某个 Topic 下的消息分类。
  5. Producer:消息生产者,也称为消息发布者,负责生产并发送消息。
  6. Producer ID:一类 Producer 的标识,这类 Producer 通常生产并发送一类消息,且发送逻辑一致。
  7. Consumer:消息消费者,也称为消息订阅者,负责接收并消费消息。
  8. Consumer ID:一类 Consumer 的标识,这类 Consumer 通常接收并消费一类消息,且消费逻辑一致。

2. RocketMQ的4个组件:

分别是nameserver、broker、producer和consumer。

  1. nameserver: 存储当前集群**所有Brokers信息、Topic跟Broker的对应关系**。
  2. Broker: 集群最核心的模块,主要负责Topic消息存储、消费者的消费位点管理(消费进度)。
  3. Producer: 消息生产者,每个生产者都有一个ID(编号),多个生产者实例可以共用同一个ID。同一个ID下所有实例组成一个生产者集群。
  4. Consumer: 消息消费者,每个订阅者也有一个ID(编号),多个消费者实例可以共用同一个ID。同一个ID下所有实例组成一个消费者集群。

3. 集群部署结构

4. 工作流程

  1. 启动Nameserver,Nameserver起来后监听端口,等待Broker、Produer、Consumer连上来,相当于一个路由控制中心。
  2. Broker启动,跟所有的Nameserver保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有topic信息。注册成功后,Nameserver集群中就有Topic跟Broker的映射关系。
  3. 收发消息前,先创建topic,创建topic时需要指定该topic要存储在哪些Broker上。也可以在发送消息时自动创建Topic。
  4. Producer发送消息,启动时先跟Namesrv集群中的其中一台建立长连接,并从Nameserver中获取当前发送的Topic存在哪些Broker上,然后跟对应的Broker建立长连接,直接向Broker发消息。
  5. Consumer跟Producer类似。跟其中一台Nameserver建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。

三、 下载与安装

1. 从官网下载rocketMq

http://rocketmq.apache.org/
下载如图,最新版

2. 把文件解压出来,如下图所示

四、 启动与测试

1. 启动nameserver

在window(也就是用管理员方式运行)上启动:用cmd进入bin目录下执行启动命令

start mqnamesrv.cmd

会弹出一个框,表示启动成功。
Bug1:赶紧去配置环境变量。

然后重新执行启动命令。弹出 成功的框框:

2. 启动 broker 

然后在bin目录下再执行

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

//autoCreateTopicEnable=true 表示默认创建topic

回车后会出现下面的bug2。
bug2:修改bin目录下的runbroker.cmd文件。

最后一行中,CLASSPATH 加上双引号,变为“CLASSPATH”
 

 然后重新执行启动命令。弹出 成功的框框:

总共三个界面

 扩展:在linux中的启动命令:
nohup sh bin/mqnamesrv &
nohup sh bin/mqbroker -n 127.0.0.1:9876 &

五、 rocketMq可视化视图 下载与安装

1. 下载项目,自己打包

项目地址:https://github.com/apache/rocketmq-externals

2. 把下载的项目解压出来,找到rocketmq-console项目

 修改rocketmq-console\src\main\resources文件下的application.properties文件

如下:

server.contextPath=
server.port=8088
#spring.application.index=true
spring.application.name=rocketmq-console
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
logging.config=classpath:logback.xml
#if this value is empty,use env value rocketmq.config.namesrvAddr  NAMESRV_ADDR | now, you can set it in ops page.default localhost:9876
rocketmq.config.namesrvAddr=127.0.0.1:9876
#if you use rocketmq version < 3.5.8, rocketmq.config.isVIPChannel should be false.default true
rocketmq.config.isVIPChannel=false
#rocketmq-console's data path:dashboard/monitor
rocketmq.config.dataPath=/tmp/rocketmq-console/data
#set it false if you don't want use dashboard.default true
rocketmq.config.enableDashBoardCollect=true
#set the message track trace topic if you don't want use the default one
rocketmq.config.msgTrackTopicName=

3. 打包项目

进入 \rocketmq-externals\rocketmq-console 文件夹,执行maven命令
mvn clean package -Dmaven.test.skip=true

跳过测试,直接打包。

 打包成功

 

4. 启动 打包好的项目

首先启动rocketMq的服务
项目本身就是springboot项目,直接启动:
D:\mq\rocketmq-externals\rocketmq-console\target>java -jar rocketmq-console-ng-1.0.0.jar &

命令:java -jar rocketmq-console-ng-1.0.0.jar –server.port=12581

注意:不指定端口的话,默认8080(避免与Tomcat冲突,最好指定)但是我在application.propertise 配置文件中,已经配置了端口,则这里不用加参数

5. 启动后的页面

一共打开三个服务,如图:

在浏览器输入:127.0.0.1:9876

六. 测试:用Java代码发送和接受信息 

1. 测试

生产者:

package feng.rocketmq.quickstart;

import org.apache.rocketmq.client.exception.MQBrokerException;
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;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.io.UnsupportedEncodingException;

public class ProducerTest {
    public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException, InterruptedException, MQBrokerException {
//        while (true){
            // 1. 创建 DefaultMQProducer
            DefaultMQProducer mqProducer = new DefaultMQProducer("ProducerTest");
            // 2. 设置 namesrv 地址
            mqProducer.setNamesrvAddr("127.0.0.1:9876");
            // 3. 开启 DefaultMQProducer
            mqProducer.start();
            // 4. 创建消息 Message    String topic, String tags, String keys, byte[] body
            Message message = new Message("TopicTest1",   // 主题
                    "TagA",                                 // 主要用于消息过滤
                    "key1",                                 // 消息的唯一值
                    "HELLO WORLD".getBytes(RemotingHelper.DEFAULT_CHARSET));
            // 5. 发送消息
            SendResult sendResult = mqProducer.send(message);
            System.out.printf(String.valueOf(sendResult));
            // 6. 关闭 DefaultMQProducer
            mqProducer.shutdown();
//        }
    }
}

消费者:

package feng.rocketmq.quickstart;

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.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.common.RemotingHelper;

import java.io.UnsupportedEncodingException;
import java.util.List;

public class ConsumerTest {

    public static void main(String[] args) throws MQClientException {
        // 1. 创建 DefaultMQPushConsumer
        DefaultMQPushConsumer mqPushConsumer = new DefaultMQPushConsumer("ConsumerTest");
        // 2. 设置 namesrv
        mqPushConsumer.setNamesrvAddr("127.0.0.1:9876");
        // 3. 设置 subscribe ,这里是要读取的主题信息
        mqPushConsumer.subscribe("TopicTest1",    // 指定要消费的主题
                "*"                                // 过滤规则
        );
        // 设置 消息拉取 最大数
        mqPushConsumer.setConsumeMessageBatchMaxSize(2);
        //设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费
        //如果非第一次启动,那么按照上次消费的位置继续消费
        mqPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        // 字面意思:消费线程最小值
        mqPushConsumer.setConsumeThreadMin(1);
        // 字面意思:消费线程最大值
        mqPushConsumer.setConsumeThreadMax(1);
        //设置消费模型,集群还是广播,默认为集群
        mqPushConsumer.setMessageModel(MessageModel.CLUSTERING);
        // 设置
        mqPushConsumer.setPullThresholdForQueue(1);

        // 4. 创新消息监听 MessageListener  匿名内部类方式实现
        mqPushConsumer.registerMessageListener(new MessageListenerConcurrently(){
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                // 5. 获取消息信息
                // 迭代 消息信息
                for (MessageExt msg: list){
                    if (msg.getTopic().equals("TopicTest1")){
                        if (msg.getTags() != null && msg.getTags().equals("TagA")){
                            try {
                                // 获取主题
                                String topic = msg.getTopic();

                                // 获取标签
                                String tags = msg.getTags();

                                // 获取信息
                                byte[] body = msg.getBody();
                                // String result = new String(body);
                                String result = null;
                                result = new String(body, RemotingHelper.DEFAULT_CHARSET);
                                System.out.println("Consumer消费信息---topic:"+topic+",TagA:"+tags+",result"+result);

                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                                //消息重试  消息消费失败之后,会重新再发一次。
                                return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                            }

                        }
                    }
                }
                // 6. 返回消息读取状态
                // 消息消费完成
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        // 开启Consumer
        mqPushConsumer.start();

        // lambda
//        mqPushConsumer.registerMessageListener();
    }
}

2. 小总结

到目前为止,开启的服务有
1、 namesrv
2、 broker
3、 rockermq-console 可视化工具

 

还可以在可视化工具中查看**消息和消费者**。

七、 RocketMQ顺序消息

消息有序指的是可以**按照消息的发送顺序来消费**。 RocketMQ可以严格的保证消息有序。但这个顺序,不是全局顺序,只是分区(queue)顺序。要全局顺序只能一个分区。
如何保证顺序?

在MQ的模型中,顺序需要由3个阶段去保障:

1.消息被发送时保持顺序

2.消息被存储时保持和发送的顺序一致

3.消息被消费时保持和存储的顺序一致

 发送时保持顺序意味着对于有顺序要求的消息,用户应该在同一个线程中采用同步的方式发送。存储保持和发送的顺序一致则要求在同一线程中被发送出来的消息A和B,存储时在空间上A一定在B之前。而消费保持和存储一致则要求消息A、B到达Consumer之后必须按照先A后B的顺序被处理。

--------------------------------------------------------

参考

RocketMQ 基本知识介绍、下载、安装、测试、集群,看这一篇博客即可。_冯安晨-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值