All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.javaclub.cdl.client.config.DbConfigManager Maven / Gradle / Ivy

There is a newer version: 2.3.9
Show newest version
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