ActiveMQ下载地址
http://activemq.apache.org/download-archives.html
ActiveMQ 依赖JDK版本
MQ版本号 | Build-Jdk | 依赖JDK |
---|---|---|
apache-activemq-5.0.0 | 1.5.0_12 | 1.5+ |
apache-activemq-5.1.0 | 1.5.0_12 | 1.5+ |
apache-activemq-5.2.0 | 1.5.0_15 | 1.5+ |
apache-activemq-5.3.0 | 1.5.0_17 | 1.5+ |
apache-activemq-5.4.0 | 1.5.0_19 | 1.5+ |
apache-activemq-5.5.0 | 1.6.0_23 | 1.6+ |
apache-activemq-5.6.0 | 1.6.0_26 | 1.6+ |
apache-activemq-5.7.0 | 1.6.0_33 | 1.6+ |
apache-activemq-5.8.0 | 1.6.0_37 | 1.6+ |
apache-activemq-5.9.0 | 1.6.0_51 | 1.6+ |
apache-activemq-5.10.0 | 1.7.0_12-ea | 1.7+ |
apache-activemq-5.11.0 | 1.7.0_60 | 1.7+ |
apache-activemq-5.12.0 | 1.7.0_80 | 1.7+ |
apache-activemq-5.13.0 | 1.7.0_80 | 1.7+ |
apache-activemq-5.14.0 | 1.7.0_80 | 1.7+ |
apache-activemq-5.14.5 apache-activemq-5.15.0 | 1.8.0_112 | 1.8+ |
为何讲ActiveMQ依赖JDK版本呢
当版本不对应时启动activeMQ时没问题,但是后台页面访问不了同时停止时会报错,错如下图
如何查看官方发布ActiveMQ依赖JDK版本
解压apache-activemq-5.15.2-bin.tar.gz 里面有一个activemq-all-5.15.2.jar 打开jar包里面的META-INF目录下有MANIFEST.MF文件,里面有Build-Jdk:1.8.0_144,就是对应jdk版本号
安装部署步骤(activemq5.13. 2 JDK版本jdk1.7.0_80)
# 查看是否自带了Java rpm -qa | grep java # 卸载Linux自带的OpenJava yum remove -y java # 或者 rpm -e java # 上传或联网下载JDK 7 rz jdk-7u80-linux-x64.rpm # 或者 wget http://download.Oracle.com/otn-pub/java/jdk/7u80-b15/jdk-7u80-linux-x64.rpm rpm -ivh jdk-7u80-linux-x64.rpm java -version vi ~/.bash_profile --------------------------------------------- export JAVA_HOME=/usr/java/jdk1.7.0_80 export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar --------------------------------------------- source ~/.bash_profile echo $JAVA_HOME # 上传或联网下载activemq rz apache-activemq-5.13.2-bin.tar.gz # 或者 wget http://archive.apache.org/dist/activemq/5.13.2/apache-activemq-5.13.2-bin.tar.gz tar zxvf apache-activemq-5.13.2-bin.tar.gz mv apache-activemq-5.13.2 /usr/local/activemq # 直接改造activemq原生启动脚本来做服务引导脚本 ln -s /usr/local/activemq/bin/activemq /etc/init.d/ vi /etc/init.d/activemq --------------------------------------------- # 第二行插入(注释可以不管) # chkconfig: 345 63 37 # description: Auto start ActiveMQ --------------------------------------------- # 可以设置开机启动了 chkconfig activemq on chkconfig --list activemq # 启动服务看看 service activemq start
# 设置防火墙
service iptables status
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 61616 -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 8161 -j ACCEPT
service iptables save
service iptables restart
如上部署好后,就可以正常使用,默认消息端口是61616,后台管理网址端口8161,直接用浏览器打开后台管理网址,界面如下:
activemq console参数进行前台启动,可能会暴露出错误原因,命令如下:
# 先停用activemq service activemq stop # 手动控制台方式启动 /usr/local/activemq/bin/activemq console
查看 activemq进程 ps -ef | grep activemq
修改ActiveMQ的配置
1,broker配置:
- [root@centos6 bin]$ vi ../conf/activemq.xml
broker策略配置:
- <destinationPolicy>
- <policyMap>
- <policyEntries>
- <policyEntry topic=">" producerFlowControl="true">
- <!-- 如果一个消费者消费消息的速度比较慢,这会对非持久化主题产生影响, -->
- <!-- 因为消息会在broker的内存中大量堆积,由于开启了producer-flow-control,-->
- <!-- 将导致所有的生产者生产消息的速度放慢,这样即使某些消费消息速度非常 -->
- <!-- 快的消费者也将放慢其消费消息的速度 -->
- <!-- 为此增加了以下几种策略控制 -->
- <!-- broker为该主题最多保存1000条消息,如果消息数目超过了1000, -->
- <!-- 旧消息将被丢弃 -->
- <pendingMessageLimitStrategy>
- <constantPendingMessageLimitStrategy limit="1000"/>
- </pendingMessageLimitStrategy>
- </policyEntry>
- </policyEntries>
- </policyMap>
- </destinationPolicy>
生产者流控制(producer-flow-control)配置:
如果broker占用的内存或硬盘空间到达配置值,broker会阻塞消息生产者的send()方法,直到一些消息被消费,broker才能够继续接收新消息并使用被消费消息所占用的内存或硬盘空间存放新的消息
- <systemUsage>
- <!-- broker一直没有可使用空间将有可能导致消息生产者的send()方法无限阻塞 -->
- <!-- 一种替代方式是使用下面的配置,这时send()方法将会失败并抛出一个 -->
- <!-- javax.jms.ResourceAllocationException异常 -->
- <!-- <systemUsage sendFailIfNoSpace="true"> -->
- <!-- 更好的解决方式如下,客户端会首先等待3000毫秒,然后再次尝试 -->
- <!-- 如果此时broker依然没有足够的空间可用,才抛出异常 -->
- <systemUsage sendFailIfNoSpaceAfterTimeout="3000">
- <!-- 非持久化消息最大占用内存大小 -->
- <memoryUsage>
- <memoryUsage percentOfJvmHeap="70" />
- </memoryUsage>
- <!-- 持久化消息最大占用硬盘大小 -->
- <storeUsage>
- <storeUsage limit="100 gb"/>
- </storeUsage>
- <!-- 临时消息最大占用硬盘大小 -->
- <tempUsage>
- <tempUsage limit="50 gb"/>
- </tempUsage>
- </systemUsage>
- </systemUsage>
去掉非必需的通信协议(Client与Broker、Broker与Broker之间使用该协议进行通信),只留下TCP协议(特别需要注意的是61616是broker的监听端口):
- <transportConnectors>
- <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
- <transportConnector name="tcp" uri="tcp://0.0.0.0:61616
- ?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- <!--
- <transportConnector name="amqp" uri="amqp://0.0.0.0:5672
- ?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="stomp" uri="stomp://0.0.0.0:61613
- ?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883
- ?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="ws" uri="ws://0.0.0.0:61614
- ?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- -->
- </transportConnectors>
2,web服务配置:
$ACTIVEMQ_HOME/conf/activemq.xml文件的最后引入了jetty.xml文件:
- <import resource="jetty.xml"/>
ActiveMQ中内置了一个servlet引擎(参见$ACTIVEMQ_HOME/conf/jetty.xml,角色权限、校验规则等配置都在该文件中,这里不详细说明了),用以提供web监控服务,默认的端口号是8161:
- <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
- <!-- the default port number for the web console -->
- <property name="port" value="8161"/>
- </bean>
web服务需要登录后才能使用,账号信息保存在$ACTIVEMQ_HOME/conf/jetty-realm.properties文件中:
- <bean id="securityLoginService" class="org.eclipse.jetty.security.HashLoginService">
- <property name="name" value="ActiveMQRealm" />
- <property name="config" value="${activemq.conf}/jetty-realm.properties" />
- </bean>
$ACTIVEMQ_HOME/conf/jetty-realm.properties中的账号、账号密码和账号角色信息如下:
- # Defines users that can access the web (console, demo, etc.)
- # username: password [,rolename ...]
- admin: admin, admin
- user: user, user
3,日志配置:
- [root@centos6 bin]$ vi ../conf/log4j.properties
ActiveMQ的日志文件存放路径如下:
- log4j.appender.logfile.file=${activemq.base}/data/activemq.log
- ......
- log4j.appender.logfile.layout.ConversionPattern=%d | %-5p | %m | %c | %t%n
四,启动ActiveMQ
- [root@centos6 bin]$ ./activemq start
- [root@centos6 data]# ../bin/activemq start
INFO: Loading '/usr/local/apache-activemq-5.13.2//bin/env'
INFO: Using java '/usr/java/jdk1.7.0_80/bin/java'
INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details
INFO: pidfile created : '/usr/local/apache-activemq-5.13.2//data/activemq.pid' (pid '31944 - 通过ps -ef | grep activemq命令可以看到ActiveMQ的进程号是31944
查看日志文件
1.[root@centos6 apache-activemq-5.13.2]# cd ./data/
2.[root@centos6 data]# tail -90f activemq.log
日志中有如下信息说明ActiveMQ启动成功:
还能够看到很多其它重要信息:
1.[root@centos6 data]# netstat -an|grep 8161tcp 0 0 :::8161 :::* LISTEN
2.[root@centos6 data]# netstat -an|grep 61616
tcp 0 0 :::61616 :::* LISTEN
ActiveMQ启动后,可以通过Web服务查看其状态,账号密码为admin/admin:
五,简单测试
消息生产者:
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class MessageSender {
private static String URL = "tcp://localhost:61616";
private static String QUEUE_NAME = "test_queue";
public static void main(String[] args) {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(URL);
Connection conn = null;
Session sess = null;
try {
conn = factory.createConnection();
conn.start();
sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination dest = sess.createQueue(QUEUE_NAME);
MessageProducer producer = sess.createProducer(dest);
TextMessage msg = sess.createTextMessage("Just a test!");
producer.send(msg);
} catch (JMSException e) {
e.printStackTrace();
} finally {
if(sess != null)
try {
sess.close();
} catch (JMSException e) {
e.printStackTrace();
}
if(conn != null)
try {
conn.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
消息消费者,有两种实现方式:
1,Listener
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
public class IMessageListener implements MessageListener {
private static String URL = "tcp://localhost:61616";
private static String QUEUE_NAME = "test_queue";
public void onMessage(Message msg) {
if(null != msg && msg instanceof TextMessage){
try {
System.out.println("Message : " + ((TextMessage)msg).getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(URL);
Connection conn = null;
Session sess = null;
try {
conn = factory.createConnection();
conn.start();
sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination dest = sess.createQueue(QUEUE_NAME);
MessageConsumer consumer = sess.createConsumer(dest);
consumer.setMessageListener(new IMessageListener());
} catch (JMSException e) {
e.printStackTrace();
} /*finally { // 连接关闭就没有consumer了
if(sess != null)
try {
sess.close();
} catch (JMSException e) {
e.printStackTrace();
}
if(conn != null)
try {
conn.close();
} catch (JMSException e) {
e.printStackTrace();
}
}*/
}
}
2,Receiver
运行结果如下:
1. Message : Just a test!