RocketMQ 使用入门案例

RocketMQ概述

RocketMQ是一款由阿里研发的高性能高可靠性的分布式消息队列,使用Java语言开发,该项目已经贡献给了Apache基金会,成为Apache的顶级开源项目。

在早期,阿里内部使用ActiveMQ作为其消息传递中间件,随着业务的快速增长,基于ActiveMQ的消息队列集群在处理大规模业务吞吐量时会遇到IO等性能瓶颈,阿里研发团队曾努力优化ActiveMQ,但无奈效果不理想,紧接着他们将目光投向Kafka,不幸的是Kafka并不能满足他们的要求, 特别是在低延迟和高可靠性方面。在这种情况下,阿里研发团队最终决定自己研发一个消息队列引擎来处理更广泛的使用场景,包括从传统的发布/订阅到大批量高实时、消息零丢失的交易系统。并且将该方案向社区开放,希望可以服务更多的企业。

RocketMQ官方网址:http://rocketmq.apache.org/

RocketMQ 基本特性

  • 消息模式:拉模式(ActiveMQ使用推模式)
  • 支持协议:TCP/JMS/OpenMessaging
  • 顺序消息:确保严格的消息排序,并可以优雅地扩展
  • 定时消息:支持定时消息
  • 批量消息:支持批量消息
  • 广播消息:支持广播消息
  • 消息过滤:支持基于SQL92标准的属性过滤表达式
  • 服务器触发重发:支持消息服务器触发重新传递
  • 消息存储:支持高性能、低延迟的消息文件存储
  • 消息追溯:支持时间戳和偏移量两种方式对消息进行追溯
  • 高可用和故障转移:系统支持主从模式(不需要其他插件)
  • 消息追踪
  • 配置复杂度:开箱即用,只需要配置几个参数即可
  • 管理和操作工具支持:支持web和终端命令两种方式管理

下载配置安装

