概述

ActiveMQ是Apache所提供的一个开源的消息系统,全然採用Java来实现。因此。它能非常好地支持J2EE提出的JMS(Java Message Service,即Java消息服务)规范。

JMS是一组Java应用程序接口。它提供消息的创建、发送、读取等一系列服务。JMS提供了一组公共应用程序接口和响应的语法。相似于Java数据库的统一訪问接口JDBC,它是一种与厂商无关的API,使得Java程序能够与不同厂商的消息组件非常好地进行通信。

JMS支持两种消息发送和接收模型。一种称为P2P(Ponit to Point)模型。即採用点对点的方式发送消息。P2P模型是基于队列的,消息生产者发送消息到队列。消息消费者从队列中接收消息,队列的存在使得消息的异步传输称为可能,P2P模型在点对点的情况下进行消息传递时採用。

还有一种称为Pub/Sub(Publish/Subscribe,即公布-订阅)模型,公布-订阅模型定义了怎样向一个内容节点公布和订阅消息,这个内容节点称为topic(主题)。主题能够觉得是消息传递的中介,消息公布这将消息公布到某个主题,而消息订阅者则从主题订阅消息。主题使得消息的订阅者与消息的公布者互相保持独立。不须要进行接触就可以保证消息的传递,公布-订阅模型在消息的一对多广播时採用。


ActiveMQ的安装

下载最新的安装包apache-activemq-5.13.2-bin.tar.gz(此包linux下的,案例也是针对linux系统进行阐述,当然ActiveMQ也有win版的。这里就不赘述了)。能够去官网下载。也能够在下方留言区留下你的邮箱。博主会发给你的~

下载之后解压: tar -zvxf apache-activemq-5.13.2-bin.tar.gz

ActiveMQ文件夹内容有:

  • bin文件夹包括ActiveMQ的启动脚本
  • conf文件夹包括ActiveMQ的全部配置文件
  • data文件夹包括日志文件和持久性消息数据
  • example: ActiveMQ的演示样例
  • lib: ActiveMQ执行所须要的lib
  • webapps: ActiveMQ的web控制台和一些相关的demo

执行命令:activemq start(在activemq/bin下执行)

INFO: Loading '/users/shr/apache-activemq-5.13.2//bin/env'
INFO: Using java '/users/shr/util/JavaDir/jdk/bin/java'
INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details
INFO: pidfile created : '/users/shr/apache-activemq-5.13.2//data/activemq.pid' (pid '986')

查看activemq是否执行命令:ps -aux | grep activemq

shr        986  1.2  9.7 1281720 201936 pts/5  Sl   19:43   0:17 /users/shr/util/JavaDir/jdk/bin/java -Xms64M -Xmx1G -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=/users/shr/apache-activemq-5.13.2//conf/login.config -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/users/shr/apache-activemq-5.13.2//tmp -Dactivemq.classpath=/users/shr/apache-activemq-5.13.2//conf:/users/shr/apache-activemq-5.13.2//../lib/: -Dactivemq.home=/users/shr/apache-activemq-5.13.2/ -Dactivemq.base=/users/shr/apache-activemq-5.13.2/ -Dactivemq.conf=/users/shr/apache-activemq-5.13.2//conf -Dactivemq.data=/users/shr/apache-activemq-5.13.2//data -jar /users/shr/apache-activemq-5.13.2//bin/activemq.jar start
shr 1501 0.0 0.0 5176 724 pts/5 S+ 20:06 0:00 grep activemq

关闭命令: activemq stop

