linux下搭建activemq高可用集群

一. 简介

           从 ActiveMQ 5.9 开始,ActiveMQ 的集群实现方式取消了传统的 Master-Slave 方式,增加了基于 ZooKeeper + LevelDB 的 Master-Slave 实现方式,其他两种方式目录共享和数据库共享依然存在。本文采用zookeeper来管理节点实现activemq的高可用。

           zookeeper集群的安装说明,请参照笔者的另一篇博客: linux下安装zookeeper集群

二. 集群部署说明

2.1 节点信息

 activemq.xmlactivemq.xmljetty.xml 
主机

集群端口

replicatedLevelDB.bind

消息端口

transportConnector.uri

管控台端口

jettyPort.port

安装目录
182.61.53.64tcp://0.0.0.0:62621515118161/home/env/activemq
182.61.61.90tcp://0.0.0.0:62622515128161/home/env/activemq
182.61.32.229tcp://0.0.0.0:62623515138161/home/env/activemq

 

 

 

 

 

2.2 安装activemq

           给三台服务器分别安装activemq. 

           activemq的安装说明,请参照笔者的另一篇博客: linux下安装activemq

 

三. 配置高可用

3.1 修改activemq.xml

3.1.1 修改brokerName

注: 三台机器要一致,此处,均改为"activemqCluster"

3.1.2 为persistenceAdapter添加replicatedLevelDB元素

注:zkAddress为之前搭好的三台zookeeper集群的地址。 

        其它俩台也这样修改,需要注意: zookeeper之间和ip:port之间不要有多余的空格。

        bind分别为 tcp://0.0.0.0:62621,tcp://0.0.0.0:62622,tcp://0.0.0.0:62623

        hostname要对应各自服务器的ip(182.61.61.90, 182.61.32.229)即可。         

 
  1. <persistenceAdapter>

  2.  
  3. <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->

  4.  
  5. <!-- activemq zookeeper high availiability -->

  6. <replicatedLevelDB

  7. directory="${activemq.data}/leveldb"

  8. replicas="3"

  9. bind="tcp://0.0.0.0:62623"

  10. zkAddress="182.61.53.64:2181,182.61.61.90:2181,182.61.32.229:2181"

  11. hostname="182.61.32.229"

  12. zkPath="/activemq/leveldb-stores"

  13. />

  14.  
  15. </persistenceAdapter>

 

3.1.3 修改消息端口uri

注: 将uri的链接端口分别改为51511, 51512, 51513即可

 

四. 测试

4.1 控制台访问测试

        分别访问三台activemq的控制台,发现只有一台可以访问。

        关闭这台后,再访问另外俩台,发现有一台可以访问。

4.2 代码测试

4.2.1 代码

A.. pom.xml

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  4. <modelVersion>4.0.0</modelVersion>

  5.  
  6. <groupId>com.yzx</groupId>

  7. <artifactId>activemqdemo</artifactId>

  8. <version>0.0.1-SNAPSHOT</version>

  9. <packaging>jar</packaging>

  10.  
  11. <name>activemqdemo</name>

  12. <description>Demo project for Spring Boot</description>

  13.  
  14. <parent>

  15. <groupId>org.springframework.boot</groupId>

  16. <artifactId>spring-boot-starter-parent</artifactId>

  17. <version>2.0.3.RELEASE</version>

  18. <relativePath/> <!-- lookup parent from repository -->

  19. </parent>

  20.  
  21. <properties>

  22. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  23. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

  24. <java.version>1.8</java.version>

  25. </properties>

  26.  
  27. <dependencies>

  28.  
  29. <dependency>

  30. <groupId>org.springframework.boot</groupId>

  31. <artifactId>spring-boot-starter-web</artifactId>

  32. </dependency>

  33.  
  34. <!-- activemq -->

  35. <dependency>

  36. <groupId>org.springframework.boot</groupId>

  37. <artifactId>spring-boot-starter-activemq</artifactId>

  38. </dependency>

  39. <dependency>

  40. <groupId>org.apache.activemq</groupId>

  41. <artifactId>activemq-pool</artifactId>

  42. </dependency>

  43. <!-- activemq -->

  44.  
  45. <dependency>

  46. <groupId>com.alibaba</groupId>

  47. <artifactId>fastjson</artifactId>

  48. <version>1.2.40</version>

  49. </dependency>

  50.  
  51. <dependency>

  52. <groupId>org.springframework.boot</groupId>

  53. <artifactId>spring-boot-starter-test</artifactId>

  54. <scope>test</scope>

  55. </dependency>

  56. </dependencies>

  57.  
  58. <build>

  59. <plugins>

  60. <plugin>

  61. <groupId>org.springframework.boot</groupId>

  62. <artifactId>spring-boot-maven-plugin</artifactId>

  63. </plugin>

  64. </plugins>

  65. </build>

  66.  
  67.  
  68. </project>

