使用 jdbc 方式配置主从模式,持久化消息存放在数据库中。

在同一时刻,只有一个 master broker,master 接受客户端的连接,slave 不接受连接。
当 master 因为关机而下线后,其中一个 slave 会提升为 master,然后接受客户端连接。但原来 master 的非持久消息丢失了,而持久消息保存在数据库中。

broker xml 配置:使用 MySQL 数据源

<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Use JDBC for message persistence
For more information, see: http://activemq.apache.org/persistence.html You need to add Derby database to your classpath in order to make this example work.
Download it from http://db.apache.org/derby/ and put it in the ${ACTIVEMQ_HOME}/lib/optional/ folder
Optionally you can configure any other RDBM as shown below To run ActiveMQ with this configuration add xbean:conf/activemq-jdbc.xml to your command e.g. $ bin/activemq xbean:conf/activemq-jdbc.xml
-->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"> <broker useJmx="false" brokerName="jdbcBroker" xmlns="http://activemq.apache.org/schema/core">
<persistenceAdapter>
<jdbcPersistenceAdapter dataDirectory="${activemq.base}/data" dataSource="#mysql-ds"/>
</persistenceAdapter> <transportConnectors>
<transportConnector name="default" uri="tcp://0.0.0.0:61616"/>
</transportConnectors>
</broker> <!-- Embedded Derby DataSource Sample Setup -->
<!-- <bean id="derby-ds" class="org.apache.derby.jdbc.EmbeddedDataSource">
<property name="databaseName" value="derbydb"/>
<property name="createDatabase" value="create"/>
</bean> --> <!-- Postgres DataSource Sample Setup -->
<!--
<bean id="postgres-ds" class="org.postgresql.ds.PGPoolingDataSource">
<property name="serverName" value="localhost"/>
<property name="databaseName" value="activemq"/>
<property name="portNumber" value="0"/>
<property name="user" value="activemq"/>
<property name="password" value="activemq"/>
<property name="dataSourceName" value="postgres"/>
<property name="initialConnections" value="1"/>
<property name="maxConnections" value="10"/>
</bean>
--> <!-- MySql DataSource Sample Setup --> <bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.40.8:3306/db_zhang?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="200"/>
<property name="poolPreparedStatements" value="true"/>
</bean> <!-- Oracle DataSource Sample Setup -->
<!--
<bean id="oracle-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:AMQDB"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
<property name="maxActive" value="200"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
--> </beans>

客户端配置,producer 和 consumer 是一样的:

new ActiveMQConnectionFactory("failover:(tcp://localhost:61616,tcp://localhost:61618)");

以 MySQL 数据库为例,启动 broker 后,MySQL 中会创建 3 张表:
ACTIVEMQ_MSGS 存放持久消息
ACTIVEMQ_LOCK 表中只有一条记录,broker 执行 SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE 获取锁,获得锁的 broker 是 master
ACTIVEMQ_ACKS

broker 获取锁的调用栈如下:

// org.apache.activemq.store.jdbc.DefaultDatabaseLocker
public void doStart() throws Exception { LOG.info("Attempting to acquire the exclusive lock to become the Master broker");
// SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE
String sql = getStatements().getLockCreateStatement();
LOG.debug("Locking Query is "+sql); while (true) {
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
lockCreateStatement = connection.prepareStatement(sql);
// 执行 SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE
// 如果成功,则跳出循环。如果超时,则抛异常
lockCreateStatement.execute();
break;
} catch (Exception e) {
try {
if (isStopping()) {
throw new Exception(
"Cannot start broker as being asked to shut down. "
+ "Interrupted attempt to acquire lock: "
+ e, e);
}
if (exceptionHandler != null) {
try {
exceptionHandler.handle(e);
} catch (Throwable handlerException) {
LOG.error( "The exception handler "
+ exceptionHandler.getClass().getCanonicalName()
+ " threw this exception: "
+ handlerException
+ " while trying to handle this exception: "
+ e, handlerException);
} } else {
LOG.debug("Lock failure: "+ e, e);
}
} finally {
// Let's make sure the database connection is properly
// closed when an error occurs so that we're not leaking
// connections
if (null != connection) {
try {
connection.rollback();
} catch (SQLException e1) {
LOG.debug("Caught exception during rollback on connection: " + e1, e1);
}
try {
connection.close();
} catch (SQLException e1) {
LOG.debug("Caught exception while closing connection: " + e1, e1);
} connection = null;
}
}
} finally {
if (null != lockCreateStatement) {
try {
lockCreateStatement.close();
} catch (SQLException e1) {
LOG.debug("Caught while closing statement: " + e1, e1);
}
lockCreateStatement = null;
}
} LOG.info("Failed to acquire lock. Sleeping for " + lockAcquireSleepInterval + " milli(s) before trying again...");
try {
Thread.sleep(lockAcquireSleepInterval);
} catch (InterruptedException ie) {
LOG.warn("Master lock retry sleep interrupted", ie);
}
} LOG.info("Becoming the master on dataSource: " + dataSource);
}

broker 执行 SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE 获取锁,获取成功,则成为 master,如果失败,则睡眠一段时间后,继续获取锁。