INFO: Loading '/users/shr/apache-activemq-5.13.2//bin/env'
INFO: Using java '/users/shr/util/JavaDir/jdk/bin/java'
INFO: Waiting at least 30 seconds for regular process termination of pid '986' :
Java Runtime: Oracle Corporation 1.7.0_79 /users/shr/util/JavaDir/jdk1.7.0_79/jre
Heap sizes: current=63232k free=62218k max=932096k
JVM args: -Xms64M -Xmx1G -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=/users/shr/apache-activemq-5.13.2//conf/login.config -Dactivemq.classpath=/users/shr/apache-activemq-5.13.2//conf:/users/shr/apache-activemq-5.13.2//../lib/: -Dactivemq.home=/users/shr/apache-activemq-5.13.2/ -Dactivemq.base=/users/shr/apache-activemq-5.13.2/ -Dactivemq.conf=/users/shr/apache-activemq-5.13.2//conf -Dactivemq.data=/users/shr/apache-activemq-5.13.2//data
Extensions classpath:
[/users/shr/apache-activemq-5.13.2/lib,/users/shr/apache-activemq-5.13.2/lib/camel,/users/shr/apache-activemq-5.13.2/lib/optional,/users/shr/apache-activemq-5.13.2/lib/web,/users/shr/apache-activemq-5.13.2/lib/extra]
ACTIVEMQ_HOME: /users/shr/apache-activemq-5.13.2
ACTIVEMQ_BASE: /users/shr/apache-activemq-5.13.2
ACTIVEMQ_CONF: /users/shr/apache-activemq-5.13.2/conf
ACTIVEMQ_DATA: /users/shr/apache-activemq-5.13.2/data
Connecting to pid: 986
..Stopping broker: localhost
.. TERMINATED

ActiveMQ的默认服务端口为61616。这个能够在conf/activemq.xml配置文件里改动:

<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

案例

在下载的apache-activemq-5.13.2-bin.tar.gz包中解压有一个jar包:activemq-all-5.13.2.jar,引入这个jar到你的项目中就可以開始编写案例代码。

博主的activemqserver地址为10.10.195.187。这个在以下代码中会有体现。

依照JMS的规范,我们首先须要获得一个JMS connection factory.。通过这个connection factory来创建connection.在这个基础之上我们再创建session, destination, producer和consumer。因此基本的几个过程例如以下:

  1. 获得JMS connection factory. 通过我们提供特定环境的连接信息来构造factory。
  2. 利用factory构造JMS connection
  3. 启动connection
  4. 通过connection创建JMS session.
  5. 指定JMS destination.
  6. 创建JMS producer或者创建JMS message并提供destination.
  7. 创建JMS consumer或注冊JMS message listener.
  8. 发送和接收JMS message.
  9. 关闭全部JMS资源,包括connection, session, producer, consumer等。

以下来看代码举例(P2P式)。

通过Java实现的基于ActiveMQ的请求提交:

package com.zzh.activemq;

import java.io.Serializable;
import java.util.HashMap; import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session; import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory; public class RequestSubmit
{
//消息发送者
private MessageProducer producer;
//一个发送或者接受消息的线程
private Session session; public void init() throws Exception
{
//ConnectionFactory连接工厂,JMS用它创建连接
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://10.10.195.187:61616");
//Connection:JMSclient到JMS Provider的连接。从构造工厂中得到连接对象
Connection connection = connectionFactory.createConnection();
//启动
connection.start();
//获取连接操作
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Destination destinatin = session.createQueue("RequestQueue");
//得到消息生成(发送)者
producer = session.createProducer(destinatin);
//设置不持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
} public void submit(HashMap<Serializable,Serializable> requestParam) throws Exception
{
ObjectMessage message = session.createObjectMessage(requestParam);
producer.send(message);
session.commit();
} public static void main(String[] args) throws Exception{
RequestSubmit submit = new RequestSubmit();
submit.init();
HashMap<Serializable,Serializable> requestParam = new HashMap<Serializable,Serializable>();
requestParam.put("朱小厮", "zzh");
submit.submit(requestParam);
}
}

创建Session时有两个非常重要的參数,第一个boolean类型的參数用来表示是否採用事务消息。

假设是事务消息。对于的參数设置为true。此时消息的提交自己主动有comit处理,消息的回滚则自己主动由rollback处理。

增加消息不是事务的。则相应的该參数设置为false,此时分为三种情况:

  • Session.AUTO_ACKNOWLEDGE表示Session会自己主动确认所接收到的消息。
  • Session.CLIENT_ACKNOWLEDGE表示由client程序通过调用消息的确认方法来确认所接收到的消息。
  • Session.DUPS_OK_ACKNOWLEDGE使得Session将“懒惰”地确认消息,即不会马上确认消息,这样有可能导致消息反复投递。

提供Java实现的基于ActiveMQ的请求处理:

