一、编译

虽然ActiveMQ提供了发布版本,但是建议同学们自己下载源代码编译,以后万一有坑,还可以尝试自己改改源码。

1.1 https://github.com/apache/activemq/releases 到这里下载最新的release版源码(当前最新版本为5.13.2),并解压到某个目录(以下用$ACTIVEMQ_HOME代替解压根目录)

1.2 编译

  1. cd $ACTIVEMQ_HOME
  2. mvn clean install -Dmaven.test.skip=true

编译成功后,在$ACTIVEMQ_HOME/assembly/target下会生成可xxx.bin.tar.gz的可执行文件压缩包

二、启动

将编译后得到的xxx.bin.tar.gz解压,然后执行

  1. tar -zxvf apache-activemq-5.13.2-bin.tar.gz
  2. cd apache-activemq-5.13.2/bin
  3. ./activemq start

后面的可选参数还有 status、restart、stop、list等,不清楚的地方,直接 --help 查看。

注:生产环境中,可能会对activemq的jvm内存设置上限,可以直接修改bin/activemq启动脚本,vi bin/activemq 找到下面的位置:

  1. # Note: This function uses globally defined variables
  2. # - $ACTIVEMQ_PIDFILE : the name of the pid file
  3. # - $ACTIVEMQ_OPTS : Additional options
  4. ACTIVEMQ_OPTS="-server -Xms512M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M "
  5. # - $ACTIVEMQ_SUNJMX_START : options for JMX settings
  6. # - $ACTIVEMQ_SSL_OPTS : options for SSL encryption

设置ACTIVEMQ_OPTS即可,然后重启activemq,建议启动成功后,用jinfo {activemq的pid} 来验证查看一下  

三、管理界面

启动成功后,可以浏览 http://localhost:8161/admin/

默认用户名、密码:admin/admin

管理界面是用jetty做容器的,如果想修改管理界面的端口,可以编辑../conf/jetty.xml,找到下面这一段:

  1. <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
  2. <!-- the default port number for the web console -->
  3. <property name="host" value="0.0.0.0"/>
  4. <property name="port" value="8161"/>
  5. </bean>

用户名/密码是在 ../conf/jetty-realm.properties 里,比如要增加一个管理员jimmy/123456,可参考下面修改:

  1. admin: admin, admin
  2. jimmy: 123456, admin
  3. user: user, user

注:管理界面有一个小坑,ActiveMQ 5.13.与jdk1.8兼容性有点问题,如果使用jdk1.8,管理界面进入Queues标签页时,偶尔会报错,但是并不影响消息正常收发,只是无法从界面上查看队列情况,如果出现该问题,可将jdk版本降至1.7,同时最好清空data目录下的所有数据,再重启activemq即可。

2016-06-18 注:最新版的5.13.已经修复了这个bug,建议大家使用最新版本。

  

四、示例代码

通常消息队列都支持二种模式:基于主题(topic)的发布(Publish)/订阅(Subscribe)模式、点对点(p2p)模式,下面的示例代码为p2p场景。

先给出gradle项目的依赖项

  1. dependencies {
  2. compile "org.springframework:spring-core:4.2.5.RELEASE"
  3. compile "org.springframework:spring-beans:4.2.5.RELEASE"
  4. compile "org.springframework:spring-context:4.2.5.RELEASE"
  5. compile "org.springframework:spring-jms:4.2.3.RELEASE"
  6. compile 'org.apache.activemq:activemq-all:5.13.2'
  7. compile 'org.apache.commons:commons-pool2:2.4.2'
  8. testCompile group: 'junit', name: 'junit', version: '4.12'
  9. }

4.1 spring配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.  
  6. <bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
  7. <property name="connectionFactory">
  8. <bean class="org.apache.activemq.ActiveMQConnectionFactory">
  9. <!--broker服务的地址-->
  10. <property name="brokerURL" value="tcp://localhost:61616"/>
  11. <!--默认值为1000,如果不需要这么大,可以调小-->
  12. <property name="maxThreadPoolSize" value="100"/>
  13. </bean>
  14. </property>
  15. </bean>
  16.  
  17. <bean id="dest" class="org.apache.activemq.command.ActiveMQQueue">
  18. <!--队列名称-->
  19. <property name="physicalName" value="myQueue"/>
  20. </bean>
  21.  
  22. <bean id="myJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
  23. <property name="connectionFactory" ref="jmsFactory"/>
  24. <!--默认的队列-->
  25. <property name="defaultDestination" ref="dest"/>
  26. <!--接收超时时间10秒-->
  27. <property name="receiveTimeout" value="10000"/>
  28. </bean>
  29.  
  30. </beans>

