请先按下面这个说明 把mycat处理起来,
http://blog.csdn.net/mingover/article/details/78846853
下载源码,
覆盖下面三个文件
Mycat-Server\src\main\resources\server.xml
Mycat-Server\src\main\resources\rules.xml
Mycat-Server\src\main\resources\schema.xml
启动进程
MycatStartup.java
从mysql客户端登陆 mycat服务器
说明在断点的时候,会有几条请求,如 show states;要认准sql那次
ServerConnection.routeEndExecuteSQL中设置断点,我们可以看到线程内容如下图
$_NIOREACTOR-2-RW@2373" prio=5 tid=0x16 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at io.mycat.server.ServerConnection.routeEndExecuteSQL(ServerConnection.java:275)
at io.mycat.server.ServerConnection.execute(ServerConnection.java:226)
at io.mycat.server.handler.SelectHandler.handle(SelectHandler.java:105)
at io.mycat.server.ServerQueryHandler.query(ServerQueryHandler.java:79)
at io.mycat.net.FrontendConnection.query(FrontendConnection.java:324)
at io.mycat.net.FrontendConnection.query(FrontendConnection.java:344)
at io.mycat.net.handler.FrontendCommandHandler.handle(FrontendCommandHandler.java:71)
at io.mycat.net.FrontendConnection.rawHandle(FrontendConnection.java:500)
at io.mycat.net.FrontendConnection.handle(FrontendConnection.java:482)
at io.mycat.net.AbstractConnection.onReadData(AbstractConnection.java:327)
at io.mycat.net.NIOSocketWR.asynRead(NIOSocketWR.java:196)
at io.mycat.net.AbstractConnection.asynRead(AbstractConnection.java:279)
at io.mycat.net.NIOReactor$RW.run(NIOReactor.java:113)
at java.lang.Thread.run(Thread.java:744)
既然是分表,在查询的时候,自然 是把sql拆出来到多个节点中查询,通过代码,我们发现下面这几个关键类
ServerConnection.routeEndExecuteSQL -> RouteService.route
以下为获取rrs的内容
/**
* 检查是否有分片
*/
if (schema.isNoSharding() && ServerParse.SHOW != sqlType) {
rrs = RouterUtil.routeToSingleNode(rrs, schema.getDataNode(), stmt);
} else {
RouteResultset returnedSet = routeSystemInfo(schema, sqlType, stmt, rrs);
if (returnedSet == null) {
rrs = routeNormalSqlWithAST(schema, stmt, rrs, charset, cachePool,sqlType,sc);
}
}
如上图所示 DruidMycatRouteStrategy.routeSystemInfot得到了rrs对象,这个对象是包含了多个节点的sql,其内存内容如下图所示
可以看到,路由中对应两个库,
源sql是 limit 10635,10
对应于两个库 是 limit 0,10645,可以猜想 其是要从两个库中查出这么多数据,然后进行排序取10条数据返回到客户端
在日志里也能看到情况:
2018-04-10 21:48:46,068 [WARN ][$_NIOREACTOR-5-RW] ServerConnection [id=1, schema=TESTDB, host=127.0.0.1, user=root,txIsolation=3, autocommit=true, schema=TESTDB]SELECT * from t_gd_user_copy t limit 10635,10, route={
1 -> tx_pay{SELECT *
FROM t_gd_user_copy t
LIMIT 0, 10645}
2 -> tx_pay2{SELECT *
FROM t_gd_user_copy t
LIMIT 0, 10645}
如下图,先是得到路由rrs ,而且里面已经有了notes 描述,对每个节点的sql也OK了
public void routeEndExecuteSQL(String sql, final int type, final SchemaConfig schema) {
// 路由计算
RouteResultset rrs = null;
try {
rrs = MycatServer
.getInstance()
.getRouterservice()
.route(MycatServer.getInstance().getConfig().getSystem(),
schema, type, sql, this.charset, this);
} catch (Exception e) {
...
}
if (rrs != null) {
// session执行
session.execute(rrs, rrs.isSelectForUpdate()?ServerParse.UPDATE:type);
}
}
确认路由后,则需要具体去查询 节点的mysql了.
涉及到connection等,
涉及类:PhysicalDBNode.getConnection -> PhysicalDatasource.PhysicalDatasource
处理好conn后 MultiNodeQueryHandler.connectionAcquired 去具体执行sql,发下为关键内容:
private void _execute(BackendConnection conn, RouteResultsetNode node) {
if (clearIfSessionClosed(session)) {
return;
}
conn.setResponseHandler(this);
try {
conn.execute(node, session.getSource(), autocommit);
} catch (IOException e) {
connectionError(e, conn);
}
}
如果在conn.execute中继续往 里走,发现 mycat使用的是nio方式,所以,这里不会有返回,返回及其相关内容在 回调函数中处理,
mycat 请求mysql使用nio方式,则自然不会在发送的线程中处理返回结果。但逻辑还是在handler中
如果是两台机的sql,则两台机发送完sql到mysql后,才会走到nio的resp中处理
MultiNodeQueryHandler 类的以下方法
/**
* 将汇聚结果集数据真正的发送给Mycat客户端
* @param source
* @param eof
* @param
*/
public void outputMergeResult(final ServerConnection source, final byte[] eof, Iterator iter,AtomicBoolean isMiddleResultDone) {
...
}
采用nio的话,发出和发送就是不同的线程,
如图所示 MultiNodeQueryHandler 处理类中 会把内容write出去,即发送到客户端
上面这个函数是 multiQueryHandler.outputMergeResult .
在这之前,还是有sort之类的逻辑
如果你对java的nio编程有了解,可以去从入口中往里走
NIOReactor.run()
@Override
public void run() {
int invalidSelectCount = 0;
Set keys = null;
for (;;) {
++reactCount;
try {
final Selector tSelector = this.selector;
long start = System.nanoTime();
tSelector.select(500L);
long end = System.nanoTime();
register(tSelector);
keys = tSelector.selectedKeys();
.....