ActiveMQ Failover broker url顺序

 

ActiveMQ的客户端支持失效重连。昨天在配置ActiveMQ的主从结构后,客户端使用失效重连协议连接到代理,如下所示:

Java代码   收藏代码
  1. failover:(tcp://master:61616,tcp://slave:61616)  

 测试的时候客户端有时候连接到master上,有时候连接到slave上。这就尴尬了,正常理解的话,配在前面的broker url应该先尝试连接,连接不上才连接后面的url,即从前到后的顺序,但是测试结果来看,是不一定的。

使用logback打开了ActiveMQ的日志

Java代码   收藏代码
  1. <logger name="org.apache.activemq" level="debug" additivity="false">  
  2.     <appender-ref ref="STDOUT"/>  
  3. </logger>  

 日志中输出的确有的时候只直接连了slave,而不是每次都先连master,而且master是正常的,那就说明的确客户端是做过处理了,并不是按从前到后的顺序依次连接。

日志中会输出“Successfully connected to slave...”,logback配置中输出了代码行数,因此很快定位到程序,org.apache.activemq.transport.failover.FailoverTransport类的876行(客户端使用的是activemq-all-5.4.3.jar),代码如下

Java代码   收藏代码
  1. final boolean doReconnect() {  
  2.         Exception failure = null;  
  3.         synchronized (reconnectMutex) {  
  4.   
  5.             // If updateURIsURL is specified, read the file and add any new  
  6.             // transport URI's to this FailOverTransport.   
  7.             // Note: Could track file timestamp to avoid unnecessary reading.  
  8.             String fileURL = getUpdateURIsURL();  
  9.             if (fileURL != null) {  
  10.                 BufferedReader in = null;  
  11.                 String newUris = null;  
  12.                 StringBuffer buffer = new StringBuffer();  
  13.   
  14.                 try {  
  15.                     in = new BufferedReader(getURLStream(fileURL));  
  16.                     while (true) {  
  17.                         String line = in.readLine();  
  18.                         if (line == null) {  
  19.                             break;  
  20.                         }  
  21.                         buffer.append(line);  
  22.                     }  
  23.                     newUris = buffer.toString();  
  24.                 } catch (IOException ioe) {  
  25.                     LOG.error("Failed to read updateURIsURL: " + fileURL, ioe);  
  26.                 } finally {  
  27.                     if (in != null) {  
  28.                         try {  
  29.                             in.close();  
  30.                         } catch (IOException ioe) {  
  31.                             // ignore  
  32.                         }  
  33.                     }  
  34.                 }  
  35.                   
  36.                 processNewTransports(isRebalanceUpdateURIs(), newUris);  
  37.             }  
  38.   
  39.             if (disposed || connectionFailure != null) {  
  40.                 reconnectMutex.notifyAll();  
  41.             }  
  42.   
  43.             if (connectedTransport.get() != null || disposed || connectionFailure != null) {  
  44.                 return false;  
  45.             } else {  
  46.                 List<URI> connectList = getConnectList();  
  47.                 if (connectList.isEmpty()) {  
  48.                     failure = new IOException("No uris available to connect to.");  
  49.                 } else {  
  50.                     if (!useExponentialBackOff || reconnectDelay == -1) {  
  51.                         reconnectDelay = initialReconnectDelay;  
  52.                     }  
  53.                     synchronized (backupMutex) {  
  54.                         if (backup && !backups.isEmpty()) {  
  55.                             BackupTransport bt = backups.remove(0);  
  56.                             Transport t = bt.getTransport();  
  57.                             URI uri = bt.getUri();  
  58.                             t.setTransportListener(myTransportListener);  
  59.                             try {  
  60.                                 if (started) {  
  61.                                     restoreTransport(t);  
  62.                                 }  
  63.                                 reconnectDelay = initialReconnectDelay;  
  64.                                 failedConnectTransportURI = null;  
  65.                                 connectedTransportURI = uri;  
  66.                                 connectedTransport.set(t);  
  67.                                 reconnectMutex.notifyAll();  
  68.                                 connectFailures = 0;  
  69.                                 LOG.info("Successfully reconnected to backup " + uri);  
  70.                                 return false;  
  71.                             } catch (Exception e) {  
  72.                                 LOG.debug("Backup transport failed", e);  
  73.                             }  
  74.                         }  
  75.                     }  
  76.   
  77.                     Iterator<URI> iter = connectList.iterator();  
  78.                     while (iter.hasNext() && connectedTransport.get() == null && !disposed) {  
  79.                         URI uri = iter.next();  
  80.                         Transport t = null;  
  81.                         try {  
  82.                             LOG.debug("Attempting connect to: " + uri);  
  83.                             SslContext.setCurrentSslContext(brokerSslContext);  
  84.                             t = TransportFactory.compositeConnect(uri);  
  85.                             t.setTransportListener(myTransportListener);  
  86.                             t.start();  
  87.   
  88.                             if (started) {  
  89.                                 restoreTransport(t);  
  90.                             }  
  91.   
  92.                             LOG.debug("Connection established");  
  93.                             reconnectDelay = initialReconnectDelay;  
  94.                             connectedTransportURI = uri;  
  95.                             connectedTransport.set(t);  
  96.                             reconnectMutex.notifyAll();  
  97.                             connectFailures = 0;  
  98.                             // Make sure on initial startup, that the  
  99.                             // transportListener  
  100.                             // has been initialized for this instance.  
  101.                             synchronized (listenerMutex) {  
  102.                                 if (transportListener == null) {  
  103.                                     try {  
  104.                                         // if it isn't set after 2secs - it  
  105.                                         // probably never will be  
  106.                                         listenerMutex.wait(2000);  
  107.                                     } catch (InterruptedException ex) {  
  108.                                     }  
  109.                                 }  
  110.                             }  
  111.                             if (transportListener != null) {  
  112.                                 transportListener.transportResumed();  
  113.                             } else {  
  114.                                 LOG.debug("transport resumed by transport listener not set");  
  115.                             }  
  116.                             if (firstConnection) {  
  117.                                 firstConnection = false;  
  118.                                 <span style="font-size: 1.1em; line-height: 1.3em;">LOG.info("Successfully connected to " + uri);</span>  
  119.                             } else {  
  120.                                 LOG.info("Successfully reconnected to " + uri);  
  121.                             }  
  122.                             connected = true;  
  123.                             return false;  
  124.                         } catch (Exception e) {  
  125.                             failure = e;  
  126.                             LOG.debug("Connect fail to: " + uri + ", reason: " + e);  
  127.                             if (t != null) {  
  128.                                 try {  
  129.                                     t.stop();  
  130.                                 } catch (Exception ee) {  
  131.                                     LOG.debug("Stop of failed transport: " + t + " failed with reason: " + ee);  
  132.                                 }  
  133.                             }  
  134.                         } finally {  
  135.                             SslContext.setCurrentSslContext(null);  
  136.                         }  
  137.                     }  
  138.                 }  
  139.             }  
  140.             int reconnectAttempts = 0;  
  141.             if (firstConnection) {  
  142.                 if (this.startupMaxReconnectAttempts != 0) {  
  143.                     reconnectAttempts = this.startupMaxReconnectAttempts;  
  144.                 }  
  145.             }  
  146.             if (reconnectAttempts == 0) {  
  147.                 reconnectAttempts = this.maxReconnectAttempts;  
  148.             }  
  149.             if (reconnectAttempts > 0 && ++connectFailures >= reconnectAttempts) {  
  150.                 LOG.error("Failed to connect to transport after: " + connectFailures + " attempt(s)");  
  151.                 connectionFailure = failure;  
  152.   
  153.                 // Make sure on initial startup, that the transportListener has  
  154.                 // been initialized  
  155.                 // for this instance.  
  156.                 synchronized (listenerMutex) {  
  157.                     if (transportListener == null) {  
  158.                         try {  
  159.                             listenerMutex.wait(2000);  
  160.                         } catch (InterruptedException ex) {  
  161.                         }  
  162.                     }  
  163.                 }  
  164.   
  165.                 if (transportListener != null) {  
  166.                     if (connectionFailure instanceof IOException) {  
  167.                         transportListener.onException((IOException) connectionFailure);  
  168.                     } else {  
  169.                         transportListener.onException(IOExceptionSupport.create(connectionFailure));  
  170.                     }  
  171.                 }  
  172.                 reconnectMutex.notifyAll();  
  173.                 return false;  
  174.             }  
  175.         }  
  176.         if (!disposed) {  
  177.   
  178.             LOG.debug("Waiting " + reconnectDelay + " ms before attempting connection. ");  
  179.             synchronized (sleepMutex) {  
  180.                 try {  
  181.                     sleepMutex.wait(reconnectDelay);  
  182.                 } catch (InterruptedException e) {  
  183.                     Thread.currentThread().interrupt();  
  184.                 }  
  185.             }  
  186.   
  187.             if (useExponentialBackOff) {  
  188.                 // Exponential increment of reconnect delay.  
  189.                 reconnectDelay *= backOffMultiplier;  
  190.                 if (reconnectDelay > maxReconnectDelay) {  
  191.                     reconnectDelay = maxReconnectDelay;  
  192.                 }  
  193.             }  
  194.         }  
  195.         return !disposed;  
  196.     }  

 代码List<URI> connectList = getConnectList();获取配置的broker url,打了断点后debug发现,这边获取的List中的URI有时候已经不是配置中的顺序了,进入getConnectList方法

Java代码   收藏代码
  1. private List<URI> getConnectList() {  
  2.         ArrayList<URI> l = new ArrayList<URI>(uris);  
  3.         boolean removed = false;  
  4.         if (failedConnectTransportURI != null) {  
  5.             removed = l.remove(failedConnectTransportURI);  
  6.         }  
  7.         if (randomize) {  
  8.             // Randomly, reorder the list by random swapping  
  9.             for (int i = 0; i < l.size(); i++) {  
  10.                 int p = (int) (Math.random() * 100 % l.size());  
  11.                 URI t = l.get(p);  
  12.                 l.set(p, l.get(i));  
  13.                 l.set(i, t);  
  14.             }  
  15.         }  
  16.         if (removed) {  
  17.             l.add(failedConnectTransportURI);  
  18.         }  
  19.         LOG.debug("urlList connectionList:" + l);  
  20.         return l;  
  21.     }  

 这边有个randomize,默认值为true,即默认这边会对配置的url重新排序,所以导致连接初始化是可能不是按照想象的从前到后的顺序连接,解决也简单,在连接后价格参数,将randomize设为false

Java代码   收藏代码
  1. failover:(tcp://master:61616,tcp://slave:61616)?randomize=false  

 这样每次都会先连接master,master连不上才会连slave。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值