注:brokerURL的地址是在conf/activemq.xml里定义里,见下面的片段

  1. <transportConnectors>
  2. <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
  3. <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  4. <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  5. <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  6. <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  7. <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  8. </transportConnectors>

另外,连接ActiveMQ默认情况下,没有任何安全机制,也就是说任何人只要知道brokerURL都能连接,这显然不安全,可以在activemq.xml里,找到<broker>节点,紧贴它的地方添加下面这段:

  1. <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
  2.  
  3. <plugins>
  4. <simpleAuthenticationPlugin>
  5. <users>
  6. <authenticationUser username="${activemq.username}" password="${activemq.password}" groups="users,admins"/>
  7. </users>
  8. </simpleAuthenticationPlugin>
  9. </plugins>
  10. ...
  11. </broker>

那么问题来了,这个${activemq.username}及${activemq.password}的值是在哪里定义的呢?仍然在activemq.xml里找答案,在最开始的地方有一段:

  1. <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  2. <property name="locations">
  3. <value>file:${activemq.conf}/credentials.properties</value>
  4. </property>
  5. </bean>

换句话说,conf/credentials.properties这里保存的就是连接activemq的用户名和密码,启用连接的安全机制后,spring的配置文件要做如下调整:

  1. <bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
  2. <property name="connectionFactory">
  3. <bean class="org.apache.activemq.ActiveMQConnectionFactory">
  4. <!--broker服务的地址-->
  5. <property name="brokerURL" value="tcp://localhost:61616"/>
  6. <!--默认值为1000,如果不需要这么大,可以调小-->
  7. <property name="maxThreadPoolSize" value="100"/>
  8. <property name="userName" value="system"/>
  9. <property name="password" value="manager"/>
  10. </bean>
  11. </property>
  12. </bean>

4.2 生产者代码

发送消息的代码有二种写法:

a)利用spring-jms的JmsTemplate

  1. package com.cnblogs.yjmyzz.activemq;
  2.  
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. import org.springframework.jms.core.JmsTemplate;
  6.  
  7. /**
  8. * ActiveMQ消息发送示例(利用JMSTemplate)
  9. * Author:菩提树下的杨过 http://yjmyzz.cnblogs.com
  10. */
  11. public class JmsTemplateProducer {
  12.  
  13. public static void main(String[] args) {
  14.  
  15. ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
  16. JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
  17.  
  18. System.out.println("准备发送消息...");
  19. int max = 100000;
  20. Long start = System.currentTimeMillis();
  21. for (int i = 0; i < max; i++) {
  22. jmsTemplate.convertAndSend("message test:" + i);
  23. }
  24. Long end = System.currentTimeMillis();
  25. Long elapse = end - start;
  26. int perform = Double.valueOf(max / (elapse / 1000d)).intValue();
  27.  
  28. System.out.print("发送 " + max + " 条消息,耗时:" + elapse + "毫秒,平均" + perform + "条/秒");
  29. }
  30. }

b) 利用activeMQ的Producer

  1. package com.cnblogs.yjmyzz.activemq;
  2.  
  3. import org.apache.activemq.command.ActiveMQQueue;
  4. import org.apache.activemq.pool.PooledConnectionFactory;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;
  7.  
  8. import javax.jms.*;
  9. import java.io.IOException;
  10.  
  11. /**
  12. * ActiveMQ消息发送示例(利用Producer)
  13. * Author:菩提树下的杨过 http://yjmyzz.cnblogs.com
  14. */
  15. public class ActiveMQProducer {
  16.  
  17. public static void main(String[] args) throws JMSException, IOException, InterruptedException {
  18. ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
  19. PooledConnectionFactory connectionFactory = context.getBean(PooledConnectionFactory.class);
  20. ActiveMQQueue destination = context.getBean(ActiveMQQueue.class);
  21. Connection connection = connectionFactory.createConnection();
  22. connection.start();
  23. Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  24. MessageProducer producer = session.createProducer(destination);
  25.  
  26. System.out.println("准备发送消息...");
  27. int max = 100000;
  28. Long start = System.currentTimeMillis();
  29.  
  30. for (int i = 0; i < max; i++) {
  31. TextMessage msg = session.createTextMessage("message test:" + i);
  32. //msg.setIntProperty("id", i);
  33. producer.send(msg);
  34. }
  35. Long end = System.currentTimeMillis();
  36. Long elapse = end - start;
  37. int perform = Double.valueOf(max / (elapse / 1000d)).intValue();
  38.  
  39. System.out.print("发送 " + max + " 条消息,耗时:" + elapse + "毫秒,平均" + perform + "条/秒");
  40.  
  41. //producer.send(session.createTextMessage("SHUTDOWN"));
  42. //Thread.sleep(1000 * 3);
  43. //connection.close();
  44. System.exit(0);
  45. }
  46. }