超时而抛出的异常:

ActiveMQ 配置jdbc主从的更多相关文章

  1. AMQ学习笔记 - 14. 实践方案:基于ZooKeeper + ActiveMQ + replicatedLevelDB的主从部署

    概述 基于ZooKeeper + ActiveMQ + replicatedLevelDB,在Windows平台的主从部署方案. 主从部署可以提供数据备份.容错[1]的功能,但是不能提供负载均衡的功能 ...

  2. ActiveMQ配置详解

    原文链接 一.消息目的地策略 在节点destinationPolicy配置策略,可以对单个或者所有的主题和队列进行设置,使用流量监控,当消息达到memoryLimit的时候,ActiveMQ会减慢消息 ...

  3. 从零开始学 Java - Spring 集成 ActiveMQ 配置(一)

    你家小区下面有没有快递柜 近两年来,我们收取快递的方式好像变了,变得我们其实并不需要见到快递小哥也能拿到自己的快递了.对,我说的就是类似快递柜.菜鸟驿站这类的代收点的出现,把我们原来快递小哥必须拿着快 ...

  4. 从零开始学 Java - Spring 集成 ActiveMQ 配置(二)

    从上一篇开始说起 上一篇从零开始学 Java - Spring 集成 ActiveMQ 配置(一)文章中讲了我关于消息队列的思考过程,现在这一篇会讲到 ActivMQ 与 Spring 框架的整合配置 ...

  5. 使用配置文件来配置JDBC连接数据库

    1.管理数据库连接的Class 代码如下: package jdbcTest;import java.sql.Connection;import java.sql.DriverManager;impo ...

  6. spring中配置jdbc数据源

    1.加入jdbc驱动器包,mysql-connector-java.jar 2.加入commons-dbcp.jar配置数据源 3.在classpath下新建文件jdbc.properties,配置j ...

  7. redis主从配置及主从切换 转

    redis主从配置及主从切换 转自 http://blog.sina.com.cn/s/blog_67196ddc0101h8v0.html (2014-04-28 17:48:47) 转载▼   分 ...

  8. weblogic配置jdbc数据源

    weblogic配置jdbc数据源的过程 方法/步骤   启动weblogic 管理服务器,使用管理用户登录weblogic管理控制台   打开管理控制台后,在左侧的树形域结构中,选择服务->数 ...

  9. 配置mysql主从步骤

    在公司开发中,有时候为了缓解数据库压力,会把读写分开为两个数据库来操作,读为一个数据库,写为一个数据库,然后两个数据库做同步,这样能明显降低数据库的压力,下面给大家介绍如何进行mysql主从数据库配置 ...

随机推荐

  1. Oracle spatial、openlayers、geoserver开发地理信息系统总结

    感谢开源,使用OpenLayers+Geoserver的地理信息系统开发很简单,完全可以套用开发MIS系统的经验,我这里总结为三个步骤: 1.数据准备 2.数据发布 3.数据展现 我将按照这个思路来介 ...

  2. CSDN-markdown编辑器语法——字体、字号与颜色

     Markdown是一种可以使用普通文本编辑器编写的标记语言,通过类似HTML的标记语法,它可以使普通文本内容具有一定的格式.但是它本身是不支持修改字体.字号与颜色等功能的!   CSDN-markd ...

  3. Django中ORM系统多表数据操作

    一,多表操作之增删改查 1.在seting.py文件中配置数据库连接信息 2.创建数据库关联关系models.py from django.db import models # Create your ...

  4. 使用ajax判断登录用户名

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Register.aspx. ...

  5. Java中String类型细节

    Java中String类型细节 一 . String两种初始化方式 1 . String str1= “abc”;//String类特有的创建字符对象的方式,更高效 在字符串缓冲区中检测”abc”是否 ...

  6. Android 虹软免费人脸识别App

    人脸识别+本机Web后端 人脸sdk采用虹软sdk,本机web采用AndServer:上传姓名+人脸图片即可实现注册源码地址:https://github.com/joetang1989/ArcFac ...

  7. Codeforces 1043 F - Make It One

    F - Make It One 思路: dp + 容斥 首先, 答案不会超过7, 因为前7个质数的乘积大于3e5(最坏的情况是7个数, 每个数都缺少一个不同的因子) 所以从1到7依次考虑 dp[i][ ...

  8. Codeforces 101173 C - Convex Contour

    思路: 如果所有的图形都是三角形,那么答案是2*n+1 否则轮廓肯定触到了最上面,要使轮廓线最短,那么轮廓肯定是中间一段平的 我们考虑先将轮廓线赋为2*n+2,然后删去左右两边多余的部分 如果最左边或 ...

  9. vue-循环标记列表元素

    <el-col :lg="4" class="list" v-for="(item,index) in picList"> &l ...

  10. jenkins之从0到1利用Git和Ant插件打war包并自动部署到tomcat(第二话):安装插件,配置JDK、Git、Ant

    jenkins之所以这么强大,离不开丰富的插件库. 要确保jenkins上安装好Git plugin.GitHub plugin.AntPlugin插件,一般在启动jenkins时默认安装的插件中就包 ...