本篇將根據(jù)啟動類MycatStartup.java來概覽MyCAT的啟動流程讥裤。
為了簡明清晰姻报,所有源碼只列出關(guān)鍵代碼加以說明,只做NIO網(wǎng)絡(luò)框架的相關(guān)分析吴旋。
Mycat的主要啟動流程在單例MycatServer.java中,我們先看下構(gòu)造方法治拿。
private MycatServer() {
//讀取文件配置
this.config = new MycatConfig();
//緩存服務(wù)初始化
cacheService = new CacheService();
//路由計算初始化
routerService = new RouteService(cacheService);
//SQL解析器
sqlInterceptor = (SQLInterceptor) Class.forName(
config.getSystem().getSqlInterceptor()).newInstance();
}
主要邏輯說明:
1褂傀、讀取配置文件。
即schema.xml仙辟、server.xml、rule.xml未檩。mycat支持兩種配置粟焊,zk或者本地文件,方式配置項在myid.properties文件中的loadZk=false or true项棠。基于zk的配置方式會從zk將約定路徑上的配置內(nèi)容讀取到本地文件合瓢,在此行代碼解析到MycatConfig.java類中透典。
2、緩存和路由計算初始化峭咒。
緩存的配置信息在cacheservice.properties,默認(rèn)實現(xiàn)為factory.encache=io.mycat.cache.impl.EnchachePooFactory则果。支持可配各個場景的緩存實現(xiàn),緩存空間的大小西壮,以及緩存的超時時間。例:
pool.SQLRouteCache=encache,10000,1800
layedpool.TableID2DataNodeCache=encache,10000,18000
配置了RouteService的本地緩存池贡定。
備注:
SQLRouteCache的緩存key為 schema+SQL語句可都,value為 RouteResultset路由信息
TableID2DataNodeCache的緩存key為 id 的值,value為 節(jié)點名
接下來我們分析MycatServer.startup()方法渠牲,該方法中完成了Mycat網(wǎng)絡(luò)通信框架中前端、后端通信的關(guān)鍵組件的初始化签杈。
public void startup() throws IOException {
//創(chuàng)建對SocketChannel進(jìn)行封裝的工廠類
ServerConnectionFactory sf = new ServerConnectionFactory();
//創(chuàng)建緩存塊pool,支持可配答姥,默認(rèn)使用直接內(nèi)存
bufferPool = new DirectByteBufferPool(bufferPoolPageSize,bufferPoolChunkSize,
bufferPoolPageNumber,system.getFrontSocketSoRcvbuf());
//創(chuàng)建業(yè)務(wù)線程池和異步處理器
processors = new NIOProcessor[processorCount];
//業(yè)務(wù)線程池的大小可以適當(dāng)小一些,Mycat主要處理流程都是在reactor線程組中完成的
businessExecutor = ExecutorUtil.create("BusinessExecutor",
threadPoolSize);
for (int i = 0; i < processors.length; i++) {
processors[i] = new NIOProcessor("Processor" + i, bufferPool,
businessExecutor);
}
//創(chuàng)建NIOReactorPool, 默認(rèn)大小為機(jī)器cpu核心線程數(shù)
NIOReactorPool reactorPool = new NIOReactorPool(
DirectByteBufferPool.LOCAL_BUF_THREAD_PREX + "NIOREACTOR",
processors.length);
//創(chuàng)建NIOConnector
connector = new NIOConnector(DirectByteBufferPool.LOCAL_BUF_THREAD_PREX + "NIOConnector", reactorPool);
((NIOConnector) connector).start();
//創(chuàng)建并啟動NIOAcceptor
server = new NIOAcceptor(DirectByteBufferPool.LOCAL_BUF_THREAD_PREX + NAME
+ "Server", system.getBindIp(), system.getServerPort(), sf, reactorPool);
server.start();
//初始化數(shù)據(jù)庫連接尚粘,調(diào)度心跳監(jiān)聽任務(wù)
Map<String, PhysicalDBPool> dataHosts = config.getDataHosts();
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.parseInt(index));
node.startHeartbeat();
}
scheduler.scheduleAtFixedRate(dataNodeHeartbeat(), 0L, system.getDataNodeHeartbeatPeriod(),TimeUnit.MILLISECONDS);
}
主要邏輯說明:
1敲长、ServerConnectionFactory
封裝SocketChannel為ServerConnection, 設(shè)置數(shù)據(jù)包handler處理器,創(chuàng)建當(dāng)前連接的NonBlockingSession
2祈噪、DirectByteBufferPool
預(yù)創(chuàng)建緩存塊pool
3、NIOReactorPool-線程組
NIOReactor線程組盔腔,用來監(jiān)聽并處理前端和后端的SelectionKey.OP_READ讀事件遂填,可以看到NIOConnector和NIOAcceptor都持有了reactorPool澈蝙,創(chuàng)建連接后都交給reactorPool去處理。
4灯荧、NIOConnector-單線程
創(chuàng)建數(shù)據(jù)庫連接,監(jiān)聽并處理SelectionKey.OP_CONNECT事件
5、NIOAcceptor-單線程
接收客戶端(也就是業(yè)務(wù)服務(wù))連接請求哆窿,監(jiān)聽并處理SelectionKey.OP_ACCEPT事件
本篇分析到此結(jié)束。
轉(zhuǎn)載請備注原文鏈接挚躯。