B. application.yml

 
  1. server:

  2. port: 8080

  3.  
  4. spring:

  5. activemq:

  6. #broker-url: tcp://47.106.116.228:61616

  7. broker-url: failover:(tcp://182.61.53.64:51511,tcp://182.61.61.90:51512,tcp://182.61.32.229:51513)

  8. user: admin

  9. password: admin

  10. pool:

  11. enabled: true

  12. packages:

  13. trust-all: true # 如果使用ObjectMessage传输对象,必须要加上这个信任包,否则会报ClassNotFound异常

  14. jms:

  15. pub-sub-domain: true # 启动主题消息

C. ActiveMqConfig

 
  1. package com.yzx.activemqdemo.demo1;

  2.  
  3.  
  4. import org.springframework.context.annotation.Bean;

  5. import org.springframework.context.annotation.Configuration;

  6. import org.springframework.jms.config.DefaultJmsListenerContainerFactory;

  7. import org.springframework.jms.config.JmsListenerContainerFactory;

  8.  
  9. import javax.jms.ConnectionFactory;

  10.  
  11. @Configuration

  12. public class ActiveMqConfig {

  13.  
  14.  
  15. // queue模式的ListenerContainer

  16. @Bean

  17. public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ConnectionFactory activeMQConnectionFactory) {

  18. DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();

  19. bean.setConnectionFactory(activeMQConnectionFactory);

  20. return bean;

  21. }

  22.  
  23.  
  24. // topic模式的ListenerContainer

  25. @Bean

  26. public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {

  27. DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();

  28. bean.setPubSubDomain(true);

  29. bean.setConnectionFactory(activeMQConnectionFactory);

  30. return bean;

  31. }

  32.  
  33. }

D. MqProducer

 
  1. package com.yzx.activemqdemo.demo1;

  2.  
  3. import org.apache.activemq.command.ActiveMQQueue;

  4. import org.apache.activemq.command.ActiveMQTopic;

  5. import org.springframework.beans.factory.annotation.Autowired;

  6. import org.springframework.jms.core.JmsMessagingTemplate;

  7. import org.springframework.stereotype.Service;

  8.  
  9. import java.io.Serializable;

  10. import java.util.List;

  11.  
  12. @Service

  13. public class MqProducer {

  14.  
  15.  
  16. @Autowired

  17. private JmsMessagingTemplate jmsMessagingTemplate;

  18.  
  19.  
  20. /**

  21. * 发送字符串消息队列

  22. *

  23. * @param queueName 队列名称

  24. * @param message 字符串

  25. */

  26. public void sendStringQueue(String queueName, String message) {

  27. this.jmsMessagingTemplate.convertAndSend(new ActiveMQQueue(queueName), message);

  28. }

  29.  
  30.  
  31. }

E. QueueConsumer

 
  1. package com.yzx.activemqdemo.demo1;

  2.  
  3. import org.springframework.jms.annotation.JmsListener;

  4. import org.springframework.stereotype.Component;

  5.  
  6. import javax.jms.ObjectMessage;

  7. import java.util.List;

  8.  
  9. @Component

  10. public class QueueConsumer {

  11.  
  12. @JmsListener(destination = "stringQueue", containerFactory = "jmsListenerContainerQueue")

  13. public void receiveStringQueue(String msg) {

  14. System.out.println("接收到消息...." + msg);

  15. }

  16.  
  17.  
  18. }