RocketMQ下载地址[http://rocketmq.apache.org/release_notes/release-notes-4.2.0/]

RocketMQ 使用入门案例_第1张图片

解压

解压完成的结构

RocketMQ 使用入门案例_第2张图片

配置环境变量

  • 变量名:ROCKETMQ_HOME
  • 变量值:MQ解压路径\MQ文件夹名
  • 设置Path:%ROCKETMQ_HOME%\bin

启动

Windows键 + R 进入Bin目录

start mqnamesrv.cmd

Windows键 + R 进入Bin目录,启动新窗口

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

如果启动出现无反应的情况,可以查看日志,目前也是成功状态,但是cmd窗口没有任何反应!

C:\Users\xxxxx\logs\rocketmqlogs

RocketMQ 使用入门案例_第3张图片

也可以删除目录下的文件重新启动

C:\Users\xxxxx\store

插件配置

  • 下载插件项目

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

码云地址 https://gitee.com/mirrors/RocketMQ-Externals

只需要这一个项目就OK rocketmq-console

  • 修改配置文件
src\main\resources\application.properties
  • 找到需要修改的配置进行修改

RocketMQ 使用入门案例_第4张图片

启动项目,访问可视化界面

  • 首先将rocketmq-console项目编译打包

进入rocketmq-console cmd打开命令行窗口 执行命令

mvn clean package -Dmaven.test.skip=true
  • 启动项目

进入rocketmq-console\target 运行jar包

java -jar rocketmq-console-ng-1.0.1.jar
  • 访问RocketMQ 可视化界面

RocketMQ 使用入门案例_第5张图片

项目整合RocketMQ

alibaba-provider消息提供者

在这里插入图片描述

pom.xml


<dependency>
    <groupId>org.apache.rocketmqgroupId>
    <artifactId>rocketmq-spring-boot-starterartifactId>
    <version>${rocketmq.server.version}version>
dependency>

application.yml

#配置RocketMQ
rocketmq:
  #MQ地址 集群 127.0.0.0:9876;127.0.0.0:9876;127.0.0.0:9876
  name-server: localhost:9876
  producer:
    #MQ组名
    group: ${
     spring.application.name}
    #消息达到4096字节的时候,消息就会被压缩。默认就是4096,有利于网络传输,提升性能。
    compress-message-body-threshold: 4096
    #消息发送的超时时间,毫米级别,默认为3S
    send-message-timeout: 3000
    #同步消息发送失败重试次数
    retry-times-when-send-failed: 3
    #在内部发送失败时是否重试其他代理。 源码:setRetryAnotherBrokerWhenNotStoreOK,就是指:发送到broker-a失败是否发送到broker-b。这个参数在有多个broker才生效。
    retry-next-server: true
    #异步消息发送失败重试的次数
    retry-times-when-send-async-failed: 3

消息提供代码

  • controller
@Api(tags = "消息服务端")
@RequestMapping("/provider")
@RestController
public class RocketmqProviderController {
     

    @Autowired
    private RocketmqProviderService rocketmqProviderService;

    @ApiOperation(value = "发送普通消息1")
    @RequestMapping(value = "/send", method = RequestMethod.GET)
    public R sendMessage() {
     
        return R.ok(rocketmqProviderService.sendMessage());
    }

    @ApiOperation(value = "发送对象消息3")
    @RequestMapping(value = "/send/testMessage", method = RequestMethod.GET)
    public R sendObjectMessage() {
     
        return R.ok(rocketmqProviderService.sendObjectMessage());
    }

    @ApiOperation(value = "发送顺序消息4")
    @RequestMapping(value = "/send/SendOrderly", method = RequestMethod.GET)
    public R sendSendOrderly() {
     
        return R.ok(rocketmqProviderService.sendSendOrderly());
    }

    @ApiOperation(value = "发送异步消息5")
    @RequestMapping(value = "/send/asyncSendMq", method = RequestMethod.GET)
    public R asyncSendMQMessageSend() {
     
        return R.ok(rocketmqProviderService.asyncSendMQMessageSend());
    }

    /**
     * rocketMq单向发送不关心结果的发送测试【日志收集】
     */
    @ApiOperation(value = "发送不关心结果消息6")
    @RequestMapping(value = "/send/sendOneWay", method = RequestMethod.GET)
    public R oneWaySendMQMessageSend() {
     
        return R.ok(rocketmqProviderService.oneWaySendMQMessageSend());
    }


    @ApiOperation(value = "发送延时消息7")
    @RequestMapping(value = "/send/delayedSendMQ", method = RequestMethod.GET)
    public R delayedSendMQMessageSend() {
     
        return R.ok(rocketmqProviderService.delayedSendMQMessageSend());
    }


    /**
     * 分布式事务消息发送
     */
    @ApiOperation(value = "发送事务消息8")
    @RequestMapping(value = "/send/transaction", method = RequestMethod.GET)
    public R transactionMQSend() {
     
        return R.ok(rocketmqProviderService.transactionMQSend());
    }

}
  • service
/**
 * RocketMQ 接口
 */
public interface RocketmqProviderService {
     

    R sendMessage();

    R sendObjectMessage();

    R sendSendOrderly();

    R asyncSendMQMessageSend();

    R oneWaySendMQMessageSend();

    R delayedSendMQMessageSend();

    R transactionMQSend();
}
  • impl
@Slf4j
@Service
public class RocketmqProviderServiceImpl implements RocketmqProviderService {
     

    /**
     * topic要和消费端的topic保持一致
     * group组不需要保持一致
     */


    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 普通文本消息
     *
     * @return
     */
    @Override
    public R sendMessage() {
     

        String stringTopic = "string-topic";
        String payloadStr = "Hello world!";
        SendResult sendResult = rocketMQTemplate.syncSend(stringTopic, payloadStr);
        log.info("MQ同步发送String类型的消息topic为:{},返回结果:{}", stringTopic, sendResult);
        return R.ok("普通消息发送成功");
    }

    /**
     * 发送对象消息
     *
     * @return
     */
    @Override
    public R sendObjectMessage() {
     
        String stringTopic = "object-topic";
        TestMessage testMessage = new TestMessage();
        testMessage.setId(1);
        testMessage.setName("张三");
        testMessage.setCreateDate(new Date());
        testMessage.setFlag(true);

        SendResult sendResult = rocketMQTemplate.syncSend(stringTopic, testMessage);
        log.info("MQ同步发送对象类型的消息topic为:{},返回结果:{}", stringTopic, sendResult);
        return R.ok("对象消息发送成功");
    }

    /**
     * 发送顺序消息
     *
     * @return
     */
    @Override
    public R sendSendOrderly() {
     
        String topic = "sendOrderly-topic";
        for (int i = 0; i < 100; i++) {
     
            rocketMQTemplate.syncSendOrderly(topic, "顺序消息" + i, "1");
        }
        return R.ok("发送顺序消息成功");
    }

    /**
     * 异步发送:
     * 指发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
     * MQ 的异步发送,需要用户实现异步发送回调接口(SendCallback),在执行消息的异步发送时,
     * 应用不需要等待服务器响应即可直接返回,通过回调接口接收务器响应,并对服务器的响应结果进行处理。
     */
    @Override
    public R asyncSendMQMessageSend() {
     
        String objectTopic = "async-topic";
        TestMessage testMessage = new TestMessage();
        testMessage.setId(123456789);
        testMessage.setName("张三");
        testMessage.setCreateDate(new Date());
        testMessage.setFlag(true);
        rocketMQTemplate.asyncSend(objectTopic, testMessage, new SendCallback() {
     
            @Override
            public void onSuccess(SendResult sendResult) {
     
                log.info("异步消息发送成功:{}", sendResult);
            }

            @Override
            public void onException(Throwable throwable) {
     
                log.error("异步消息发送失败:{}", throwable.getCause());
            }
        });
        return R.ok("发送异步消息成功");
    }

    @Override
    public R oneWaySendMQMessageSend() {
     
        String objectTopic = "OneWay-topic";
        TestMessage testMessage = new TestMessage();
        testMessage.setId(123456789);
        testMessage.setName("张三");
        testMessage.setCreateDate(new Date());
        testMessage.setFlag(true);
        rocketMQTemplate.sendOneWay(objectTopic, testMessage);
        return R.ok("发送不关心结果消息成功");
    }

    @Override
    public R delayedSendMQMessageSend() {
     
        //SendResult syncSend(String destination, Message message, long timeout, int delayLevel);
        String objectTopic = "delayed-topic";
        TestMessage testMessage = new TestMessage();
        testMessage.setId(123456789);
        testMessage.setName("张三");
        testMessage.setCreateDate(new Date());
        testMessage.setFlag(true);

        Message<TestMessage> message = MessageBuilder.withPayload(testMessage).build();
        //这里的2就是对应上面延迟5s的。就是延迟5s发送消息。
        SendResult sendResult = rocketMQTemplate.syncSend(objectTopic, message, 1000, MessageDelayLevel.TIME_5S);
        log.info("发送延迟消息返回结果:{}", sendResult);
        return R.ok("发送延时消息成功");
    }

    @Override
    public R transactionMQSend() {
     
        //消息发送回调:com.zl.integraterocketmq.listener.TransactionListenerImpl
        //topic:tag
        String destination = "transaction-topic";
        //同步阻塞
        CountDownLatch latch = new CountDownLatch(1);

        TestMessage testMessage = new TestMessage();
        testMessage.setId(123456789);
        testMessage.setName("张三");
        testMessage.setCreateDate(new Date());
        testMessage.setFlag(true);

        String transactionId = UUID.randomUUID().toString();
        Message<TestMessage> message = MessageBuilder
                .withPayload(testMessage)
                .setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId)
                .setHeader(RocketMQHeaders.KEYS, testMessage.getId())
                .build();
//      sendMessageInTransaction(final String txProducerGroup, final String destination, final Message message, final Object arg)
        TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(destination, message, latch);

        if (sendResult.getSendStatus().equals(SendStatus.SEND_OK)
                && sendResult.getLocalTransactionState().equals(LocalTransactionState.COMMIT_MESSAGE)) {
     
            //下单成功,并且消息对消费端可见。

            //在这里可以异步通知上游服务,也可以继续走自己的逻辑,比如有些逻辑必须保证下单和库存成功之后才能走的。

            log.info("消息发送成功,并且本地事务执行成功");
        }
        try {
     
            latch.await();
        } catch (Exception e) {
     
            e.printStackTrace();
        }
        return R.ok("发送事务消息成功");
    }
}

