前言

小伙伴们大家好啊,王子又来和大家一起闲谈MQ技术了。

通过之前文章的学习,我们已经对RocketMQ的基本架构有了初步的了解,那今天王子就和大家一起来点实际的,用代码和大家一起看看RocketMQ的几种发送模式和消费模式。好了,让我们开始吧。

RocketMQ的环境准备

本次我们的环境搭建是基于docker的,需要小伙伴们准备一台CentOS7的虚拟机(虚拟机的安装这里就不做介绍了)。

王子使用的是安装在VMware中的CentOS7虚拟机系统。正式安装环境之前,为了测试方便,我们关闭了centos系统的防火墙。然后我们需要在这台虚拟机中安装docke和docker-compose,具体的安装步骤大家可以参考https://www.runoob.com/docker/centos-docker-install.html,一些常用的docker命令也可以在这个网站里查看,还是很方便的,王子在这里分享给大家。

安装过docker和docker-compose后,我们就要开始安装RocketMQ的环境了,具体的安装步骤可以参考https://gitee.com/lm970585581/docker-rocketmq中的一键部署docker-compose部分。

步骤都很简单,基本上算是一键式傻瓜安装了,但是,王子在安装的过程中却被一个问题困扰住了很久。

下边给大家说一下遇到的问题和解决的办法,这是重点哦。

王子按照步骤一步一步的执行,到最后一步执行start.sh的时候悲剧发生了。

如果一切正常,执行了这一步骤后,docker中一共会启动三个容器,分别是nameserver、broker、和rocketMQ的管控台,但是王子执行docker ps查看正在运行的容器的时候发现,居然只有两个容器在运行,broker不见了。

于是打开localhost:8180(管控台地址),发现管控台中是空的。

于是我们开始查看broker容器的启动日志,使用的命令是:docker logs -f -t --tail 行数 容器名

发现的报错信息是 java.io.FileNotFoundException: /etc/rocketmq/broker.conf (Permission denied)

到这里真实丈二的和尚摸不着头脑,一脸懵逼有木有。

进过一番努力的查找,终于找到了原因,由于centos7中安全模块selinux把权限禁掉了,所以导致不能读取broker.conf文件,具体这个安全模块是做什么的王子也没有仔细研究,我们目前是用不到,于是在linux中使用setenforce 0命令把它关闭了。

再重新启动broker容器,发现问题解决了。

好了环境我们部署完成之后,进入我们今天的主要内容,RocketMQ的发送模式和消费模式有哪几种。

RocketMQ的发送

同步发送