F. ActivemqdemoApplicationTests

 
  1. package com.yzx.activemqdemo;

  2.  
  3. import com.yzx.activemqdemo.demo1.MqProducer;

  4. import com.yzx.activemqdemo.demo1.User;

  5. import org.junit.Test;

  6. import org.junit.runner.RunWith;

  7. import org.springframework.beans.factory.annotation.Autowired;

  8. import org.springframework.boot.test.context.SpringBootTest;

  9. import org.springframework.test.context.junit4.SpringRunner;

  10.  
  11. import java.io.Serializable;

  12. import java.util.ArrayList;

  13. import java.util.List;

  14.  
  15. @RunWith(SpringRunner.class)

  16. @SpringBootTest

  17. public class ActivemqdemoApplicationTests {

  18.  
  19. @Autowired

  20. private MqProducer mqProducer;

  21.  
  22.  
  23. @Test

  24. public void testStringQueue() {

  25.  
  26. for (int i = 1; i <= 1000; i++) {

  27. System.out.println("第" + i + "次发送字符串队列消息");

  28. mqProducer.sendStringQueue("stringQueue", "消息:" + i);

  29. }

  30. }

  31.  
  32. }

4.2.2 运行结果

A. 初次正好选中主节点直接发消息

 
  1. 2018-07-29 18:21:34.503 INFO 25764 --- [ActiveMQ Task-1] o.a.a.t.failover.FailoverTransport : Successfully connected to tcp://182.61.53.64:51511

  2. 2018-07-29 18:21:34.695 INFO 25764 --- [ main] c.y.a.ActivemqdemoApplicationTests : Started ActivemqdemoApplicationTests in 4.931 seconds (JVM running for 6.787)

  3. 第1次发送字符串队列消息

  4. 第2次发送字符串队列消息

  5. 第3次发送字符串队列消息

  6. 接收到消息....消息:1

  7. 接收到消息....消息:2

B. 初次没有选中主节点,先报异常,然后直接选中主节点发消息

 
  1. 2018-07-29 18:23:08.454 INFO 23884 --- [ActiveMQ Task-1] o.a.a.t.failover.FailoverTransport : Successfully connected to tcp://182.61.32.229:51513

  2. 2018-07-29 18:23:17.796 WARN 23884 --- [229:51513@55464] o.a.a.t.failover.FailoverTransport : Transport (tcp://182.61.32.229:51513) failed , attempting to automatically reconnect: {}

  3.  
  4. java.net.SocketException: Software caused connection abort: recv failed

  5. at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.8.0_171]

  6. at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[na:1.8.0_171]

  7. at java.net.SocketInputStream.read(SocketInputStream.java:189) ~[na:1.8.0_171]

  8. at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_171]

  9. at org.apache.activemq.transport.tcp.TcpBufferedInputStream.fill(TcpBufferedInputStream.java:50) ~[activemq-client-5.15.4.jar:5.15.4]

  10. at org.apache.activemq.transport.tcp.TcpTransport$2.fill(TcpTransport.java:634) ~[activemq-client-5.15.4.jar:5.15.4]

  11. at org.apache.activemq.transport.tcp.TcpBufferedInputStream.read(TcpBufferedInputStream.java:59) ~[activemq-client-5.15.4.jar:5.15.4]

  12. at org.apache.activemq.transport.tcp.TcpTransport$2.read(TcpTransport.java:619) ~[activemq-client-5.15.4.jar:5.15.4]

  13. at java.io.DataInputStream.readInt(DataInputStream.java:387) ~[na:1.8.0_171]

  14. at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:268) ~[activemq-client-5.15.4.jar:5.15.4]

  15. at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:240) ~[activemq-client-5.15.4.jar:5.15.4]

  16. at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:232) ~[activemq-client-5.15.4.jar:5.15.4]

  17. at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:215) ~[activemq-client-5.15.4.jar:5.15.4]

  18. at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]

  19.  
  20. 2018-07-29 18:23:17.847 INFO 23884 --- [ActiveMQ Task-2] o.a.a.t.failover.FailoverTransport : Successfully reconnected to tcp://182.61.53.64:51511

  21. 2018-07-29 18:23:17.914 INFO 23884 --- [ main] c.y.a.ActivemqdemoApplicationTests : Started ActivemqdemoApplicationTests in 14.434 seconds (JVM running for 16.723)

  22. 第1次发送字符串队列消息

  23. 第2次发送字符串队列消息

  24. 接收到消息....消息:1

 