这二种方式在性能上差不多,4核8G的mac book pro上,大致每秒可以写入3k+条消息。但是从代码量来讲,明显JmsTemplate的代码量更少,推荐使用。

4.3 消费者代码

当然也可以用JmsTemplate接收消息,但是一般得自己去写while(true)循环,而且默认情况下,上下文如果不是同一个连接,JmsTemplate A发出的消息,JmsTemplate B是接收不到的,所以不建议这种方式。最好参考下面的示例,使用JMS的MessageLisenter去监听消息,这也是JMS规范建议的标准做法:

  1. package com.cnblogs.yjmyzz.activemq;
  2.  
  3. import org.apache.activemq.command.ActiveMQQueue;
  4. import org.apache.activemq.pool.PooledConnectionFactory;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;
  7. import javax.jms.*;
  8. import java.io.IOException;
  9.  
  10. /**
  11. * ActiveMQ消息接收示例(使用MessageListener)
  12. * Author:菩提树下的杨过 http://yjmyzz.cnblogs.com
  13. */
  14. public class MessageListenerConsumer {
  15.  
  16. public static void main(String[] args) throws JMSException, IOException {
  17. ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
  18. PooledConnectionFactory connectionFactory = context.getBean(PooledConnectionFactory.class);
  19. ActiveMQQueue destination = context.getBean(ActiveMQQueue.class);
  20. Connection connection = connectionFactory.createConnection();
  21. connection.start();
  22. Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  23. MessageConsumer consumer = session.createConsumer(destination);
  24. consumer.setMessageListener(new ActiveMQListener());
  25. System.in.read();
  26. }
  27.  
  28. static class ActiveMQListener implements MessageListener {
  29. @Override
  30. public void onMessage(Message message) {
  31. try {
  32. if (message instanceof TextMessage) {
  33. System.out.println(((TextMessage) message).getText());
  34. }
  35. } catch (JMSException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. }
  40. }

4.4 嵌入式Broker

类似jetty、tombat之类可以内嵌到代码中启动一样,ActiveMQ也可以直接在代码中内嵌启动,这个很方便一些轻量级的使用场景,示例代码如下:

  1. public class EmbbedBroker {
  2. public static void main(String[] args) throws Exception {
  3. BrokerService broker = new BrokerService();
  4. broker.addConnector("tcp://localhost:61616");
  5. broker.start();
  6. System.out.println("ActiveMQ 已启动!");
  7. }
  8. }

关于嵌入式Broker的更多细节,可以参考 http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html

4.5 消息的自动确认与手动确认

在接收消息时,如果Session使用的是 Session.AUTO_ACKNOWLEDGE,即:

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

则消息一旦被接受,不论onMessage()里的业务逻辑执行成功与否,消息都将从ActiveMQ的队列里立刻删除。如果希望业务处理成功后,再通知ActiveMQ删除消息,可以改成:

  1. Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);

然后onMessage方法调用message.acknowledge手动确认,参考以下代码:

  1. static class ActiveMQListener implements MessageListener {
  2. @Override
  3. public void onMessage(Message message) {
  4. try {
  5. if (message instanceof TextMessage) {
  6. System.out.println(((TextMessage) message).getText());
  7. message.acknowledge(); //手动确认消息
  8. }
  9. } catch (JMSException e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. }

  

ActiveMQ笔记(1):编译、安装、示例代码的更多相关文章

  1. 20190418 CentOS7实用技能综合:系统安装 + WinScp客户端连接 + 防火墙端口号iptables + Nginx编译安装 + MySQL编译安装 + Redis编译安装 + MongoDB编译安装 + ActiveMQ/RocketMQ/RabbitMQ编译安装 + ...各类常用生产环境软件的编译安装

    系统安装 + WinScp客户端连接 + 防火墙端口号iptables + Nginx编译安装 + MySQL编译安装 + Redis编译安装 + MongoDB编译安装 + ActiveMQ/Roc ...

  2. Sqlite学习笔记(一)&&编译安装

    Sqlite简介 sqlite是一个开源的嵌入式文件数据库,sqlite以动态链接库的方式供应用程序调用,所有的数据库对象都存储在同一个文件中. sqlite动态库非常小,最新的3.8.11版本也只有 ...

  3. redis 学习笔记(2)-client端示例代码

    redis提供了几乎所有主流语言的client,java中主要使用二种:Jedis与Redisson 一.Jedis的使用 <dependency> <groupId>redi ...

  4. 末学者笔记--apache编译安装及LAMP架构上线

    apache介绍 一.Apache的三种工作模式 Apache一共有3种稳定的MPM模式(多进程处理模块),它们分别是prefork.worker.event.http-2.2版本的httpd默认的m ...

  5. Redis笔记 -- make编译安装报错记录2则(一)

    1.Redis的获取与安装,目前最新稳定版本为4.0.10 Redis:  https://redis.io/download GitHub:  https://github.com/antirez/ ...

  6. wechat开发笔记之1.接口示例代码

    修改后的php示例代码! <?php /** * wechat php test */ //define your token define("TOKEN", "w ...

  7. [运维笔记] Nginx编译安装

    yum -y install pcre-devel.x86_64 yum -y install openssl openssl-devel.x86_64 useradd www -s /sbin/no ...

  8. CentOS 6.3编译安装LAMP环境笔记

    转载地址:http://www.jb51.net/article/54969.htm 最近抽空在虚拟机上测试成功了LAMP各个最新版本的整合编译安装,算是把之前的博文整合精简,以下内容均在CENTOS ...

  9. nginx编译安装之-./configure 参数详解

    参考官方文档 http://nginx.org/en/docs/configure.html --with开头的,默认是禁用的(没启动的,想使用的话需要在编译的时候加上) --without开头的,默 ...

随机推荐

  1. linux内核调试技术之printk

    原创博客:欢迎转载,转载请注明出处https://i.cnblogs.com/EditPosts.aspx?postid=6218383 1.简介(基于s3c2440 linux) 在内核调试技术之中 ...

  2. context:component-scan" 的前缀 "context" 未绑定。

    SpElUtilTest.testSpELLiteralExpressiontestSpELLiteralExpression(cn.zr.spring.spel.SpElUtilTest)org.s ...

  3. [Tool] github 入手教程

    简单的介绍一下 Github 的基本操作. 主页:https://github.com/ 首先自然是在 GitHub 注册一个帐号了.然后开始正文吧. Git 基本介绍 Git 是属于分布式版本控制系 ...

  4. 初识C#接口

    C# 接口(Interface) 接口定义了所有类继承接口时应遵循的语法合同.接口定义了语法合同 "是什么" 部分,派生类定义了语法合同 "怎么做" 部分. 接 ...

  5. GridView详细介绍

    GridView控件的属性 表10.6 GridView控件的行为属性属性描述AllowPaging指示该控件是否支持分页.AllowSorting指示该控件是否支持排序.AutoGenerateCo ...

  6. Go语言开发

    Go语言圣经(中文版)     Go编程语言规范 搭建Go开发及调试环境(LiteIDE + GoClipse) -- Windows篇           Go开发工具 Go命令行操作命令详细介绍 ...

  7. Linux下安装Hadoop完全分布式(Ubuntu12.10)

    Hadoop的安装非常简单,可以在官网上下载到最近的几个版本,最好使用稳定版.本例在3台机器集群安装.hadoop版本如下: 工具/原料 hadoop-0.20.2.tar.gz Ubuntu12.1 ...

  8. Angular通过XHR加载模板而限制使用file://(解决方案)

    编写angular项目时,遇到此困难: angular.js:12011 XMLHttpRequest cannot load file:///E:/angular/imooc/chapter2/bo ...

  9. R语言:常用统计检验

    统计检验是将抽样结果和抽样分布相对照而作出判断的工作.主要分5个步骤: 建立假设 求抽样分布 选择显著性水平和否定域 计算检验统计量 判定 -- 百度百科 假设检验(hypothesis test)亦 ...

  10. Using AlloyTouch to control three.js 3D model

    As you can see, the above cube rotation, acceleration, deceleration stop all through the AlloyTouch ...