alibaba-consumer消息消费者

在这里插入图片描述

pom.xml

<dependency>
    <groupId>org.apache.rocketmqgroupId>
    <artifactId>rocketmq-spring-boot-starterartifactId>
    <version>${rocketmq.server.version}version>
dependency>


<dependency>
    <groupId>org.apache.rocketmqgroupId>
    <artifactId>rocketmq-clientartifactId>
    <version>${rocketmq.client.version}version>
dependency>

application.yml

rocketmq:
  name-server: localhost:9876
  producer:
    group: ${
     spring.application.name}

消息消费者代码

  • ConsumerRocketMQ1普通消息
/**
 * consumeMode:
 *      CONCURRENTLY, 并发执行
 *      ORDERLY;      顺序执行
 *
 * topic:
 *      要和服务端的topic保持一直,才可以接收到对应的消息
 *
 * consumerGroup:
 *      这个可以随便写,不需要保持一致
 *
 * 消费端要实现RocketMQListener 泛型对应服务端发送的消息类型来决定
 * 一条消息topic 可以被两个consumerGroup 同时消费,获取消息
 *
 *
 */

@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "string-topic", consumerGroup = "my_consumer_test_group1")
public class ConsumerRocketMQ1 implements RocketMQListener<String> {
     

    @Override
    public void onMessage(String s) {
     
        log.info("ConsumerRocketMQ1接收普通消息:{}", s);
    }
}
 
  
  • ConsumerRocketMQ2普通消息和ConsumerRocketMQ1 同时去接收普通消息
