com.github.javaclub.cdl.client.config.DbConfigManager Maven / Gradle / Ivy
package com.github.javaclub.cdl.client.config;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
import com.github.javaclub.cdl.client.atom.SAtomDataSource;
import com.github.javaclub.cdl.client.common.DataSourceHolder;
import com.github.javaclub.cdl.client.common.DataSourceWrapper;
import com.github.javaclub.cdl.client.group.DBSelector;
import com.github.javaclub.cdl.client.group.DefaultDBSelector;
import com.github.javaclub.cdl.client.group.SGroupDataSource;
import com.github.javaclub.cdl.client.matrix.rule.DynamicRouterStrategy;
import com.github.javaclub.cdl.client.util.LogUtils;
import com.github.javaclub.cdl.client.util.MasterSlaveSwitch;
import com.github.javaclub.configcenter.client.ConfigListener;
import com.github.javaclub.configcenter.client.DefaultConfigCenterClient;
import com.github.javaclub.configcenter.client.util.DESCoder;
/**
* DB动态配置管理
*/
public class DbConfigManager {
private static final Logger logger = LoggerFactory.getLogger(DbConfigManager.class);
private String appId;
private String appKey;
private String appName;
private String env;
private boolean onlyAtom = false;
private boolean enableTrace = false;
private ConcurrentMap sGroupDataSourceMap = new ConcurrentHashMap<>();
private volatile Map dbWSelectorMap = new ConcurrentHashMap<>();
private volatile Map dbRSelectorMap = new ConcurrentHashMap<>();
private Map dataSourceWrapperMap = new ConcurrentHashMap<>();
private volatile Map dbGroupCfgMap;
private Map dbGroupInitedMap = new ConcurrentHashMap<>();
private ReadWriteLock lock = new ReentrantReadWriteLock();
private Object lockObject = new Object();
private DefaultConfigCenterClient defaultConfigCenterClient;
public synchronized void init() throws Exception {
defaultConfigCenterClient = new DefaultConfigCenterClient();
logger.warn("begin to init DB, [appId={}, appKey={}, appName={}, env={}]", appId, appKey, appName, env);
LogUtils.printCdlLog(String.format("begin to init DB, [appId: %s, appKey: %s, appName: %s, env: %s]", appId, appKey, appName, env));
if (!onlyAtom) {
List dbGroupCfg = getGroupCfg(appKey, appName, new ConfigListener() {
@SuppressWarnings("unchecked")
@Override
public void update(String newConfig) {
try {
if (StringUtils.isNotBlank(newConfig)) {
String rawCfg = DESCoder.decrpty(newConfig, appKey);
if (rawCfg != null) {
LogUtils.printCdlLog("begin to update db cfg ...");
updateDB(JSONObject.parseObject(rawCfg, List.class));
LogUtils.printCdlLog("end to update db cfg ...");
}
}
} catch (Exception e) {
logger.error("", e);
}
}
});
initDbGroupList(dbGroupCfg);
logger.warn("end to init DB");
LogUtils.printCdlLog("end to init DB");
}
}
public synchronized Map getAtomConf(String groupName, String dsKey, final SAtomDataSource sAtomDataSource) {
try {
String configkey = appName + "." + groupName + "." + dsKey;
Map dbaKeyMap = getDBAKey();
int dbaid = Integer.parseInt(dbaKeyMap.get("dbaid"));
String dbakey = dbaKeyMap.get("dbakey");
String value = defaultConfigCenterClient.getConfig(dbaid, dbakey, configkey, new ConfigListener() {
@Override
public void update(String newConfig) {
try {
if (StringUtils.isNotBlank(newConfig)) {
sAtomDataSource.updateConf(parseAtomConf(DESCoder.decrpty(newConfig, appKey)));
}
} catch (Exception e) {
logger.error("", e);
}
}
});
if (StringUtils.isNotBlank(value)) {
return parseAtomConf(DESCoder.decrpty(value, appKey));
}
} catch (Exception e) {
logger.error(" ", e);
}
return null;
}
public String getShardDynamicRouter(final DynamicRouterStrategy dynamicRouterStrategy) {
String configkey = appName + ".shard.router";
Map dbaKeyMap = getDBAKey();
int dbaid = Integer.parseInt(dbaKeyMap.get("dbaid"));
String dbakey = dbaKeyMap.get("dbakey");
String value = defaultConfigCenterClient.getConfig(dbaid, dbakey, configkey, new ConfigListener() {
@Override
public void update(String newConfig) {
try {
if (StringUtils.isNotBlank(newConfig)) {
dynamicRouterStrategy.updateRouter(newConfig);
}
} catch (Exception e) {
logger.error("", e);
}
}
});
return value;
}
@SuppressWarnings("unchecked")
private Map parseAtomConf(String conf) {
if (StringUtils.isNotBlank(conf)) {
return JSONObject.parseObject(conf, Map.class);
}
return null;
}
public void registerSGroupDataSource(String groupName, SGroupDataSource sGroupDataSource) throws SQLException {
sGroupDataSourceMap.put(groupName, sGroupDataSource);
initOneDbGroup(groupName);
}
public SGroupDataSource getSGroupDataSource(String groupName) throws SQLException {
if (null == sGroupDataSourceMap.get(groupName)) {
createSGroupDataSource(groupName);
}
return sGroupDataSourceMap.get(groupName);
}
public void createSGroupDataSource(String groupName) throws SQLException {
synchronized (lockObject){
if (null == sGroupDataSourceMap.get(groupName)) {
SGroupDataSource sGroupDataSource = new SGroupDataSource();
sGroupDataSource.setGroupName(groupName);
sGroupDataSource.setDbConfigManager(this);
sGroupDataSource.init();
}
}
}
public DBSelector getDBSelector(String groupName, boolean isRead) throws SQLException {
try {
if(MasterSlaveSwitch.isMaster()){
isRead = false;
}
if(MasterSlaveSwitch.isSlave()){
isRead = true;
}
lock.readLock().lock();
DBSelector dBSelector;
if (isRead) {
dBSelector = dbRSelectorMap.get(groupName);
} else {
dBSelector = dbWSelectorMap.get(groupName);
}
if (dBSelector == null) {
throw new RuntimeException("Not found any datasource for:appName[" + appName + "],groupName[" + groupName + "],isRead[" + isRead + "]");
}
return dBSelector;
} finally {
MasterSlaveSwitch.clear();
lock.readLock().unlock();
}
}
private void initDbGroupList(List list) throws SQLException {
if (list != null && !list.isEmpty()) {
Map tmp = new HashMap<>();
for (JSONObject object : list) {
DbGroupCfg dbGroupCfg = getDbGroupCfgFromJson(object);
logger.warn("dbGroupCfg: {}", dbGroupCfg.toString());
LogUtils.printCdlLog(String.format("dbGroupCfg: %s", dbGroupCfg.toString()));
tmp.put(dbGroupCfg.getGroupName(), dbGroupCfg);
dbGroupInitedMap.put(dbGroupCfg.getGroupName(), false); // lazy init
}
dbGroupCfgMap = tmp;
} else {
throw new RuntimeException("not found any dbGroup cfg");
}
}
private synchronized void initOneDbGroup(String groupName) throws SQLException {
if (dbGroupInitedMap.get(groupName) != null && dbGroupInitedMap.get(groupName)) {
return;
}
dbWSelectorMap.remove(groupName);
dbRSelectorMap.remove(groupName);
DbGroupCfg dbGroupCfg = dbGroupCfgMap.get(groupName);
if (dbGroupCfg == null) {
throw new RuntimeException("not found dbgroup cfg for " + groupName);
}
for (String dsKey : dbGroupCfg.getAtomCfgMap().keySet()) {
DbAtomCfg dbAtomCfg = JSONObject.parseObject(dbGroupCfg.getAtomCfgMap().get(dsKey), DbAtomCfg.class);
DataSourceWrapper dataSourceWrapper = dataSourceWrapperMap.get(dsKey);
if (dataSourceWrapper == null) {
SAtomDataSource sAtomDataSource = new SAtomDataSource();
sAtomDataSource.setGroupName(groupName);
sAtomDataSource.setDsKey(dsKey);
dataSourceWrapper = new DataSourceWrapper();
dataSourceWrapper.setDataSourceKey(dsKey);
dataSourceWrapper.setWeightStr(dbAtomCfg.getModel());
if (!dataSourceWrapper.isNA()) {
dataSourceWrapper.setDataSourceIndex(dbAtomCfg.getDbIndex());
dataSourceWrapper.setWrappedDataSource(sAtomDataSource);
sAtomDataSource.setDbConfigManager(DbConfigManager.this);
sAtomDataSource.setUp();
dataSourceWrapperMap.put(dsKey, dataSourceWrapper);
logger.warn("init dbAtomCfg: {}", dbAtomCfg.toString());
LogUtils.printCdlLog(String.format("init dbAtomCfg: %s", dbAtomCfg.toString()));
}
} else { // 读写变更
dataSourceWrapper.setWeightStr(dbAtomCfg.getModel());
if (dataSourceWrapper.isNA()) { // 此数据源下线
dataSourceWrapperMap.remove(dsKey);
dataSourceWrapper.close();
logger.warn("offline dbAtomCfg: {}", dbAtomCfg.toString());
LogUtils.printCdlLog(String.format("offline dbAtomCfg: %s", dbAtomCfg.toString()));
continue;
} else {
logger.warn("update dbAtomCfg: {}", dbAtomCfg.toString());
LogUtils.printCdlLog(String.format("update dbAtomCfg: %s", dbAtomCfg.toString()));
}
}
if (dataSourceWrapper.hasWriteWeight()) { // 写库
if (dbWSelectorMap.get(groupName) == null) {
DefaultDBSelector defaultDBSelector = new DefaultDBSelector();
defaultDBSelector.setMaster(true);
dbWSelectorMap.put(groupName, defaultDBSelector);
DataSourceHolder holder = new DataSourceHolder(dataSourceWrapper);
dbWSelectorMap.get(groupName).addDataSourceHolder(holder);
} else {
logger.error("write data source cannot more than one : {},{}", appName, groupName);
LogUtils.printCdlLog(String.format("write data source cannot more than one: %s, %s", appName, groupName));
throw new RuntimeException("write data source cannot more than one");
}
}
if (dataSourceWrapper.hasReadWeight()) { // 读库
if (dbRSelectorMap.get(groupName) == null) {
DefaultDBSelector defaultDBSelector = new DefaultDBSelector();
defaultDBSelector.setMaster(false);
dbRSelectorMap.put(groupName, defaultDBSelector);
}
DataSourceHolder holder = new DataSourceHolder(dataSourceWrapper);
dbRSelectorMap.get(groupName).addDataSourceHolder(holder);
}
}
dbGroupInitedMap.put(groupName, true);
}
private void updateDB(List list) throws SQLException {
if (list != null && !list.isEmpty()) {
try {
lock.writeLock().lock();
initDbGroupList(list);
// 更新正在使用的dbgroup
for (String groupName : sGroupDataSourceMap.keySet()) {
initOneDbGroup(groupName);
}
} finally {
lock.writeLock().unlock();
}
}
}
@SuppressWarnings("unchecked")
public List getGroupCfg(String appKey, String appName, ConfigListener listener) throws Exception {
Map cfg = getDBAKey();
if (cfg == null) {
throw new RuntimeException("not found DBA key");
}
int dbaid = Integer.parseInt(cfg.get("dbaid"));
String dbakey = cfg.get("dbakey");
String value = defaultConfigCenterClient.getConfig(dbaid, dbakey, appName, listener);
if (StringUtils.isNotBlank(value)) {
String rawCfg = DESCoder.decrpty(value, appKey);
if (rawCfg != null) {
return JSONObject.parseObject(rawCfg, List.class);
}
}
return null;
}
private Map getDBAKey() {
Map map = new HashMap<>();
map.put("dbaid", String.valueOf(getDbaId(env)));
map.put("dbakey", getDbaKey(env));
return map;
}
@SuppressWarnings("unchecked")
private DbGroupCfg getDbGroupCfgFromJson(JSONObject jSONObject) {
DbGroupCfg dbGroupCfg = new DbGroupCfg();
dbGroupCfg.setGroupIndex(jSONObject.getIntValue("groupIndex"));
dbGroupCfg.setGroupName(jSONObject.getString("groupName"));
dbGroupCfg.setAtomCfgMap(jSONObject.getObject("atomCfgMap", Map.class));
return dbGroupCfg;
}
public void setAppId(String appId) {
this.appId = appId;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public void setAppName(String appName) {
this.appName = appName;
}
public void setEnv(String env) {
this.env = env;
}
public String getEnv() {
return env;
}
public void setOnlyAtom(boolean onlyAtom) {
this.onlyAtom = onlyAtom;
}
public boolean isEnableTrace() {
return enableTrace;
}
public void setEnableTrace(boolean enableTrace) {
this.enableTrace = enableTrace;
}
public static int getDbaId(String env) {
if ("daily".equals(env) || "dev".equals(env)) {
return 26;
}
if ("gray".equals(env) || "online".equals(env)) {
return 11;
}
return -1;
}
public static String getDbaKey(String env) {
if ("daily".equals(env) || "dev".equals(env)) {
return "HBYpa8tr0yA=";
}
if ("gray".equals(env) || "online".equals(env)) {
return "ENYOpK2bQ1s=";
}
return "";
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy