1    queue与topic的技术特点对比

对比项

Topic

Queue

概要

Publish Subscribe messaging 发布订阅消息

Point-to-Point 点对点

有无状态

topic数据默认不落地,是无状态的。

Queue数据默认会在mq服务器上以文件形式保存,比如Active MQ一般保存在$AMQ_HOME\data\kr-store\data下面。也可以配置成DB存储。

完整性保障

并不保证publisher发布的每条数据,Subscriber都能接受到。

Queue保证每条数据都能被receiver接收。

消息是否会丢失

一般来说publisher发布消息到某一个topic时,只有正在监听该topic地址的sub能够接收到消息;如果没有sub在监听,该topic就丢失了。

Sender发送消息到目标Queue,receiver可以异步接收这个Queue上的消息。Queue上的消息如果暂时没有receiver来取,也不会丢失。

消息发布接收策略

一对多的消息发布接收策略,监听同一个topic地址的多个sub都能收到publisher发送的消息。Sub接收完通知mq服务器

一对一的消息发布接收策略,一个sender发送的消息,只能有一个receiver接收。receiver接收完后,通知mq服务器已接收,mq服务器对queue里的消息采取删除或其他操作。

Topic和queue的最大区别在于topic是以广播的形式,通知所有在线监听的客户端有新的消息,没有监听的客户端将收不到消息;而queue则是以点对点的形式通知多个处于监听状态的客户端中的一个。

2    topic和queue方式的消息处理效率比较

通过增加监听客户端的并发数来验证,topic的消息推送,是否会因为监听客户端的并发上升而出现明显的下降,测试环境的服务器为ci环境的ActiveMQ,客户端为我的本机。

从实测的结果来看,topic方式发送的消息,发送和接收的效率,在一个订阅者和100个订阅者的前提下没有明显差异,但在500个订阅者(线程)并发的前提下,效率差异很明显(由于500线程并发的情况下,我本机的cpu占用率已高达70-90%,所以无法确认是我本机测试造成的性能瓶颈还是topic消息发送方式存在性能瓶颈,造成效率下降如此明显)。

Topic方式发送的消息与queue方式发送的消息,发送和接收的效率,在一个订阅者和100个订阅者的前提下没有明显差异,但在500个订阅者并发的前提下,topic方式的效率明显低于queue。

Queue方式发送的消息,在一个订阅者、100个订阅者和500个订阅者的前提下,发送和接收的效率没有明显变化。

Topic实测数据:

 

发送者发送的消息总数

所有订阅者接收到消息的总数

消息发送和接收平均耗时

单订阅者

100

100

101ms

100订阅者

100

10000

103ms

500订阅者

100

50000

14162ms

Queue实测数据:

 

发送者发送的消息总数

所有订阅者接收到消息的总数

消息发送和接收平均耗时

单订阅者

100

100

96ms

100订阅者

100

100

96ms

500订阅者

100

100

100ms

3     topic方式的消息处理示例
3.1     通过客户端代码调用来发送一个topic的消息:

import javax.jms.Connection;

import javax.jms.ConnectionFactory;

import javax.jms.DeliveryMode;

import javax.jms.Destination;

import javax.jms.MessageProducer;

import javax.jms.Session;

import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;

import org.apache.activemq.ActiveMQConnectionFactory;