@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "string-topic", consumerGroup = "my_consumer_test_group2")
public class ConsumerRocketMQ2 implements RocketMQListener<String> {
     

    @Override
    public void onMessage(String s) {
     
        log.info("ConsumerRocketMQ2接收普通消息:{}", s);
    }
}
  • ConsumerRocketMQ3接收对象消息
@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "object-topic", consumerGroup = "my_consumer_object")
public class ConsumerRocketMQ3 implements RocketMQListener<TestMessage> {
     


    @Override
    public void onMessage(TestMessage testMessage) {
     
        log.info("ConsumerRocketMQ3接收对象消息:{}", testMessage);
    }
}
  • ConsumerRocketMQ4接收顺序消息
@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "sendOrderly-topic", consumerGroup = "my_consumer_sendOrderly")
public class ConsumerRocketMQ4 implements RocketMQListener<String> {
     


    @Override
    public void onMessage(String str) {
     
        log.info("ConsumerRocketMQ4接收顺序消息:{}", str);
    }
}
  • ConsumerRocketMQ5接收异步消息
@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "async-topic", consumerGroup = "my_consumer_async")
public class ConsumerRocketMQ5 implements RocketMQListener<TestMessage> {
     


    @Override
    public void onMessage(TestMessage str) {
     
        log.info("ConsumerRocketMQ5接收异步消息:{}", str);
    }
}
  • ConsumerRocketMQ6单向发送消息
//接收单向发送消息
@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "OneWay-topic", consumerGroup = "my_consumer_OneWay")
public class ConsumerRocketMQ6 implements RocketMQListener<TestMessage> {
     

    @Override
    public void onMessage(TestMessage str) {
     
        log.info("ConsumerRocketMQ6单向发送消息:{}", str);
    }
}
  • ConsumerRocketMQ7接收延时消息
//接收延时消息
@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "delayed-topic", consumerGroup = "my_consumer_delayed")
public class ConsumerRocketMQ7 implements RocketMQListener<TestMessage> {
     

    @Override
    public void onMessage(TestMessage str) {
     
        log.info("ConsumerRocketMQ7接收延时消息:{}", str);
    }
}
  • ConsumerRocketMQ8接收事务消息
//接收事务消息
@Slf4j
@Service
@RocketMQMessageListener(consumeMode = ConsumeMode.ORDERLY, topic = "transaction-topic", consumerGroup = "my_consumer_transaction")
public class ConsumerRocketMQ8 implements RocketMQListener<TestMessage> {
     

    @Override
    public void onMessage(TestMessage str) {
     
        log.info("ConsumerRocketMQ8接收事务消息:{}", str);
    }
}

推荐文章

Spring Cloud Alibaba 系列学习笔记
SpringCloud Alibaba Nacos
SpringCloud Alibaba Sentinel
@SentinelResource注解总结,异常、降级兜底
SpringCloud Alibaba Sentine 规则持久化
SpringCloud Alibaba RocketMQ
Seata1.4.2分布式事务整合nacos+SpringCloudAlibaba

觉得对您有帮助就留下个宝贵的吧!

你可能感兴趣的:(分布式,spring,cloud,alibaba,rocketMq)