搭建ActiveMQ,分在三个服务器上,单机版activemq的直接解压后启动即可,下面描述的是依赖于zookeeper选举的集群。
10.1.58.19 node1
10.1.58.26 node2
10.1.58.29 node3
1 解压
tar -zxvf apache-activemq-5.14.1-bin.tar.gz
2 创建文件夹
mkdir /usr/local/activemq-cluster
3 移动
将第一步解压的文件夹移动到activemq-cluster下
4 改名文件夹
mv apache-activemq-5.14.1 node1
(其他两台服务器也如此操作并分别改名为node2,node3)
5 修改conf/activemq.xml文件
vim activemq.xml。修改其中的bind、zkAddress、bhotname、zkPath。
5.1 第一处修改:
brokerName="active-cluster"
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-cluster" dataDirectory="${activemq.data}">
......
</broker>
5.2 第二处修改:
<persistenceAdapter>
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="10.1.58.19:2181,10.1.58.26:2181,10.1.58.29:2181"
hostname="10.1.58.19"
zkPath="/activemq/leveldb-stores"/>
</persistenceAdapter>
<persistenceAdapter>
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="10.1.58.19:2181,10.1.58.26:2181,10.1.58.29:2181"
hostname="10.1.58.26"
zkPath="/activemq/leveldb-stores"/>
</persistenceAdapter>
<persistenceAdapter>
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="10.1.58.19:2181,10.1.58.26:2181,10.1.58.29:2181"
hostname="10.1.58.29"
zkPath="/activemq/leveldb-stores"/>
</persistenceAdapter>
5.3 node1 第三处修改
修改name="openwire"
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61619?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5671?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>
这里的端口如果与本地冲突了可以修改下,我的改成这样:
-- 61616 改为 61619 -- 5671 改为 5679
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61619?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5679?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>
6 集群搭建完毕,测试一下
a.先启动zookeeper zkServer.sh start(有三个zookeeper,貌似第二个启动的是leader,用$zkServer.sh status查看)
b.再启动activemq ./activemq start
c.查看日志看是否出错 $ tail -f node1/data/activemq.log(最先启动的是master,其他的都是slaver)
访问地址:10.1.58.19:8161/admin
正mq挂掉了,当时排查,zookeeper没有问题,后来修改了activemq.xml里面的内存,改大,解决了问题。
7 设置密码
安全配置
1、控制台安全配置,打开conf/jetty.xml文件,找到
<bean id="securityConstraint" class="org.eclipse.jetty.http.security.Constraint">
<property name="name" value="BASIC" />
<property name="roles" value="admin" />
<property name="authenticate" value="false" />
</bean>
将“false”改为“true”即可。用户名和密码存放在conf/jetty-realm.properties文件中。
2、生产者和消费者连接MQ需要密码,打开conf/activemq.xml文件,在<broker>标签里的<systemUsage>标签前加入:-- 测试线加了这个配置后启动报错
<plugins>
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="${activemq.username}" password="${activemq.password}" groups="users,admins" />
</users>
</simpleAuthenticationPlugin>
</plugins>
注意必须在<systemUsage>标签前,否则启动ActiveMQ会报错。用户名和密码存放在conf/credentials.properties文件中
后台登录页面 http://10.1.58.19:8161/admin/queues.jsp admin/admin
程序中连接的地址 failover:(tcp://10.1.58.19:61619,tcp://tcp://10.1.58.26:61619,tcp://tcp://10.1.58.29:61619)?Randomize=false
activemq.username=system
activemq.password=richinfo20180828
8 测试java代码
//测试代码
package cn.zephyr.common.util.activemq;
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.ActiveMQConnectionFactory;
public class Sender {
public static void main(String[] args) {
try {
//第一步:建立ConnectionFactory工厂对象,需要填入用户名、密码、以及要连接的地址,均使用默认即可,默认端口为"tcp://localhost:61616"
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD,
"failover:(tcp://10.1.58.19:61619,tcp://tcp://10.1.58.26:61619,tcp://tcp://10.1.58.29:61619)?Randomize=false");
//第二步:通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的。
Connection connection = connectionFactory.createConnection();
connection.start();
//第三步:通过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用是事务,参数配置2为签收模式,一般我们设置自动签收。
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//第四步:通过Session创建Destination对象,指的是一个客户端用来指定生产消息目标和消费消息来源的对象,在PTP模式中,Destination被称作Queue即队列;在Pub/Sub模式,Destination被称作Topic即主题。在程序中可以使用多个Queue和Topic。
Destination destination = session.createQueue("lifeng");
//第五步:我们需要通过Session对象创建消息的发送和接收对象(生产者和消费者)MessageProducer/MessageConsumer。
MessageProducer producer = session.createProducer(null);
//第六步:我们可以使用MessageProducer的setDeliveryMode方法为其设置持久化特性和非持久化特性(DeliveryMode),我们稍后详细介绍。
//producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//第七步:最后我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的send方法发送数据。同理客户端使用receive方法进行接收数据。最后不要忘记关闭Connection连接。
for(int i = 0 ; i < 50 ; i ++){
TextMessage msg = session.createTextMessage("丑八怪" + i);
// 第一个参数目标地址
// 第二个参数 具体的数据信息
// 第三个参数 传送数据的模式
// 第四个参数 优先级
// 第五个参数 消息的过期时间
producer.send(destination, msg, DeliveryMode.NON_PERSISTENT, 0 , 1000L);
System.out.println("发送消息:" + msg.getText());
Thread.sleep(1000);
}
if(connection != null){
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package cn.zephyr.common.util.activemq;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class Receiver {
public static void main(String[] args) {
try {
//第一步:建立ConnectionFactory工厂对象,需要填入用户名、密码、以及要连接的地址,均使用默认即可,默认端口为"tcp://localhost:61616"
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD,
"failover:(tcp://10.1.58.19:61619,tcp://tcp://10.1.58.26:61619,tcp://tcp://10.1.58.29:61619)?Randomize=false");
//第二步:通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的。
Connection connection = connectionFactory.createConnection();
connection.start();
//第三步:通过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用是事务,参数配置2为签收模式,一般我们设置自动签收。
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//第四步:通过Session创建Destination对象,指的是一个客户端用来指定生产消息目标和消费消息来源的对象,在PTP模式中,Destination被称作Queue即队列;在Pub/Sub模式,Destination被称作Topic即主题。在程序中可以使用多个Queue和Topic。
Destination destination = session.createQueue("lifeng");
//第五步:通过Session创建MessageConsumer
MessageConsumer consumer = session.createConsumer(destination);
while(true){
TextMessage msg = (TextMessage)consumer.receive();
if(msg == null) break;
System.out.println("收到的内容:" + msg.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}