C. 在发送消息的过程中,主节点挂了,会在zookeeper选举新的主节点之后继续将剩余的消息消费掉。

     为方便测试,将发送消息的数量调到1000, 中间关闭主节点64的mq.

 
  1. 第237次发送字符串队列消息

  2. 接收到消息....消息:236

  3. 2018-07-29 18:35:11.204 WARN 26616 --- [.64:51511@55365] o.a.a.t.failover.FailoverTransport : Transport (tcp://182.61.53.64:51511) failed , attempting to automatically reconnect: {}

  4.  
  5. java.net.SocketException: Software caused connection abort: recv failed

  6. at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.8.0_171]

  7. at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[na:1.8.0_171]

  8. at java.net.SocketInputStream.read(SocketInputStream.java:189) ~[na:1.8.0_171]

  9. at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_171]

  10. at org.apache.activemq.transport.tcp.TcpBufferedInputStream.fill(TcpBufferedInputStream.java:50) ~[activemq-client-5.15.4.jar:5.15.4]

  11. at org.apache.activemq.transport.tcp.TcpTransport$2.fill(TcpTransport.java:634) ~[activemq-client-5.15.4.jar:5.15.4]

  12. at org.apache.activemq.transport.tcp.TcpBufferedInputStream.read(TcpBufferedInputStream.java:59) ~[activemq-client-5.15.4.jar:5.15.4]

  13. at org.apache.activemq.transport.tcp.TcpTransport$2.read(TcpTransport.java:619) ~[activemq-client-5.15.4.jar:5.15.4]

  14. at java.io.DataInputStream.readInt(DataInputStream.java:387) ~[na:1.8.0_171]

  15. at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:268) ~[activemq-client-5.15.4.jar:5.15.4]

  16. at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:240) ~[activemq-client-5.15.4.jar:5.15.4]

  17. at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:232) ~[activemq-client-5.15.4.jar:5.15.4]

  18. at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:215) ~[activemq-client-5.15.4.jar:5.15.4]

  19. at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]

  20.  
  21. 2018-07-29 18:35:39.313 INFO 26616 --- [ActiveMQ Task-2] o.a.a.t.failover.FailoverTransport : Successfully reconnected to tcp://182.61.61.90:51512

  22. 2018-07-29 18:35:39.452 WARN 26616 --- [ Session Task-4] o.a.activemq.ActiveMQMessageConsumer : ID:PC--20180608YMM-55364-1532860506351-1:1:10:1 suppressing duplicate delivery on connection, poison acking: MessageDispatch {commandId = 0, responseRequired = false, consumerId = ID:PC--20180608YMM-55364-1532860506351-1:1:10:1, destination = queue://stringQueue, message = ActiveMQTextMessage {commandId = 498, responseRequired = true, messageId = ID:PC--20180608YMM-55364-1532860506351-1:1:13:1:236, originalDestination = null, originalTransactionId = null, producerId = ID:PC--20180608YMM-55364-1532860506351-1:1:13:1, destination = queue://stringQueue, transactionId = null, expiration = 0, timestamp = 1532860511134, arrival = 0, brokerInTime = 1532860510868, brokerOutTime = 1532860539178, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@4311891c, marshalledProperties = org.apache.activemq.util.ByteSequence@139629ab, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {timestamp=1532860511133}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = 消息:236}, redeliveryCounter = 0}

  23. 第238次发送字符串队列消息

  24. 接收到消息....消息:237

  25. 第239次发送字符串队列消息

  26. 接收到消息....消息:238

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值