作者简介: 大家好。我是聪明哥,曾任中兴、美团的架构师,现任一家互联网公司的CTO。
联系QQ:184480602,请加我进群,我们一起学习,一起进步,一起抗击互联网的寒冬
想要学习,就必须深入挖掘。挖得越深,地基就越牢固。
第1 阶段:解决多线程的细节
第2 阶段:详细的多线程设计模式
第三阶段.juc源码详细分析
第四阶段.jdk源码其余部分详细分析
阶段5. JVM源码详细分析
代码源码部分
哥码浅谈源码- 源码原理【2024年最新场景:各大厂商使用线程池的问题】
码哥谈源码【炸了!雷!秃头粉丝终于逃脱了! ]
码哥聊源码~【JVM课程必备知识及c/c++调试环境搭建】
马哥谈源码-原理源码篇【阐明join方法的唤醒基本是由jvm底层析构函数决定的】
码哥源码-原理源码篇【Doug Lea为什么要在运算前将成员变量赋值给局部变量?】
码哥谈源码【傻并不坏,但因为你说的是傻话就错了! ]
码哥谈源码【谁说Spring不支持多线程事务?】
B站没有人能清楚解释红黑树的历史。如果您不能接受,请加入我们。
啪啪系列【3小时讲解020-MESI协议与波动性的关系,认为x86验证结果就是最终结果的水货请闭嘴】
4.配置模块
4.2 schema.xml
接上一篇文章,接下来加载每个schema的配置(即MyCat中每个虚拟化数据库的配置)。
XMLSchemaLoader.java
私有无效loadSchemas(元素根){
NodeList 列表=root.getElementsByTagName(\’schema\’);
for (int i=0, n=list.getLength(); i n; i++) {
元素schemaElement=(元素) list.item(i);
//读取各个属性
字符串名称=schemaElement.getAttribute(\’名称\’);
String dataNode=schemaElement.getAttribute(\’dataNode\’);
String checkSQLSchemaStr=schemaElement.getAttribute(\’checkSQLschema\’);
字符串sqlMaxLimitStr=schemaElement.getAttribute(\’sqlMaxLimit\’);
int sqlMaxLimit=-1;
//读取SQL返回结果集的限制
if (sqlMaxLimitStr !=null !sqlMaxLimitStr.isEmpty()) {
sqlMaxLimit=Integer.valueOf(sqlMaxLimitStr);
}
//检查dataNode是否已经存在并检查schema标签是否有datanode
字符串默认DbType=null;
//添加验证检查和dataNode
if (dataNode !=null !dataNode.isEmpty()) {
ListString dataNodeLst=new ArrayListString(1);
dataNodeLst.add(dataNode);
checkDataNodeExists(dataNodeLst);
String dataHost=dataNodes.get(dataNode).getDataHost();
defaultDbType=dataHosts.get(dataHost).getDbType();
} 除此之外{
数据节点=空;
}
//加载schema下的所有表
MapString, TableConfig 表=loadTables(schemaElement);
//判断schema是否重复
if (schemas.containsKey(name)) {
throw new ConfigException(\’架构\’ + 名称+ \’重复!\’);
}
//如果设置了table,则不需要设置dataNode属性。如果未设置表,则必须设置dataNode 属性。
if (dataNode==null table.size()==0) {
抛出一个新的ConfigException()
\’Schema\’+name+\’没有配置表,所以必须设置dataNode属性!\’);
}
SchemaConfig schemaConfig=new SchemaConfig(名称, dataNode,
表, sqlMaxLimit, \’true\’.equalsIgnoreCase(checkSQLSchemaStr));
//设置数据库类型。这对于后续SQL语句的路由分析很有用。
if (defaultDbType !=null) {
schemaConfig.setDefaultDataNodeDbType(defaultDbType);
if (!\’mysql\’.equalsIgnoreCase(defaultDbType)) {
schemaConfig.setNeedSupportMultiDBType(true);
}
}
//判断是否存在非mysql的数据库类型。这样方便解析,判断是否开启多库分页解析。
for (String tableName : table.keySet()) {
TableConfig tableConfig=tables.get(表名);
如果(isHasMultiDbType(tableConfig)){
schemaConfig.setNeedSupportMultiDBType(true);
休息;
}
}
//记录每个dataNode的DB类型
MapString, String dataNodeDbTypeMap=new HashMap();
for (String dataNodeName : dataNodes.keySet()) {
DataNodeConfig dataNodeConfig=dataNodes.get(dataNodeName);
String dataHost=dataNodeConfig.getDataHost();
DataHostConfig dataHostConfig=dataHosts.get(dataHost);
if (dataHostConfig !=null) {
字符串dbType=dataHostConfig.getDbType();
dataNodeDbTypeMap.put(dataNodeName, dbType);
}
}
schemaConfig.setDataNodeDbTypeMap(dataNodeDbTypeMap);
schemas.put(名称,schemaConfig);
}
}
首先,它读取模式中的每个配置属性项并确定其有效性。例如默认的dataNode是否存在。只需检查之前读取的数据节点是否存在即可。
私有无效checkDataNodeExists(CollectionString 节点) {
if (nodes==null ||nodes.size() 1) {
返回;
}
for (字符串节点: 节点) {
if (!dataNodes.containsKey(node)) {
throw new ConfigException(\’dataNode \’\’ + node + \’\’ 未找到!\’);
}
}
}
然后加载所有表和childTable。
私有MapString,TableConfigloadTables(元素节点){
//MapString, TableConfig table=new HashMapString, TableConfig();
//支持表名带引号[`] BEN GONG
MapString, TableConfig 表=new TableConfigMap();
NodeList 节点列表=node.getElementsByTagName(\’table\’);
for (int i=0; i nodeList.getLength(); i++) {
元素tableElement=(element) nodeList.item(i);
String tableNameElement=tableElement.getAttribute(\’name\’).toUpperCase();
//TODO: 添加对路由、动态日期表的支持
String tableNameSuffixElement=tableElement.getAttribute(\’nameSuffix\’).toUpperCase();
if ( !\’\’.equals( tableNameSuffixElement ) ) {
if( tableNameElement.split(\’,\’).length 1 ) {
throw new ConfigException(\’nameSuffix \’ + tableNameSuffixElement + \’, name 参数必需,不允许多次中断!\’);
}
//前缀用于表示日期格式
tableNameElement=doTableNameSuffix(tableNameElement, tableNameSuffixElement);
}
//记录主键,方便后续路由分析,并开启主键自增
String[] tableNames=tableNameElement.split(\’,\’);
字符串PrimaryKey=tableElement.hasAttribute(\’primaryKey\’)? tableElement.getAttribute(\’primaryKey\’).toUpperCase() : null;
//记录主键是否自增。默认不自动递增(启用全局序列处理程序)
布尔自动增量=false;
if (tableElement.hasAttribute(\’autoIncrement\’)) {
autoIncrement=Boolean.parseBoolean(tableElement.getAttribute(\’autoIncrement\’));
}
//记录是否需要对返回的结果集添加限制。应该默认添加。
布尔值needAddLimit=true;
if (tableElement.hasAttribute(\’needAddLimit\’)) {
needAddLimit=Boolean.parseBoolean(tableElement.getAttribute(\’needAddLimit\’));
}
//记录类型,全局或非全局
字符串tableTypeStr=tableElement.hasAttribute(\’type\’) ? tableElement.getAttribute(\’type\’) : null;
int tableType=TableConfig.TYPE_GLOBAL_DEFAULT;
if (\’global\’.equalsIgnoreCase(tableTypeStr)) {
表类型=TableConfig.TYPE_GLOBAL_TABLE;
}
//记录dataNode以及它被分发到哪个dataNode
String dataNode=tableElement.getAttribute(\’dataNode\’);
TableRuleConfig 表规则=null;
if (tableElement.hasAttribute(\’rule\’)) {
String 规则名称=tableElement.getAttribute(\’rule\’);
tableRule=tableRules.get(规则名称);
if (tableRule==null) {
throw new ConfigException(\’规则\’ + 规则名称+ \’ 未找到!\’);
}
}
需要布尔规则=false;
//记录是否有绑定的分片规则
if (tableElement.hasAttribute(\’ruleRequired\’)) {
rulesRequired=Boolean.parseBoolean(tableElement.getAttribute(\’ruleRequired\’));
}
if (表名==null) {
throw new ConfigException(\’未找到表名!\’);
}
//分配函数并重新定位dataNodes
字符串distPrex=\’分布(\’;
布尔distTableDns=dataNode.startsWith(distPlex);
如果(distTableDns){
dataNode=dataNode.substring(distPlex.length(), dataNode.length() – 1);
}
//子表函数
String subTables=tableElement.getAttribute(\’subTables\’);
for (int j=0; j tableNames.length; j++) {
字符串表名=表名[j];
TableConfig 表=new TableConfig(表名, 主键,
自动增量、需要添加限制、表类型、数据节点、
getDbType(数据节点),
(tableRule!=null) tableRule.getRule() : null,
规则必填,null,false,null,null,子表);
checkDataNodeExists(table.getDataNodes());
如果(distTableDns){
distributionDataNodes(table.getDataNodes());
}
//检查是否删除重复项
if (tables.containsKey(table.getName())) {
throw new ConfigException(\’table\’ + tableName + \’重复!\’);
}
//放入地图
table.put(table.getName(), 表);
}
//子表只有在tableName由单个表组成时才能存在(没有逗号)
if (tableNames.length==1) {
TableConfig 表=tables.get(tableNames[0]);
//处理子表
processChildTables(表,表,数据节点,表元素);
}
}
返回表。
}
对于子表,有一个递归读取配置。
私有无效processChildTables(MapString,TableConfig 表,
TableConfigparentTable, 字符串dataNodes, 元素tableNode) {
//解析子表
NodeList childNodeList=tableNode.getChildNodes();
for (int j=0; j childNodeList.getLength(); j++) {
节点theNode=childNodeList.item(j);
if (!theNode.getNodeName().equals(\’childTable\’)) {
继续;
}
元素childTbElement=(元素) theNode;
//读取子表信息
String cdTbName=childTbElement.getAttribute(\’name\’).toUpperCase();
字符串PrimaryKey=childTbElement.hasAttribute(\’primaryKey\’)
布尔自动增量=false;
if (childTbElement.hasAttribute(\’autoIncrement\’)) {
autoIncrement=Boolean.parseBoolean(childTbElement.getAttribute(\’autoIncrement\’));
}
布尔值needAddLimit=true;
if (childTbElement.hasAttribute(\’needAddLimit\’)) {
needAddLimit=Boolean.parseBoolean(childTbElement.getAttribute(\’needAddLimit\’));
}
String subTables=childTbElement.getAttribute(\’subTables\’);
//子表的Join键和对应的父键,父表和子表通过这个关联起来
String joinKey=childTbElement.getAttribute(\’joinKey\’).toUpperCase();
StringparentKey=childTbElement.getAttribute(\’parentKey\’).toUpperCase();
TableConfig 表=new TableConfig(cdTbName, PrimaryKey,
自动增量,需要添加限制,
TableConfig.TYPE_GLOBAL_DEFAULT,数据节点,
getDbType(dataNodes)、null、false、parentTable、true、
joinKey、parentKey、子表);
if (tables.containsKey(table.getName())) {
throw new ConfigException(\’table \’ + table.getName() + \’重复!\’);
}
table.put(table.getName(), 表);
//对于子表的子表,递归处理
processChildTables(表、表、数据节点、childTbElement);
}
}
对于表dataNode 支持,有一个类似于dataNode=\”distributed(dn$1-10)\” 的特殊设置。这意味着:
/**
* 将数据节点分布在多个主机上,即dn1(host1)、dn100
*(主机2)、dn300(主机3)、dn2(主机1)、dn101(主机2)、dn301(主机3).等。
* 根据主机的不同,重新定位每个主机上的数据节点。例如,在上面的例子中,host1拥有dn1、dn2,host2拥有dn100、dn101,host3拥有dn300、dn301,
* 按主机排序:0-dn1(主机1)、1-dn100(主机2)、2-dn300(主机3)、3-dn2(主机1)、4-dn101(主机2)、5-dn301(主机3)
*
* @param 数据节点
*/
私有无效distributionDataNodes(ArrayListString theDataNodes){
MapString, ArrayListString newDataNodeMap=new HashMapString, ArrayListString(dataHosts.size());
for (String dn : theDataNodes) {
DataNodeConfig dnConf=dataNodes.get(dn);
字符串主机=dnConf.getDataHost();
ArrayListString hostDns=newDataNodeMap.get(host);
hostDns=(hostDns==null) ? new ArrayListString() : hostDns;
hostDns.add(dn);
newDataNodeMap.put(主机,hostDns);
}
ArrayListString 结果=new ArrayListString(theDataNodes.size());
布尔值hasData=true;
while(有数据){
有数据=false;
for (ArrayListString dns : newDataNodeMap.values()) {
if (!dns.isEmpty()) {
结果.add(dns.remove(0));
有数据=true;
}
}
}
theDataNodes.clear();
theDataNodes.addAll(结果);
}
读取所有表后,记录DB类型。这对于后续SQL语句的路由分析很有用。将所有模式配置保存到:
私有最终MapString,SchemaConfig架构。
4.3 server.xml
然后读取并加载服务器配置。
XMLConfigLoader.java:
公共XMLConfigLoader(SchemaLoader schemaLoader) {
XMLServerLoaderserverLoader=new XMLServerLoader();
this.system=serverLoader.getSystem();
this.users=serverLoader.getUsers();
this.quarantine=serverLoader.getQuarantine();
this.cluster=serverLoader.getCluster();
this.dataHosts=schemaLoader.getDataHosts();
this.dataNodes=schemaLoader.getDataNodes();
this.schemas=schemaLoader.getSchemas();
模式加载器=null;
}
XMLServerLoader.java
公共XMLServerLoader() {
this.system=new SystemConfig();
this.users=new HashMapString, UserConfig();
this.quarantine=new QuarantineConfig();
this.load();
}
私有无效负载(){
//读取server.xml配置
输入流dtd=null;
输入流XML=null;
尝试{
dtd=XMLServerLoader.class.getResourceAsStream(\’/server.dtd\’);
xml=XMLServerLoader.class.getResourceAsStream(\’/server.xml\’);
元素根=ConfigUtil.getDocument(dtd, xml).getDocumentElement();
//加载系统标签
加载系统(根);
//加载用户标签
加载用户(root);
//加载集群配置
this.cluster=new ClusterConfig(root, system.getServerPort());
//加载权限和黑白名单
负载隔离(根);
} catch (ConfigException e) {
扔e。
} catch (异常e) {
抛出新的ConfigException(e)。
} 最后{
如果(dtd!=null){
尝试{
dtd.close();
} catch(IOException e) {
}
}
如果(xml!=null){
尝试{
xml.close();
} catch(IOException e) {
}
}
}
}
以上关于#MyCat的相关内容摘自网络,仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/91416.html