数据库路由中间件MyCat - 源代码篇(10)
此文已由作者张镐薪授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
3. 连接模块
3.5 后端连接
3.5.2 后端连接获取与维护管理
还是那之前的流程,
st=>start: MyCat接受客户端连接并为之建立唯一绑定的Session
e=>end: 将请求发送给对应连接,处理完之后归还连接
op1=>operation: MyCat接受客户端的请求,计算路由
op2=>operation: 根据请求和路由创建合适的handler,这里为SingleNodeHandler
op3=>operation: 从PhysicalDBNode中获取后端连接
cond=>condition: 尝试获取连接,连接够用?
op4=>operation: 尝试异步创建新的连接
op5=>operation: 通过DelegateResponseHandler将连接与之前的Handler,这里是SingleNodeHandler绑定
st->op1->op2->op3->condcond(yes)->econd(no)->op4->op5->e
现在我们到了尝试获取连接的阶段 PhysicalDataSource.java:
public void getConnection(String schema,boolean autocommit, final ResponseHandler handler, final Object attachment) throws IOException {//从当前连接map中拿取已建立好的后端连接
BackendConnection con = this.conMap.tryTakeCon(schema,autocommit); if (con != null) {//如果不为空,则绑定对应前端请求的handler
takeCon(con, handler, attachment, schema); return;
} else {//如果为空,新建连接
int activeCons = this.getActiveCount();//当前最大活动连接
if(activeCons+1>size){//下一个连接大于最大连接数
LOGGER.error("the max activeConnnections size can not be max than maxconnections"); throw new IOException("the max activeConnnections size can not be max than maxconnections");
}else{ // create connection
LOGGER.info("not ilde connection in pool,create new connection for " + this.name
+ " of schema "+schema);
createNewConnection(handler, attachment, schema);
}
}
}
private void createNewConnection(final ResponseHandler handler, final Object attachment, final String schema) throws IOException { //异步创建连接,将连接的handler绑定为DelegateResponseHandler
MycatServer.getInstance().getBusinessExecutor().execute(new Runnable() { public void run() { try {
createNewConnection(new DelegateResponseHandler(handler) { @Override
public void connectionError(Throwable e,
BackendConnection conn) {
handler.connectionError(e, conn);
} @Override
public void connectionAcquired(BackendConnection conn) {
takeCon(conn, handler, attachment, schema);
}
}, schema);
} catch (IOException e) {
handler.connectionError(e, null);
}
}
});
}
异步调用工厂方法创建后端连接,这里为MySQLConnection MySQLDataSource.java:
@Override
public void createNewConnection(ResponseHandler handler,String schema) throws IOException {
factory.make(this, handler,schema);
}
根据之前所述,MySQLConnection的工厂方法会先将NIOhandler设置为MySQLConnectionAuthenticator: MySQLConnectionFactory.java:
public MySQLConnection make(MySQLDataSource pool, ResponseHandler handler,
String schema) throws IOException { //DBHost配置
DBHostConfig dsc = pool.getConfig(); //根据是否为NIO返回SocketChannel或者AIO的AsynchronousSocketChannel
NetworkChannel channel = openSocketChannel(MycatServer.getInstance()
.isAIO()); //新建MySQLConnection
MySQLConnection c = new MySQLConnection(channel, pool.isReadNode()); //根据配置初始化MySQLConnection
MycatServer.getInstance().getConfig().setSocketParams(c, false);
c.setHost(dsc.getIp());
c.setPort(dsc.getPort());
c.setUser(dsc.getUser());
c.setPassword(dsc.getPassword());
c.setSchema(schema); //目前实际连接还未建立,handler为MySQL连接认证MySQLConnectionAuthenticator,传入的handler为后端连接处理器ResponseHandler
c.setHandler(new MySQLConnectionAuthenticator(c, handler));
c.setPool(pool);
c.setIdleTimeout(pool.getConfig().getIdleTimeout()); //AIO和NIO连接方式建立实际的MySQL连接
if (channel instanceof AsynchronousSocketChannel) {
((AsynchronousSocketChannel) channel).connect( new InetSocketAddress(dsc.getIp(), dsc.getPort()), c,
(CompletionHandler) MycatServer.getInstance()
.getConnector());
} else { //通过NIOConnector建立连接
((NIOConnector) MycatServer.getInstance().getConnector())
.postConnect(c); } return c;
}
这里传入的ResponseHandler为DelegateResponseHandler,在连接建立验证之后,会调用: MySQLConnectionAuthenticator.java:
public void handle(byte[] data) { //省略
//设置ResponseHandler
if (listener != null) {
listener.connectionAcquired(source);
} //省略}
DelegateResponseHandler.java:
private final ResponseHandler target;@Override
public void connectionAcquired(BackendConnection conn) { //将后端连接的ResponseHandler设置为target
target.connectionAcquired(conn);
}
这样,原来没获取到连接的ResponseHandler就获得需要的连接,之后进行处理。处理完后,归还到连接池中。
private void returnCon(BackendConnection c) { //清空连接的Attachment
c.setAttachment(null); //设置为未使用
c.setBorrowed(false); //更新上次使用时间,用于清理空闲连接
c.setLastTime(TimeUtil.currentTimeMillis()); //获取连接池对应的队列
ConQueue queue = this.conMap.getSchemaConQueue(c.getSchema()); //按照是否Autocommit分类归还连接
boolean ok = false; if (c.isAutocommit()) {
ok = queue.getAutoCommitCons().offer(c);
} else {
ok = queue.getManCommitCons().offer(c);
} //归还失败,关闭连接,记录
if (!ok) {
LOGGER.warn("can't return to pool ,so close con " + c);
c.close("can't return to pool ");
}
}
4.配置模块
MyCat实例初始化时究竟会有什么操作呢?看下MyCat程序入口: MycatStartup.java:
public static void main(String[] args) { //是否启用zk配置,/myid.properties中的loadZk属性决定,默认不启用,从本地xml文件中读取配置
ZkConfig.instance().initZk(); try {
String home = SystemConfig.getHomePath(); if (home == null) {
System.out.println(SystemConfig.SYS_HOME + " is not set.");
System.exit(-1);
} // init
MycatServer server = MycatServer.getInstance();
server.beforeStart(); // startup
server.startup();
System.out.println("MyCAT Server startup successfully. see logs in logs/mycat.log"); while (true) {
Thread.sleep(300 * 1000);
}
} catch (Exception e) {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
LogLog.error(sdf.format(new Date()) + " startup error", e);
System.exit(-1);
}
}
从代码中,可以简单的分为三步:
MycatServer.getInstance():获取MyCat实例,其实就是读取配置文件,并验证正确性等
server.beforeStart():获取环境变量,日志配置
server.startup():启动MyCat,启动线程,初始化线程池和连接池等。
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 SVN迁移到GIT
【推荐】 移动端推广APP防作弊机制之依我见
数据库路由中间件MyCat - 源代码篇(10)的更多相关文章
- 数据库路由中间件MyCat - 源代码篇(1)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 进入了源代码篇,我们先从整体入手,之后拿一个简单流程前端连接建立与认证作为例子,理清代码思路和设计模式.然后 ...
- 数据库路由中间件MyCat - 源代码篇(13)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 4.配置模块 4.2 schema.xml 接上一篇,接下来载入每个schema的配置(也就是每个MyCat ...
- 数据库路由中间件MyCat - 源代码篇(7)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 3.4 FrontendConnection前端连接 构造方法: public Fronte ...
- 数据库路由中间件MyCat - 源代码篇(15)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. public static void handle(String stmt, ServerConnectio ...
- 数据库路由中间件MyCat - 源代码篇(17)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 调用processInsert(sc,schema,sqlType,origSQL,tableName,pr ...
- 数据库路由中间件MyCat - 源代码篇(14)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 对于表的dataNode对应关系,有个特殊配置即类似dataNode="distributed(d ...
- 数据库路由中间件MyCat - 源代码篇(4)
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2. 前端连接建立与认证 Title:MySql连接建立以及认证过程client->MySql:1.T ...
- 数据库路由中间件MyCat - 源代码篇(2)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2. 前端连接建立与认证 Title:MySql连接建立以及认证过程client->MySql:1.T ...
- 数据库路由中间件MyCat - 源代码篇(16)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 5. 路由模块 真正取得RouteResultset的步骤:AbstractRouteStrategy的ro ...
随机推荐
- java网络编程—TCP(1)
演示tcp的传输的客户端和服务端的互访. 需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息. 客户端: 1,建立socket服务.指定要连接主机和端口. 2,获取socket流中的输出流. ...
- 【extjs6学习笔记】1.14 初始: ViewModel
ViewModel是一个管理特定UI组件数据的类. 可以将其视为特定视图的记录容器. 它支持与UI组件的双向数据绑定,只要用户在视图中更改数据,它具有最新的副本. 与模型不同,它不能包含代理,因此它不 ...
- MySQL访问
MySQL访问 1.介绍 python访问mysql数据库,需要安装mysql的python插件. 2.安装插件 通过pip命令安装mysql插件. # cmd>pip install PyMy ...
- ARM实验1 —— 流水灯实验
实验内容: 编写GPIO模块程序,实现对FS_4412平台的上的led2,led3,led4 ,led5,的流水灯实现. 实验目的: 熟悉开发环境的使用. 掌握Exynos 4412处理器GPIO功能 ...
- Redis常用特性
发布订阅 ·服务器状态在pubsub_channels字典保存了所有频道的订阅关系:SUBSCRIBE命令负责将客户端和被订阅的频道关联到这个字典里面,而UNSUBSCRIBE命令则负责解除客户端和被 ...
- 【BZOJ3720】Gty的妹子树(主席树+时间分块)
点此看题面 大致题意: 给你一棵有根树,让你支持三种操作:询问某子树中大于\(x\)的值的个数,把某一节点值改成\(x\),添加一个父节点为\(u\).权值为\(x\)的节点. 关于此题做法 此题做法 ...
- python setup.py install 报错
python setup.py install 报错信息 [root@VM_25_28_centos psutil-2.0.0]# python setup.py install running in ...
- Python求包含数字或字母最长的字符串及长度
一.求包含数字或字母最长的字符串及长度 org = 'ss121*2222&sdfs2!aaabb' result = [] #保存最终要输出的字符串 result_temp = [] #保存 ...
- javaweb基础(25)_jsp标签实例一
一.简单标签(SimpleTag) 由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广, SUN公司为降低标签技术的学习难度,在JSP 2.0中定义了一个更为简单.便于编 ...
- 操作系统(4)_进程同步_李善平ppt
生产者进程count++是它的临界区,消费者count--是它的临界区. 经典同步问题,死锁问题,略.