publicclass SendTopic {

privatestaticfinalintSEND_NUMBER = 5;

publicstaticvoid sendMessage(Session session, MessageProducer producer)

throws Exception {

for (int i = 1; i <=SEND_NUMBER; i++) {

TextMessage message = session

.createTextMessage("ActiveMq发送的消息" + i);

//发送消息到目的地方

System.out.println("发送消息:" + "ActiveMq 发送的消息" + i);

producer.send(message);

}

}

publicstaticvoid main(String[] args) {

// ConnectionFactory:连接工厂,JMS用它创建连接

ConnectionFactory connectionFactory;

// Connection:JMS客户端到JMS Provider的连接

Connection connection = null;

// Session:一个发送或接收消息的线程

Session session;

// Destination:消息的目的地;消息发送给谁.

Destination destination;

// MessageProducer:消息发送者

MessageProducer producer;

// TextMessage message;

//构造ConnectionFactory实例对象,此处采用ActiveMq的实现jar

connectionFactory = new ActiveMQConnectionFactory(

ActiveMQConnection.DEFAULT_USER,

ActiveMQConnection.DEFAULT_PASSWORD,

"tcp://10.20.8.198:61616");

try {

//构造从工厂得到连接对象

connection = connectionFactory.createConnection();

//启动

connection.start();

//获取操作连接

session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);

//获取session注意参数值FirstTopic是一个服务器的topic(与queue消息的发送相比,这里是唯一的不同)

destination = session.createTopic("FirstTopic");

//得到消息生成者【发送者】

producer = session.createProducer(destination);

//设置不持久化,此处学习,实际根据项目决定

producer.setDeliveryMode(DeliveryMode.PERSISTENT);

//构造消息,此处写死,项目就是参数,或者方法获取

sendMessage(session, producer);

session.commit();

catch (Exception e) {

e.printStackTrace();

finally {

try {

if (null != connection)

connection.close();

catch (Throwable ignore) {

}

}

}

}

3.2     启动多个客户端监听来接收topic的消息:

publicclass ReceiveTopicimplements Runnable {

private StringthreadName;

ReceiveTopic(String threadName) {

this.threadName = threadName;

}

publicvoid run() {

// ConnectionFactory:连接工厂,JMS用它创建连接

ConnectionFactory connectionFactory;

// Connection:JMS客户端到JMS Provider的连接

Connection connection =null;

// Session:一个发送或接收消息的线程

Session session;

// Destination:消息的目的地;消息发送给谁.

Destination destination;

//消费者,消息接收者

MessageConsumer consumer;

connectionFactory = new ActiveMQConnectionFactory(

ActiveMQConnection.DEFAULT_USER,

ActiveMQConnection.DEFAULT_PASSWORD,"tcp://10.20.8.198:61616");

try {

//构造从工厂得到连接对象

connection = connectionFactory.createConnection();

//启动

connection.start();

//获取操作连接,默认自动向服务器发送接收成功的响应

session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

//获取session注意参数值FirstTopic是一个服务器的topic

destination = session.createTopic("FirstTopic");

consumer = session.createConsumer(destination);

while (true) {

//设置接收者接收消息的时间,为了便于测试,这里设定为100s

TextMessage message = (TextMessage) consumer

.receive(100 * 1000);

if (null != message) {

System.out.println("线程"+threadName+"收到消息:" + message.getText());

else {

continue;

}

}

catch (Exception e) {

e.printStackTrace();

finally {

try {

if (null != connection)

connection.close();

catch (Throwable ignore) {

}

}

}

publicstaticvoid main(String[] args) {

//这里启动3个线程来监听FirstTopic的消息,与queue的方式不一样三个线程都能收到同样的消息

ReceiveTopic receive1=new ReceiveTopic("thread1");

ReceiveTopic receive2=new ReceiveTopic("thread2");

ReceiveTopic receive3=new ReceiveTopic("thread3");

Thread thread1=new Thread(receive1);

Thread thread2=new Thread(receive2);

Thread thread3=new Thread(receive3);

thread1.start();

thread2.start();

thread3.start();

}

}

4     queue方式的消息处理示例

ActiveMQ的queue以及topic两种消息处理机制分析的更多相关文章

  1. SpringBoot整合ActiveMq实现Queue和Topic两种模式(看不懂你来打我)

    目录 一.前言 二.ActiveMq的下载和使用 三.依赖准备 四.yml文件配置 五.配置Bean 六.创建生产者(Queue+Topic) 七.创建消费者(Topic模式下) 八.测试结果(Top ...

  2. FMX有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法(firemonkey messaging)

    看FMX代码,发现有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法.   早前,看过文章说TMessageManage ...

  3. Java中的ReentrantLock和synchronized两种锁定机制的对比

    问题:多个访问线程将需要写入到文件中的数据先保存到一个队列里面,然后由专门的 写出线程负责从队列中取出数据并写入到文件中. http://blog.csdn.net/top_code/article/ ...

  4. ReentrantLock和synchronized两种锁定机制

    ReentrantLock和synchronized两种锁定机制 >>应用synchronized同步锁 把代码块声明为 synchronized,使得该代码具有 原子性(atomicit ...

  5. JAVA基础之两种核心机制

    突然之间需要学习Java,学校里学的东西早就忘记了,得用最短的时间把Java知识理顺,重点还是J2EE,毕竟所有的ava项目中95%都是J2EE,还是先从基础的J2SE学起吧....... 首先是了解 ...

  6. SpringMVC提供两种校验机制

    本文不讲如何使用SpringMVC提供的两种校验机制,只是简单的说明一下其中的差别而已: 1.创建一个Bean,在Bean的属性中添加校验信息,通过配置LocalValidatorFactoryBea ...

  7. 分析RedisRDB和AOF两种持久化机制的工作原理及优劣势

    一.RDB和AOF两种持久化机制的介绍 RDB持久化机制,对redis中的数据执行周期性的持久化 AOF机制对每条写入命令作为日志,以append-only(追加)的模式写入一个日志文件中,在redi ...

  8. java两种同步机制的实现 synchronized和reentrantlock

    java两种同步机制的实现 synchronized和reentrantlock 双11加保障过去一周,趁现在有空,写一点硬货,因为在进入阿里之后工作域的原因之前很多java知识点很少用,所以记录一下 ...

  9. Redis两种持久化策略分析

    Redis专题地址:https://www.cnblogs.com/hello-shf/category/1615909.html SpringBoot读源码系列:https://www.cnblog ...

随机推荐

  1. 剑指offer:1.找出数组中重复的数(java版)

    数组中重复的数:题目:找出数组中重复的数,题目描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内.数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任 ...

  2. mac node版本管理

    (0)简说 目前有n和nvm这两个工具可以对Node进行升级,以下简单介绍一下二者的使用. (1)n 安装很简单: $ sudo npm install -g n 另一种获取源码的方法安装: $ gi ...

  3. 关于微信小程序<radio-group>布局排列

    微信小程序更新以后今天<radio>全部变成垂直排列了,布局乱了. 一开始尝试给外层<view>添加display:flex;flex-direction:row:未果. 后来 ...

  4. leaflet计算多边形面积

    上一篇介绍了使用leaflet绘制圆形,那如何计算圆形的面积呢? 1.使用数学公式计算,绘制好圆形后,获取中心点以及半径即可 2.使用第三方工具计算,如turf.js. 这里turf的area方法入参 ...

  5. Arcgis去除Z,M值

    在arcgis中,我们常用的数据类型有点,线,面数据,但是有时候我们在转换数据的时候经常会带有ZM值,而带ZM值的数据在有些软件中是不会显示的,也就是说显示存在问题,所以我们需要去除掉ZM值 在arc ...

  6. PHP mkdir新建目录

    一.在本目录下新建目录 <?php$dir_url = 'aaa/';if(!is_dir($dir_url)) {   mkdir($dir_url, 0777);}?> 二.在级联创建 ...

  7. 微信小程序中如何获取for循环的item相关值到JS页面的问题

    今天小程序开发过程中,遇到了这个棘手的问题.由于我没有前端基础,只是知道一点儿基本的HTML标签,所以卡了好久,特此分享,望后来的你,可以有所收获. measure  step 1  *.WXML: ...

  8. Web前端:博客美化:二、鼠标特效

    1.获取JS权限 因为是js代码所以需要放在 侧边栏公告 里 没开通之前,有一个申请的链接,点击即可,我是第二天才看到过审的 ^-^ 2.Ctrl+C.Ctrl+V 数组里的文字随自己心情啦 另:30 ...

  9. Jenkins 配置CI/CD任务

    本文演示如何通过Jenkins创建CI/CD任务,部署一整套微服务体系结构,并运行在之前搭建的mini云平台上. 如果是初始尝试实践,可能需要参考 快速搭建云原生架构的实践环境 和 Jhipster技 ...

  10. [20190211]简单测试端口是否打开.txt

    [20190211]简单测试端口是否打开.txt --//昨天看一个链接,提到如果判断一个端口是否打开可以简单执行如下:--//参考链接:https://dba010.com/2019/02/04/c ...