功能需求
- master 正常时 所有请求router到master;
- master不正常时,DQL路由到slaves(slaves 会进行负载均衡,算法自定),DML DDL等抛异常;
直接贴代码 简单点
Demo.java
package com.yiwugou.demo.sharding;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import io.shardingsphere.core.api.MasterSlaveDataSourceFactory;
import io.shardingsphere.core.api.config.MasterSlaveRuleConfiguration;
public class Demo {
private static YiwugouConfig config = new YiwugouConfig();
public static void main(String[] args) throws Exception {
DataSource masterSlaveDataSource = initMasterSlaveDataSource();
DataSource dataSource = initYiwugouDataSource(masterSlaveDataSource);
JdbcTemplate jdbcTemplate = initJdbcTemplate(dataSource);
for (int i = 0; i <= 100000; i++) {
try {
List<Map<String, Object>> objs = jdbcTemplate.queryForList("select * from T_DEMO");
System.err.println(i + "=" + objs);
Thread.sleep(1000L);
} catch (Exception e) {
e.printStackTrace();
}
// try {
// jdbcTemplate.update("insert into T_DEMO (name) values ('abcd" + i
// + "')");
// System.err.println("execute=" + i);
// Thread.sleep(1000L);
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}
public static DataSource initYiwugouDataSource(DataSource dataSource) {
YiwugouDataSource ds = new YiwugouDataSource(dataSource, config);
return ds;
}
public static DataSource initMasterSlaveDataSource() throws SQLException {
DataSource ds_72 = initDataSource("com.mysql.jdbc.Driver", "jdbc:mysql://10.6.2.72:3306/demo", "root",
"admin123");
DataSource ds_127 = initDataSource("com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1:3306/demo", "root", "");
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("ds_master", ds_127);
dataSourceMap.put("ds_slave_0", ds_72);
// dataSourceMap.put("ds_slave_1", slaveDataSource1);
MasterSlaveRuleConfiguration masterSlaveRuleConfig = new MasterSlaveRuleConfiguration("ds_master_slave",
"ds_master", Arrays.asList("ds_slave_0"));
DataSource dataSource = MasterSlaveDataSourceFactory.createDataSource(dataSourceMap, masterSlaveRuleConfig,
new HashMap<String, Object>());
return dataSource;
}
public static DataSource initDataSource(String driver, String url, String username, String password) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setMaxActive(100);
dataSource.setMinIdle(5);
dataSource.setFailFast(true); // 重要 不然会卡住
Filter yiwugouFilter = new YiwugouFilter(new Runnable() {
@Override
public void run() {
config.setAlived(false);
}
});
dataSource.setProxyFilters(Arrays.asList(yiwugouFilter));
// dataSource.setBreakAfterAcquireFailure(true);
// dataSource.setAsyncInit(true);
return dataSource;
}
public static JdbcTemplate initJdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
}
YiwugouConfig.java
package com.yiwugou.demo.sharding;
public class YiwugouConfig {
private boolean isAlived = true;
public boolean isAlived() {
return isAlived;
}
public void setAlived(boolean isAlived) {
this.isAlived = isAlived;
}
}
YiwugouDataSource
package com.yiwugou.demo.sharding;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import javax.sql.DataSource;
import io.shardingsphere.core.api.HintManager;
public class YiwugouDataSource implements DataSource {
private DataSource dataSource;
private YiwugouConfig config;
public YiwugouDataSource(DataSource dataSource, YiwugouConfig config) {
this.dataSource = dataSource;
this.config = config;
}
@Override
public Connection getConnection() throws SQLException {
if (config.isAlived()) {
HintManager hintManager = HintManager.getInstance();
hintManager.setMasterRouteOnly();
}
Connection con = this.getDataSource().getConnection();
return con;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
if (config.isAlived()) {
HintManager hintManager = HintManager.getInstance();
hintManager.setMasterRouteOnly();
}
Connection con = this.getDataSource().getConnection(username, password);
return con;
}
private DataSource getDataSource() {
return this.dataSource;
}
@Override
public void setLoginTimeout(int timeout) throws SQLException {
this.getDataSource().setLoginTimeout(timeout);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return this.getDataSource().getLogWriter();
}
@Override
public void setLogWriter(PrintWriter pw) throws SQLException {
this.getDataSource().setLogWriter(pw);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return this.getDataSource().unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return this.getDataSource().isWrapperFor(iface);
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return this.getDataSource().getParentLogger();
}
@Override
public int getLoginTimeout() throws SQLException {
return this.getDataSource().getLoginTimeout();
}
}
YiwugouFilter.java
package com.yiwugou.demo.sharding;
import java.sql.SQLException;
import com.alibaba.druid.filter.FilterAdapter;
import com.alibaba.druid.filter.FilterChain;
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;
import com.alibaba.druid.proxy.jdbc.ResultSetProxy;
import com.alibaba.druid.proxy.jdbc.StatementProxy;
public class YiwugouFilter extends FilterAdapter {
public YiwugouFilter(Runnable runnable) {
this.runnable = runnable;
}
private Runnable runnable;
@Override
public void preparedStatement_addBatch(FilterChain chain, PreparedStatementProxy statement) throws SQLException {
try {
super.preparedStatement_addBatch(chain, statement);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement) throws SQLException {
try {
return super.preparedStatement_execute(chain, statement);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)
throws SQLException {
try {
return super.preparedStatement_executeQuery(chain, statement);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public int preparedStatement_executeUpdate(FilterChain chain, PreparedStatementProxy statement)
throws SQLException {
try {
return super.preparedStatement_executeUpdate(chain, statement);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException {
try {
super.statement_addBatch(chain, statement, sql);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException {
try {
return super.statement_execute(chain, statement, sql);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)
throws SQLException {
try {
return super.statement_execute(chain, statement, sql, autoGeneratedKeys);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)
throws SQLException {
try {
return super.statement_execute(chain, statement, sql, columnIndexes);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)
throws SQLException {
try {
return super.statement_execute(chain, statement, sql, columnNames);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public int[] statement_executeBatch(FilterChain chain, StatementProxy statement) throws SQLException {
try {
return super.statement_executeBatch(chain, statement);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)
throws SQLException {
try {
return super.statement_executeQuery(chain, statement, sql);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException {
try {
return super.statement_executeUpdate(chain, statement, sql);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)
throws SQLException {
try {
return super.statement_executeUpdate(chain, statement, sql, autoGeneratedKeys);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)
throws SQLException {
try {
return super.statement_executeUpdate(chain, statement, sql, columnIndexes);
} catch (Exception e) {
runnable.run();
throw e;
}
}
@Override
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)
throws SQLException {
try {
return super.statement_executeUpdate(chain, statement, sql, columnNames);
} catch (Exception e) {
runnable.run();
throw e;
}
}
}