MyCat源码分析系列之——配置信息和启动流程
更多MyCat源码分析,请戳MyCat源码分析系列
MyCat配置信息
除了一些默认的配置参数,大多数的MyCat配置信息是通过读取若干.xml/.properties文件获取的,主要包括:
1)server.xml:系统和用户相关配置
2)schema.xml:虚拟库、表、数据节点配置等
3)rule.xml:分片规则设置
4)cacheservice.properties:缓存相关设置
5)dnindex.properties:datahost主从切换配置文件
6)sequence_conf.properties:本地全局序列号配置文件
而在代码层面,与配置相关的类主要包括3个:
1)MycatConfig:最为重要的配置类
2)ReloadConfig:用于通过管理端口执行mysql> reload @@config或config_all命令,重新载入配置文件
3)RollbackConfig:用于通过管理端口执行mysql> rollback @@config命令,将配置信息回滚至reload之前的状态
接下来重点介绍MycatConfig,它最关键的属性如下:
private volatile SystemConfig system;
private volatile MycatCluster cluster;
private volatile MycatCluster _cluster;
private volatile QuarantineConfig quarantine;
private volatile QuarantineConfig _quarantine;
private volatile Map<String, UserConfig> users;
private volatile Map<String, UserConfig> _users;
private volatile Map<String, SchemaConfig> schemas;
private volatile Map<String, SchemaConfig> _schemas;
private volatile Map<String, PhysicalDBNode> dataNodes;
private volatile Map<String, PhysicalDBNode> _dataNodes;
private volatile Map<String, PhysicalDBPool> dataHosts;
private volatile Map<String, PhysicalDBPool> _dataHosts;
- SystemConfig:包含了诸多系统相关的配置参数(如端口、编码、线程池大小、BufferPool大小、隔离级别等)
- MycatCluster:MyCat集群配置信息
- QuarantineConfig:用户权限隔离(黑白名单)
- UserConfig:用户配置,包含用户名/密码和允许访问的虚拟库
- SchemaConfig:虚拟库配置,包括所有下属的表配置(
TableConfig
)以及这些表涉及的datanode
- PhysicalDBNode:datanode相关,对应一个数据库实例中的数据库
- PhysicalDBPool:datahost相关,里面包含了DataHostConfig配置,包括所有writeHosts和readHosts以及读写分离类型等
注意到除了SystemConfig,其余属性都还有一个前缀加了_的同名属性,这些属性其实是作为备份的,用于reload/rollback配置文件时的切换。reload和rollback相关的方法如下:
public void reload(Map<String, UserConfig> users,
Map<String, SchemaConfig> schemas,
Map<String, PhysicalDBNode> dataNodes,
Map<String, PhysicalDBPool> dataHosts, MycatCluster cluster,
QuarantineConfig quarantine,boolean reloadAll) {
apply(users, schemas, dataNodes, dataHosts, cluster, quarantine,reloadAll);
this.reloadTime = TimeUtil.currentTimeMillis();
this.status = reloadAll?RELOAD_ALL:RELOAD;
}
public void rollback(Map<String, UserConfig> users,
Map<String, SchemaConfig> schemas,
Map<String, PhysicalDBNode> dataNodes,
Map<String, PhysicalDBPool> dataHosts, MycatCluster cluster,
QuarantineConfig quarantine) {
apply(users, schemas, dataNodes, dataHosts, cluster, quarantine,status==RELOAD_ALL);
this.rollbackTime = TimeUtil.currentTimeMillis();
this.status = ROLLBACK;
}
在reload的时候注意到有reload和reload_all,区别就在于前者不会重新加载与datahost/datanode相关的更改,而后者会。
启动流程
MyCat的启动类为MycatStartup,而主体为MycatServer,其中主要分为两个步骤:
1)初始化:此过程在MycatServer构造函数时执行,包括配置文件的读取、CacheService和RouteService的创建等
public MycatServer() {
this.config = new MycatConfig();
this.timer = new Timer(NAME + "Timer", true);
this.sqlRecorder = new SQLRecorder(config.getSystem()
.getSqlRecordCount());
this.isOnline = new AtomicBoolean(true);
cacheService = new CacheService();
routerService = new RouteService(cacheService);
// load datanode active index from properties
dnIndexProperties = loadDnIndexProps();
try {
sqlInterceptor = (SQLInterceptor) Class.forName(
config.getSystem().getSqlInterceptor()).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
catletClassLoader = new DynaClassLoader(SystemConfig.getHomePath()
+ File.separator + "catlet", config.getSystem()
.getCatletClassCheckSeconds());
this.startupTime = TimeUtil.currentTimeMillis();
}
2)运行:此过程由startup()方法触发,包括处理器对象创建、bufferpool创建、处理线程池创建、AIOConnector/NIOConnector创建与启动、两个AIOAcceptor/NIOAcceptor创建与启动、后端数据库的初始连接建立、定时器线程池/定时任务创建与启动
public void startup() throws IOException {
SystemConfig system = config.getSystem();
int processorCount = system.getProcessors();
// server startup
LOGGER.info("===============================================");
LOGGER.info(NAME + " is ready to startup ...");
String inf = "Startup processors ...,total processors:"
+ system.getProcessors() + ",aio thread pool size:"
+ system.getProcessorExecutor()
+ " \r\n each process allocated socket buffer pool "
+ " bytes ,buffer chunk size:"
+ system.getProcessorBufferChunk()
+ " buffer pool's capacity(buferPool/bufferChunk) is:"
+ system.getProcessorBufferPool()
/ system.getProcessorBufferChunk();
LOGGER.info(inf);
LOGGER.info("sysconfig params:" + system.toString());
// startup manager
ManagerConnectionFactory mf = new ManagerConnectionFactory();
ServerConnectionFactory sf = new ServerConnectionFactory();
SocketAcceptor manager = null;
SocketAcceptor server = null;
aio = (system.getUsingAIO() == 1);
// startup processors
int threadPoolSize = system.getProcessorExecutor();
processors = new NIOProcessor[processorCount];
long processBuferPool = system.getProcessorBufferPool();
int processBufferChunk = system.getProcessorBufferChunk();
int socketBufferLocalPercent = system.getProcessorBufferLocalPercent();
bufferPool = new BufferPool(processBuferPool, processBufferChunk,
socketBufferLocalPercent / processorCount);
businessExecutor = ExecutorUtil.create("BusinessExecutor",
threadPoolSize);
timerExecutor = ExecutorUtil.create("Timer", system.getTimerExecutor());
listeningExecutorService = MoreExecutors.listeningDecorator(businessExecutor);
for (int i = 0; i < processors.length; i++) {
processors[i] = new NIOProcessor("Processor" + i, bufferPool,
businessExecutor);
}
if (aio) {
LOGGER.info("using aio network handler ");
asyncChannelGroups = new AsynchronousChannelGroup[processorCount];
// startup connector
connector = new AIOConnector();
for (int i = 0; i < processors.length; i++) {
asyncChannelGroups[i] = AsynchronousChannelGroup
.withFixedThreadPool(processorCount,
new ThreadFactory() {
private int inx = 1;
@Override
public Thread newThread(Runnable r) {
Thread th = new Thread(r);
th.setName(BufferPool.LOCAL_BUF_THREAD_PREX
+ "AIO" + (inx++));
LOGGER.info("created new AIO thread "
+ th.getName());
return th;
}
});
}
manager = new AIOAcceptor(NAME + "Manager", system.getBindIp(),
system.getManagerPort(), mf, this.asyncChannelGroups[0]);
// startup server
server = new AIOAcceptor(NAME + "Server", system.getBindIp(),
system.getServerPort(), sf, this.asyncChannelGroups[0]);
} else {
LOGGER.info("using nio network handler ");
NIOReactorPool reactorPool = new NIOReactorPool(
BufferPool.LOCAL_BUF_THREAD_PREX + "NIOREACTOR",
processors.length);
connector = new NIOConnector(BufferPool.LOCAL_BUF_THREAD_PREX
+ "NIOConnector", reactorPool);
((NIOConnector) connector).start();
manager = new NIOAcceptor(BufferPool.LOCAL_BUF_THREAD_PREX + NAME
+ "Manager", system.getBindIp(), system.getManagerPort(),
mf, reactorPool);
server = new NIOAcceptor(BufferPool.LOCAL_BUF_THREAD_PREX + NAME
+ "Server", system.getBindIp(), system.getServerPort(), sf,
reactorPool);
}
// manager start
manager.start();
LOGGER.info(manager.getName() + " is started and listening on "
+ manager.getPort());
server.start();
// server started
LOGGER.info(server.getName() + " is started and listening on "
+ server.getPort());
LOGGER.info("===============================================");
// init datahost
Map<String, PhysicalDBPool> dataHosts = config.getDataHosts();
LOGGER.info("Initialize dataHost ...");
for (PhysicalDBPool node : dataHosts.values()) {
String index = dnIndexProperties.getProperty(node.getHostName(),
"0");
if (!"0".equals(index)) {
LOGGER.info("init datahost: " + node.getHostName()
+ " to use datasource index:" + index);
}
node.init(Integer.valueOf(index));
node.startHeartbeat();
}
long dataNodeIldeCheckPeriod = system.getDataNodeIdleCheckPeriod();
timer.schedule(updateTime(), 0L, TIME_UPDATE_PERIOD);
timer.schedule(processorCheck(), 0L, system.getProcessorCheckPeriod());
timer.schedule(dataNodeConHeartBeatCheck(dataNodeIldeCheckPeriod), 0L,
dataNodeIldeCheckPeriod);
timer.schedule(dataNodeHeartbeat(), 0L,
system.getDataNodeHeartbeatPeriod());
timer.schedule(catletClassClear(), 30000);
}
从以上代码中不难看出,connector用于作为客户端与后端MySQL建立连接,而server和manager则作为服务端接受来自前端应用的连接请求,其中server负责常规业务流程(默认端口8066),而manager负责监控与管理(默认端口9066)。
而datahost的初始化行为由node.init(Integer.valueOf(index));触发,其目的是每个datahost中writehost会连续创建若干初始连接供使用(该数量由schema.xml中datahost标签的minCon属性确定),当后续连接不足时会创建新的连接(最大不超过maxCon)。
由此,MyCat程序启动完成,等待接受来自应用的连接请求和后续的命令处理。
为尊重原创成果,如需转载烦请注明本文出处:http://www.cnblogs.com/fernandolee24/p/5193983.html,特此感谢
MyCat源码分析系列之——配置信息和启动流程的更多相关文章
- 开源分布式数据库中间件MyCat源码分析系列
MyCat是当下很火的开源分布式数据库中间件,特意花费了一些精力研究其实现方式与内部机制,在此针对某些较为重要的源码进行粗浅的分析,希望与感兴趣的朋友交流探讨. 本源码分析系列主要针对代码实现,配置. ...
- MyCat源码分析系列之——结果合并
更多MyCat源码分析,请戳MyCat源码分析系列 结果合并 在SQL下发流程和前后端验证流程中介绍过,通过用户验证的后端连接绑定的NIOHandler是MySQLConnectionHandler实 ...
- MyCat源码分析系列之——BufferPool与缓存机制
更多MyCat源码分析,请戳MyCat源码分析系列 BufferPool MyCat的缓冲区采用的是java.nio.ByteBuffer,由BufferPool类统一管理,相关的设置在SystemC ...
- MyCat源码分析系列之——SQL下发
更多MyCat源码分析,请戳MyCat源码分析系列 SQL下发 SQL下发指的是MyCat将解析并改造完成的SQL语句依次发送至相应的MySQL节点(datanode)的过程,该执行过程由NonBlo ...
- MyCat源码分析系列之——前后端验证
更多MyCat源码分析,请戳MyCat源码分析系列 MyCat前端验证 MyCat的前端验证指的是应用连接MyCat时进行的用户验证过程,如使用MySQL客户端时,$ mysql -uroot -pr ...
- [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat
概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...
- Thinkphp源码分析系列–开篇
目前国内比较流行的php框架由thinkphp,yii,Zend Framework,CodeIgniter等.一直觉得自己在php方面还是一个小学生,只会用别人的框架,自己也没有写过,当然不是自己不 ...
- MyBatis 源码分析系列文章导读
1.本文速览 本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章.本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(how)等三个角度进行了说 ...
- spring源码分析系列 (5) spring BeanFactoryPostProcessor拓展类PropertyPlaceholderConfigurer、PropertySourcesPlaceholderConfigurer解析
更多文章点击--spring源码分析系列 主要分析内容: 1.拓展类简述: 拓展类使用demo和自定义替换符号 2.继承图UML解析和源码分析 (源码基于spring 5.1.3.RELEASE分析) ...
随机推荐
- category中重写方法?
问:可以在category中重写方法吗? 答:代码上可以实现 在category中重写方法,但在实际开发中,不建议这样做.如果确实需要重写原有方法也建议使用子类进行重写. category是为了更方便 ...
- 转:serialVersionUID作用
汗,以前学了还忘了... Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本 ...
- 【开源】分享2011-2015年全国城市历史天气数据库【Sqlite+C#访问程序】
由于个人研究需要,需要采集天气历史数据,前一篇文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子),介绍了基本的采集思路和核心代码,经过1个星期的采集,历史数据库 ...
- MAVEN学习-第一个Maven项目的构建
MAVEN安装成功之后就可以进行项目的构建和管理了: 为什么要用maven进行项目的构建和管理? 对于初学者来说一个最直接的也是最容易里的优点在于JAR包的管理,相对于以前开发一个项目的时候我们需要用 ...
- Smarty的基本使用与总结
含义: Smarty是PHP的一个引擎模板,可以更好的进行逻辑与显示的分离,即我们常说的MVC,这个引擎的作用就是将C分离出来. 环境需求:PHP5.2或者更高版本 我使用的环境是:PHP5.3,wi ...
- zookeeper源码分析之一服务端启动过程
zookeeper简介 zookeeper是为分布式应用提供分布式协作服务的开源软件.它提供了一组简单的原子操作,分布式应用可以基于这些原子操作来实现更高层次的同步服务,配置维护,组管理和命名.zoo ...
- OEL上使用yum install oracle-validated 简化主机配置工作
环境:OEL 5.7 + Oracle 10.2.0.5 RAC 如果你正在用OEL(Oracle Enterprise Linux)系统部署Oracle,那么可以使用yum安装oracle-vali ...
- 免费高效实用的.NET操作Excel组件NPOI(.NET组件介绍之六)
很多的软件项目几乎都包含着对文档的操作,前面已经介绍过两款操作文档的组件,现在介绍一款文档操作的组件NPOI. NPOI可以生成没有安装在您的服务器上的Microsoft Office套件的Excel ...
- C#~异步编程再续~await与async引起的w3wp.exe崩溃-问题友好的解决
返回目录 关于死锁的原因 理解该死锁的原因在于理解await 处理contexts的方式,默认的,当一个未完成的Task 被await的时候,当前的上下文将在该Task完成的时候重新获得并继续执行剩余 ...
- ORACLE分区表梳理系列(二)- 分区表日常维护及注意事项(红字需要留意)
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...