package com.zzh.activemq;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map; import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.ObjectMessage;
import javax.jms.Session; import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory; public class RequestProcessor
{
public void requestHandler(HashMap<Serializable,Serializable> requestParam) throws Exception
{
System.out.println("requestHandler....."+requestParam.toString());
for(Map.Entry<Serializable, Serializable> entry : requestParam.entrySet())
{
System.out.println(entry.getKey()+":"+entry.getValue());
}
} public static void main(String[] args) throws Exception
{
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://10.10.195.187:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("RequestQueue");
//消息消费(接收)者
MessageConsumer consumer = session.createConsumer(destination); RequestProcessor processor = new RequestProcessor(); while(true)
{
ObjectMessage message = (ObjectMessage) consumer.receive(1000);
if(null != message)
{
System.out.println(message);
HashMap<Serializable,Serializable> requestParam = (HashMap<Serializable,Serializable>) message.getObject();
processor.requestHandler(requestParam);
}
else
{
break;
}
}
}
}

输出结果:

ActiveMQObjectMessage {commandId = 6, responseRequired = false, messageId = ID:hidden-PC-58748-1460550507055-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:hidden-PC-58748-1460550507055-1:1:1:1, destination = queue://RequestQueue, transactionId = TX:ID:hidden-PC-58748-1460550507055-1:1:1, expiration = 0, timestamp = 1460550507333, arrival = 0, brokerInTime = 1460550505969, brokerOutTime = 1460550509143, correlationId = null, replyTo = null, persistent = false, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@74a456bb, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false}
requestHandler.....{朱小厮=zzh}
朱小厮:zzh

能够通过页面查看队列的使用情况。在浏览器中输入http://10.10.195.187:8161/admin/queues.jsp。username和password都是:admin,看到以下页面:



这个是在jettyserver下跑的,能够改动conf/jetty.xml来改动相关jetty配置。

上面的样例是关于P2P模式的,只是有个不妥之处,就是没有资源的释放。

以下举一个Pub/Sub模式的。

通过JMS创建ActiveMQ的topic。并给topic发送消息:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic; import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.Produce; public class TopicRequest
{
//消息发送者
private MessageProducer producer;
//一个发送或者接受消息的线程
private Session session;
//Connection:JMSclient到JMS Provider的连接
private Connection connection; public void init() throws Exception
{
//ConnectionFactory连接工厂,JMS用它创建连接
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://10.10.195.187:61616");
//从构造工厂中得到连接对象
connection = connectionFactory.createConnection();
//启动
connection.start();
//获取连接操作
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("MessageTopic");
producer = session.createProducer(topic);
//设置不持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
} public void submit(String mess) throws Exception
{
TextMessage message = session.createTextMessage();
message.setText(mess);
producer.send(message);
} public void close()
{
try
{
if(session != null)
session.close();
if(producer != null)
producer.close();
if(connection !=null )
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
} public static void main(String[] args) throws Exception
{
TopicRequest topicRequest = new TopicRequest();
topicRequest.init();
topicRequest.submit("I'm first");
topicRequest.close();
}
}

消息发送到相应的topic后,须要将listener注冊到须要订阅的topic上,以便能够接收该topic的消息:

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic; import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory; public class TopicReceive
{
private MessageConsumer consumer;
private Session session; public void init() throws Exception
{
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://10.10.195.187:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("MessageTopic");
consumer = session.createConsumer(topic); consumer.setMessageListener(new MessageListener(){
@Override
public void onMessage(Message message)
{
TextMessage tm = (TextMessage) message;
System.out.println(tm);
try
{
System.out.println(tm.getText());
}
catch (JMSException e)
{
e.printStackTrace();
}
}
});
} public static void main(String[] args) throws Exception
{
TopicReceive receive = new TopicReceive();
receive.init();
}
}

输出结果:

ActiveMQTextMessage {commandId = 5, responseRequired = false, messageId = ID:hidden-PC-50073-1460597487065-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:hidden-PC-50073-1460597487065-1:1:1:1, destination = topic://MessageTopic, transactionId = null, expiration = 0, timestamp = 1460597487308, arrival = 0, brokerInTime = 1460597487297, brokerOutTime = 1460597487298, correlationId = null, replyTo = null, persistent = false, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@2e4d3abf, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = I'm first}
I'm first

參考文献

1. 《大型分布式站点架构——设计与实践》陈康贤著。

2. http://activemq.apache.org/

ActiveMQ简述的更多相关文章

  1. Sping+ActiveMQ整合

    通过前一篇<ActiveMQ简述>大概对ActiveMQ有了一个大概的认识.本篇所阐述的是怎样通过Spring继承ActiveMQ进而更有效.更灵活的运用ActiveMQ. Spring和 ...

  2. Spring Boot 监听 Activemq 中的特定 topic ,并将数据通过 RabbitMq 发布出去

    1.Spring Boot 和 ActiveMQ .RabbitMQ 简介 最近因为公司的项目需要用到 Spring Boot , 所以自学了一下, 发现它与 Spring 相比,最大的优点就是减少了 ...

  3. Java消息队列--ActiveMq 实战

    1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...

  4. 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)

    Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...

  5. (jms)ActiveMQ 安装配置.

    前言 ActiveMQ他是Apache出品的一个JMS提供者,管理会话和队列,运行在JVM下,支持多种语言,如JAVA,C++,C#,应用协议: OpenWire,Stomp REST,WS Noti ...

  6. node(ActiveMq)

    简单尝试了node下的ActiveMQ 1.下载apache-activemq-5.9.0,执行bat文件: 2.登录http://localhost:8161/admin可查看其管理后台: 3.安装 ...

  7. 简述 OAuth 2.0 的运作流程

    本文将以用户使用 github 登录网站留言为例,简述 OAuth 2.0 的运作流程. 假如我有一个网站,你是我网站上的访客,看了文章想留言表示「朕已阅」,留言时发现有这个网站的帐号才能够留言,此时 ...

  8. JavaScript单线程和浏览器事件循环简述

    JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...

  9. ActiveMQ的集群方案对比及部署

    转载:http://blog.csdn.net/lifetragedy/article/details/51869032 ActiveMQ的集群 内嵌代理所引发的问题: 消息过载 管理混乱 如何解决这 ...

随机推荐

  1. explain分析SQL语句详解

    性能分析explain MySql Query Optimizer是MySql中专门负责优化select语句的优化器模块,主要功能:通过计算分析系统中收集到的系统信息,为客户端请求的Query提供他认 ...

  2. 山东省第八届省赛 A:Return of the Nim(尼姆+威佐夫)

    Problem Description Sherlock and Watson are playing the following modified version of Nim game: Ther ...

  3. ubuntu 18.04下安装编译的KMS,依赖库

    libboost-system1.65.1 libglib2.0-0 libgstreamer-plugins-base1.0-0 libgstreamer1.0-0 libnice10 libsig ...

  4. (11)python 模块和包

    一.导入模块和包 模块相当于一个.py文件,包相当于带有个__init__.py一个文件夹,既可按模块导入也可按包导入. 1.导入模块或包 import 包名或模块名 (as 别名),包名或模块名 ( ...

  5. POJ 1776 Task Sequences(竞赛图构造哈密顿通路)

    链接:http://poj.org/problem?id=1776 本文链接:http://www.cnblogs.com/Ash-ly/p/5458635.html 题意: 有一个机器要完成一个作业 ...

  6. python判断一个数是否是2的几次幂

    判断一个数是不是2的几次幂,最简单粗暴的做法就是直接迭代除以2,这里有一个更好的方法,那就是采用位运算. 我们观察下面属于2的几次幂的数的变化规律,用2进制表示. 十进制 二进制 0 0 2 10 4 ...

  7. 26、Django实战第26天:配置全局导航

    1.编辑index.html,继承base.html 2.编辑base.html,根据是否登录不同显示 问题:当我们选中一个导航,选中样式并没有成为选中的状态 因此我们编辑base.html对导航中进 ...

  8. ubuntu下如何查找某个文件的路径

    1.whereis 文件名 特点:快速,但是是模糊查找,例如 找 #whereis mysql 它会把mysql,mysql.ini,mysql.*所在的目录都找出来. 2.find / -name ...

  9. 【主席树】bzoj3653 谈笑风生

    设siz[i]表示i的子树大小-1. 询问中b在a上方的便于统计. 对于b在a下方的情况,贡献为距a距离在K以内的节点的siz之和. 按dfs序建立可持久化线段树,线段树的下标是深度. 相当于把每个点 ...

  10. 【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network

    裸题,直接上.复杂度O(n*sqrt(n)*log(n)). //Num[i]表示树中的点i在函数式权值分块中对应的点 //Map[i]表示函数式权值分块中的点i在树中对应的点 #include< ...