我们先来看一段生产者的代码:

  1. import com.alibaba.rocketmq.client.exception.MQClientException;
  2. import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
  3. import com.alibaba.rocketmq.client.producer.SendResult;
  4. import com.alibaba.rocketmq.common.message.Message;
  5. import com.alibaba.rocketmq.remoting.common.RemotingHelper;
  6.  
  7. public class RocketMQProducer {
  8. // RocketMQ的生产者类
  9. private static DefaultMQProducer producer;
  10. static {
  11. // 构建生产者对象,指定生产组
  12. producer=new DefaultMQProducer("test_group");
  13. // 设置NameServer的地址,拉取路由信息
  14. producer.setNamesrvAddr("192.168.220.110:9876");
  15. try {
  16. // 启动生产者
  17. producer.start();
  18. } catch (MQClientException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. public static void send(String topic,String message) throws Exception {
  23. // 构建消息对象
  24. Message msg=new Message(topic,
  25. "",//这里存放的Tag 我们之后会讲解
  26. message.getBytes(RemotingHelper.DEFAULT_CHARSET));
  27. SendResult send = producer.send(msg);
  28. System.out.println(send);
  29. }
  30.  
  31. public static void main(String[] args) {
  32. try {
  33. send("test","hello world!");
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }

上面的代码片段就是生产者发送消息到RocketMQ里去的代码,其实这种方式就是所谓的同步发送消息到MQ

那么什么叫同步发送消息到MQ里去?

所谓同步,意思就是你通过这行代码发送消息到MQ去,SendResult sendResult = producer.send(msg),然后你会卡在这里,代码不能往下走了

你要一直等待MQ返回一个结果给你,你拿到了结果之后,你的程序才会继续向下运行。

这个就是所谓的同步发送模式。

异步发送

接着我们来看一下异步发送的代码:

  1. import com.alibaba.rocketmq.client.exception.MQClientException;
  2. import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
  3. import com.alibaba.rocketmq.client.producer.SendCallback;
  4. import com.alibaba.rocketmq.client.producer.SendResult;
  5. import com.alibaba.rocketmq.common.message.Message;
  6. import com.alibaba.rocketmq.remoting.common.RemotingHelper;
  7.  
  8. public class RocketMQProducer {
  9. // RocketMQ的生产者类
  10. private static DefaultMQProducer producer;
  11. static {
  12. // 构建生产者对象,指定生产组
  13. producer=new DefaultMQProducer("test_group");
  14. // 设置NameServer的地址,拉取路由信息
  15. producer.setNamesrvAddr("192.168.220.110:9876");
  16. try {
  17. // 启动生产者
  18. producer.start();
  19. } catch (MQClientException e) {
  20. e.printStackTrace();
  21. }
  22. // 设置异步发送失败的时候不重试
  23. producer.setRetryTimesWhenSendAsyncFailed(0);
  24. }
  25. public static void send(String topic,String message) throws Exception {
  26. // 构建消息对象
  27. Message msg=new Message(topic,
  28. "",//这里存放的Tag 我们之后会讲解
  29. message.getBytes(RemotingHelper.DEFAULT_CHARSET));
  30. producer.send(msg, new SendCallback() {
  31. public void onSuccess(SendResult sendResult) {
  32. System.out.println(sendResult);
  33. }
  34. public void onException(Throwable throwable) {
  35. System.out.println(throwable);
  36. }
  37. });
  38.  
  39. }
  40.  
  41. public static void main(String[] args) {
  42. try {
  43. send("test","hello world!");
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }

意思就是消息发送后,代码继续向下运行,等到mq返回结果的时候,如果返回成功,就会调用回调函数onSuccess方法,返回失败就会调用onException方法。

这就是异步发送,它的特点就是不会阻塞程序,消息返回结果后再调用回调函数。

单向发送

还有一种发送方式,叫做单向发送,那么什么是单向发送呢?

代码如下:

  1. producer.sendOneway(msg);

它的意思就是生产者发送消息给MQ,发送后程序继续向下运行,不会阻塞,而且不会再管MQ的返回值。

也就是说发送过后就不关它的事了。

RocketMQ的发送方式就介绍到这里,关于具体的使用场景我们之后的文章再讨论,现在只要清楚有这些方式就可以了。

RocketMQ的消费

Push消费

我们来看一下push消费的代码

  1. import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;
  2. import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
  3. import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
  4. import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;
  5. import com.alibaba.rocketmq.client.exception.MQClientException;
  6. import com.alibaba.rocketmq.common.message.MessageExt;
  7.  
  8. import java.io.UnsupportedEncodingException;
  9. import java.util.List;
  10.  
  11. import static com.alibaba.rocketmq.remoting.common.RemotingHelper.DEFAULT_CHARSET;
  12.  
  13. public class RocketMQConsumer {
  14. public static void main(String[] args) throws MQClientException {
  15. // 创建push消费者实例,指定消费者组
  16. DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test_group");
  17. // 设置NameServer的地址,拉取路由信息
  18. consumer.setNamesrvAddr("192.168.220.110:9876");
  19. // 订阅test Topic , 第二个参数是Tag
  20. consumer.subscribe("test",null);
  21. // 注册消费者监听器,接收到消息就会调用这个方法
  22. consumer.registerMessageListener(new MessageListenerConcurrently() {
  23. public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
  24. // 在这里进行消息的处理
  25. for (MessageExt t : msgs) {
  26. try {
  27. System.out.println(new String(t.getBody(), DEFAULT_CHARSET));
  28. } catch (UnsupportedEncodingException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
  33. }
  34. });
  35. // 启动消费者实例
  36. consumer.start();
  37. System.out.println("----------Consumer Start-----------");
  38. }
  39. }

大家注意里面Consumer的类名:DefaultMQPushConsumer。

从类名中我们可以提取出来一个关键的信息:Push。其实从这里我们就能看出来,当前我们使用的消息消费实际上是Push模式。

那么什么是Push消费模式呢?

简单来讲就是Broker会主动把消息发送给你的消费者,你的消费者是被动的接收Broker推送给过来的消息,然后进行处理。

这个就是所谓的Push模式,意思就是Broker主动推送消息给消费者。

Pull消费

接下来我们简单说一下Pull消费的方式。

Pull消费其实理解起来也很容易,就是Broker不在主动推送消息给消费者了,而是消费者主动发送请求从Broker中拉取消息。

至于什么时候用Push模式,什么时候用Pull模式,我们以后再聊这个话题。

总结

今天我们一起使用Docker快速部署了RocketMQ的环境,又为小伙伴们分享了部署环境时遇到的坑和解决办法,希望小伙伴们不要再遇到这个问题的时候无从下手。

之后我们又一起写了生产者和消费者的代码,聊了聊RocketMQ的几种发送模式和消费模式。相信小伙伴们应该会有所收获。

那今天的分享就到这里,希望小伙伴们继续支持我,那么下次的分享不见不散。

往期文章推荐:

中间件专辑:

什么是消息中间件?主要作用是什么?

常见的消息中间件有哪些?你们是怎么进行技术选型的?

你懂RocketMQ 的架构原理吗?

聊一聊RocketMQ的注册中心NameServer

Broker的主从架构是怎么实现的?

RocketMQ生产部署架构如何设计

RabbitMQ和Kafka的高可用集群原理

算法专辑:

和同事谈谈Flood Fill 算法

详解股票买卖算法的最优解(一)

详解股票买卖算法的最优解(二)

RocketMQ的发送模式和消费模式的更多相关文章

  1. 深入研究RocketMQ生产者发送消息的底层原理

    前言 hello,小伙伴们,王子又来和大家研究RocketMQ的原理了,之前的文章RocketMQ生产部署架构如何设计中,我们已经简单的聊过了生产者是如何发送消息给Broker的. 我们简单回顾一下这 ...

  2. MQ系列5:RocketMQ消息的发送模式

    MQ系列1:消息中间件执行原理 MQ系列2:消息中间件的技术选型 MQ系列3:RocketMQ 架构分析 MQ系列4:NameServer 原理解析 在之前的篇章中,我们学习了RocketMQ的原理, ...

  3. RabbitMQ系列(八)--顺序消费模式和迅速消息发送模式

    MQ使用过程中,有些业务场景需要我们保证顺序消费,而如果一个Producer,一个Queue,多个Consumer的情况下是无法保证顺序的 举例: 1.业务上产生三条消息,分别是对数据的增加.修改.删 ...

  4. RocketMQ学习笔记(15)----RocketMQ的消息模式

    在前面学习ActiveMQ时,看到ActiveMQ可以是队列消息模式,也可以是订阅发布模式. 同样,在RocketMQ中,也存在两种消息模式,即是集群消费模式和广播消费模式. 1. 集群消费模式 跟A ...

  5. RocketMQ之九:RocketMQ消息发送流程解读

    在讨论这个问题之前,我们先看一下Client的整体架构. Producer与Consumer类体系 从下图可以看出以下几点:(1)Producer与Consumer的共同逻辑,封装在MQClientI ...

  6. Objective-C(十九、通知-消息发送模式之中的一个)——iOS开发基础

    结合之前的学习笔记以及參考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结. 知识点一直在变.仅仅是作为參考.以苹果官方文档为准~ 十九.通知-消息 ...

  7. RocketMQ消息发送流程和高可用设计

    (源码阅读先看主线 再看支线 先点到为止 后面再详细分解) 高可用的设计就是:当producer发送消息到broker上,broker却宕机,那下一次发送如何避免发送到这个broker上,就是采用La ...

  8. RENIX流量发送模式——网络测试仪实操

    信而泰的RENIX平台支持5种传输模式, 如下图所示. 模式一: continuous Continuous:连续发送流 持续发送方式是默认的发送模式,  它不会自动的停止, 会一直发送, 直到用户手 ...

  9. 一张图进阶 RocketMQ - 消息发送

    前 言 三此君看了好几本书,看了很多遍源码整理的 一张图进阶 RocketMQ 图片链接,关于 RocketMQ 你只需要记住这张图!觉得不错的话,记得点赞关注哦. [重要]视频在 B 站同步更新,欢 ...

随机推荐

  1. centos环境 使用kubeadm快速安装k8s集群v1.16.2

    全程使用root用户运行,宿主机需要连接外网 浏览一下官方kubeadm[有些镜像用不了] https://kubernetes.io/docs/setup/production-environmen ...

  2. SpringBoot整合WebSocket实现前后端互推消息

    小编写这篇文章是为了记录实现WebSocket的过程,受不了啰嗦的同学可以直接看代码. 前段时间做项目时设计了一个广播的场景,具体业务不再赘述,最终要实现的效果就是平台接收到的信息实时发布给所有的用户 ...

  3. 计算机网络-传输层(3)TCP协议与拥堵控制

    TCP是因特网传输层的面向连接的可靠的运输协议.   TCP被称为是面向连接的:通信双方在发送数据之前必须建立连接,连接状态只在连接的两端中维护,在沿途节点中并不维护状态. TCP连接包括:两台主机上 ...

  4. 计算机网络-应用层(4)DNS协议

    域名系统(Domain Name System, DNS):一个分层的由DNS服务器实现的分布式数据库+一个使得主机能够查询分布式数据库的应用层协议 DNS服务器通常是运行BIND (Berkeley ...

  5. 运用sed命令高效地删除文件的特定行

    运用 sed 命令高效地删除文件的特定行 正常来说,我们想要删除文件中的某些行内容,一般都是先打开这个文件,然后找到要删除的内容,再然后选中这些行并按删除键进行删除,这在数据量很少时是没有问题的.但是 ...

  6. log4j升级到log4j2

    log4j升级到log4j2 1.导入依赖 log4j2应尽量使用同一版本,否则可能出现不兼容的情况 <!-- log4j2 start --> <!-- log4j-1.2-api ...

  7. Java面试题(RabbitMQ篇)

    RabbitMQ 135. rabbitmq 的使用场景有哪些? ①. 跨系统的异步通信,所有需要异步交互的地方都可以使用消息队列.就像我们除了打电话(同步)以外,还需要发短信,发电子邮件(异步)的通 ...

  8. mysql数据库中数据类型的长度

    在mysql中新建数据表的时候会有长度一说,其实用建表语句建数据表的时候也有涉及 例如: CREATE TABLE user( uid int(4), name varchar(255), passw ...

  9. android开发之splash闪屏页判断是否第一次进入app代码

    package com.david.david.zhankudemo.activity; import android.app.Activity; import android.content.Con ...

  10. 令人蛋疼的错误提示 0xcdcdcdcd ,0xdddddddd ,0xfeeefeee ,0xcccccccc ,0xabababab

    原文地址:http://www.cnblogs.com/pcchinadreamfly/archive/2012/04/26/2471317.html参考地址:http://blog.csdn.net ...