概述

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. (六)if流程控制

    (1)单分支结构 if 条件判断;then fi 例 #!/bin/bash read -p "please input Y" num if [ "$num" ...

  2. Django CRM查询(一对多,多对多以及相关的反查)

    Customer模型: class Customer(models.Model): name = models.CharField(max_length=32) qq = models.CharFie ...

  3. fmod()函数和modf()函数

    最近从博客上看到了一个fmod函数,结果又蹦出来一个modf函数 fmod()函数: 头文件:#include<math.h> C库函数... fmod()用来对浮点数进行取模(求余),原 ...

  4. Java的Hashtable类(转)

    文章来源:http://blog.csdn.net/zhna123_2011/article/details/6741479 ps:直接copy 哈希表是一种重要的存储方式,也是一种常见的检索方法.其 ...

  5. System Center VMM请注意不同语言版本的差异

    在私有云的项目中,经常需要判断System Center一些组件的连接是否OK. 我这里有开发,和测试两个环境,开发是英文版的System Center VMM,测试用的是中文版的System Cen ...

  6. CF 834B The Festive Evening【差分+字符串处理】

    B. The Festive Evening time limit per test1 second memory limit per test256 megabytes inputstandard ...

  7. Django项目静态文件加载失败问题

    在我们平时的开发过程中,为了方便调试程序,我们都是打开开发者模式,即Debug=True,当我们正式上线的时候肯定就需要把开发者模式关掉,用uwsgi部署上去以后,突然发现我们平时辛苦做的项目的静态文 ...

  8. 并查集【p1197】[JSOI2008]星球大战

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通 ...

  9. 学习python网站

    http://code.ziqiangxuetang.com/python/python-dictionary.html

  10. 【数论】【枚举约数】【欧拉函数】bzoj2705 [SDOI2012]Longge的问题

    ∵∑gcd(i, N)(1<=i <=N) =k1*s(f1)+k2*s(k2)+...+km*s(km) {ki是N的约数,s(ki)是满足gcd(x,N)=ki(1<=x< ...