mycat启动的时候启动了三个模块

1:NIOConnector(负责链接mysql数据库,连接池以数据库为准不以链接字符串为准),

1:NIOAcceptor,ManagerConnectionFactory(管理模块,默认端口9066)

2:NIOAcceptor,ServerConnectionFactory(mysql服务模块,默认端口8066)

这里介绍下管理模块的启动流程

顺序图

NIO和AIO

mycat分别实现了NIO和AIO,由于linux当前没有真正实现AIO这里主要介绍NIO的流程。

NIO的Reactor与AIO的Proactor两种模式的场景区别:
下面是Reactor的做法:
1. 等待事件响应 (Reactor job)
2. 分发 “Ready-to-Read” 事件给用户句柄 ( Reactor job)
3. 读数据 (user handler job)
4. 处理数据( user handler job)
下面再来看看真正意义的异步模式Proactor是如何做的:
1. 等待事件响应 (Proactor job)
2. 读数据 (Proactor job)
3. 分发 “Read-Completed” 事件给用户句柄 (Proactor job)
4. 处理数据(user handler job)

mycat的NIO实现

Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。
Selector可以监听四种不同类型的事件:
- Connect
- Accept
- Read
- Write
这四种事件用SelectionKey的四个常量来表示:
- SelectionKey.OP_CONNECT
- SelectionKey.OP_ACCEPT
- SelectionKey.OP_READ
- SelectionKey.OP_WRITE
前面已经说了,NIO采用的Reactor模式:例如汽车是乘客访问的主体(Reactor),乘客上车后,到售票员(acceptor)处登记,之后乘客便可以休息睡觉去了,当到达乘客所要到达的目的地后,售票员将其唤醒即可。

核心顺序

mycat管理端的启动流程

1:new ManagerConnectionFactory extends FrontendConnectionFactory

2:new NIOReactorPool,new NIOReactor,new RW中new ConcurrentLinkedQueue<AbstractConnection>()而AbstractConnection中new NIOSocketWR

3:new NIOAcceptor中向反应堆中注册了OP_ACCEPT,该类继承了Thread然后start启动

accept

			channel = serverChannel.accept();
channel.configureBlocking(false);
FrontendConnection c = factory.make(channel);
c.setAccepted(true);
c.setId(ID_GENERATOR.getId());
NIOProcessor processor = (NIOProcessor) MycatServer.getInstance()
.nextProcessor();
c.setProcessor(processor); LOGGER.info("accept"); NIOReactor reactor = reactorPool.getNextReactor();
reactor.postRegister(c);

factory.make(channel):最终构造了ManagerQueryHandler(管理命令解析器)和FrontendAuthenticator(mycat权限解析器)

reactor.postRegister(c):把当前链接添加到reactor的registerQueue中并唤醒reactor的selector

read

在NIOReactor的registerQueue为空的时候run循环空运转,当上一步把accept的链接放到队列的时候则

			for (;;) {

				++reactCount;
try {
selector.select(500L);
register(selector);
keys = selector.selectedKeys();
for (SelectionKey key : keys) {
AbstractConnection con = null;
try {
Object att = key.attachment();
if (att != null) {
con = (AbstractConnection) att;
if (key.isValid() && key.isReadable()) {
try {
con.asynRead();
} catch (IOException e) {
con.close("program err:" + e.toString());
continue;
} catch (Exception e) {
LOGGER.debug("caught err:", e);
con.close("program err:" + e.toString());
continue;
}
}
if (key.isValid() && key.isWritable()) {
con.doNextWriteCheck();
}
} else {
key.cancel();
}
} catch (CancelledKeyException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(con + " socket key canceled");
}
} catch (Exception e) {
LOGGER.warn(con + " " + e);
}
}
} catch (Exception e) {
LOGGER.warn(name, e);
} finally {
if (keys != null) {
keys.clear();
} }

register(selector);也即

((NIOSocketWR) c.getSocketWR()).register(selector); 注册OP_READ事件
c.register();即FrontendConnection的register发送握手数据包

con.asynRead();即NIOSocketWR的asynRead即

	public void asynRead() throws IOException {
LOGGER.info("asynRead");
ByteBuffer theBuffer = con.readBuffer;
if (theBuffer == null) {
theBuffer = con.processor.getBufferPool().allocate();
con.readBuffer = theBuffer;
}
int got = channel.read(theBuffer);
con.onReadData(got); }

con.onReadData(got);即AbstractConnection的onReadData这里拆包得到完成的数据包后调用

handler.handle(data);也即FrontendAuthenticator的handle在这里check user;check password;check schema如果失败则将失败信息写入缓冲区,如果成功

则把AbstractConnection的默认hander从FrontendAuthenticator换成FrontendCommandHandler等待接下来的处理(比如show命令等,

以上的处理是发生在输入mysql -utest -ptest -h10.97.177.83 -P9066时)

认证完成后下一次的handler.handle(data)则使用FrontendCommandHandler的handle来处理也即

    public void handle(byte[] data)
{
if(source.getLoadDataInfileHandler()!=null&&source.getLoadDataInfileHandler().isStartLoadData())
{
MySQLMessage mm = new MySQLMessage(data);
int packetLength = mm.readUB3();
if(packetLength+4==data.length)
{
source.loadDataInfileData(data);
}
return;
}
switch (data[4])
{
case MySQLPacket.COM_INIT_DB:
commands.doInitDB();
source.initDB(data);
break;
case MySQLPacket.COM_QUERY:
commands.doQuery();
source.query(data);
break;
case MySQLPacket.COM_PING:
commands.doPing();
source.ping();
break;
case MySQLPacket.COM_QUIT:
commands.doQuit();
source.close("quit cmd");
break;
case MySQLPacket.COM_PROCESS_KILL:
commands.doKill();
source.kill(data);
break;
case MySQLPacket.COM_STMT_PREPARE:
commands.doStmtPrepare();
source.stmtPrepare(data);
break;
case MySQLPacket.COM_STMT_EXECUTE:
commands.doStmtExecute();
source.stmtExecute(data);
break;
case MySQLPacket.COM_STMT_CLOSE:
commands.doStmtClose();
source.stmtClose(data);
break;
case MySQLPacket.COM_HEARTBEAT:
commands.doHeartbeat();
source.heartbeat(data);
break;
default:
commands.doOther();
source.writeErrMessage(ErrorCode.ER_UNKNOWN_COM_ERROR,
"Unknown command"); }
}

source.query(data);即queryHandler.query(sql);这里的queryHandler是ManagerQueryHandler即

    public void query(String sql) {
ManagerConnection c = this.source;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(new StringBuilder().append(c).append(sql).toString());
}
int rs = ManagerParse.parse(sql);
switch (rs & 0xff) {
case ManagerParse.SELECT:
SelectHandler.handle(sql, c, rs >>> SHIFT);
break;
case ManagerParse.SET:
c.write(c.writeToBuffer(OkPacket.OK, c.allocate()));
break;
case ManagerParse.SHOW:
ShowHandler.handle(sql, c, rs >>> SHIFT);
break;
case ManagerParse.SWITCH:
SwitchHandler.handler(sql, c, rs >>> SHIFT);
break;
case ManagerParse.KILL_CONN:
KillConnection.response(sql, rs >>> SHIFT, c);
break;
case ManagerParse.OFFLINE:
Offline.execute(sql, c);
break;
case ManagerParse.ONLINE:
Online.execute(sql, c);
break;
case ManagerParse.STOP:
StopHandler.handle(sql, c, rs >>> SHIFT);
break;
case ManagerParse.RELOAD:
ReloadHandler.handle(sql, c, rs >>> SHIFT);
break;
case ManagerParse.ROLLBACK:
RollbackHandler.handle(sql, c, rs >>> SHIFT);
break;
case ManagerParse.CLEAR:
ClearHandler.handle(sql, c, rs >>> SHIFT);
break;
case ManagerParse.CONFIGFILE:
ConfFileHandler.handle(sql, c);
break;
case ManagerParse.LOGFILE:
ShowServerLog.handle(sql, c);
break;
default:
c.writeErrMessage(ErrorCode.ER_YES, "Unsupported statement");
}
}

总结

mycat的网络处理逻辑上是通过队列加上后台线程来实现了accept和read的解耦从而实现了高性能,但是代码写的就不敢恭维。

mycat服务启动{管理模块启动过程}的更多相关文章

  1. 『学了就忘』Linux服务管理 — 77、RPM包安装基于xinetd的服务的管理

    目录 1.基于xinetd服务的启动管理 (1)telnet服务安装 (2)telnet服务启动 2.基于xientd服务的自启动管理 现在Linux系统中基于xinetd的服务越来越少了,但Linu ...

  2. centOS7服务管理与启动流程

    centOS7服务管理与启动流程 centOS7启动流程 systemd简介 unit对象 unit类型 特性 service unit文件格式 service unit file文件通常由三部分组成 ...

  3. 启动期间的内存管理之初始化过程概述----Linux内存管理(九)

    在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检 ...

  4. python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。

    本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...

  5. Ubuntu管理开机启动服务项 -- 图形界面的Boot-up Manager

    有时学习时安装的服务太多,比如mysql.mongodb.redis.apache.nginx等等,它们都是默认开机启动的,如果不想让它们开机启动,用到时再自己手工启动怎么办呢? 使用sysv-rc- ...

  6. 第14章 Linux启动管理(1)_系统运行级别

    1. CentOS 6.x 启动管理 (1)系统运行级别 ①运行级别 运行级别 含义 0 关机 1 单用户模式,可以想象为Windows的安全模式,主要用于系统修复.(但不是Linux的安全模式) 2 ...

  7. linux 学习15 16 启动管理,备份和恢复

    第十五讲 启动管理 . CentOS .x 启动管理 //此处指6.3 系统运行级别 .运行级别 运行级别 含 义 关机 单用户模式,可以想象为windows的安全模式,主要用于系统修复 //linu ...

  8. Asterisk服务安装配置和启动

    Asterisk服务安装配置和启动 2014年11月4日 11:36 注意: 更新源的重要性 源的地址: http://fffo.blog.163.com/blog/static/2119130682 ...

  9. Openstack本学习笔记——Neutron-server服务加载和启动源代码分析(三)

    本文是在学习Openstack过程中整理和总结.因为时间和个人能力有限.错误之处在所难免,欢迎指正! 在Neutron-server服务载入与启动源代码分析(二)中搞定模块功能的扩展和载入.我们就回到 ...

随机推荐

  1. UIView的剖析(转)

    转自:http://blog.csdn.net/mengtnt/article/details/6716289 前面说过UIViewController,但是UIView也是在MVC中非常重要的一层  ...

  2. 去哪儿网mysql语法审核工具Inception正式开源

    Inception不仅仅是一个自动化审核工具,同时还具备执行SQL,并且生成对影响数据的回滚语句(类似于闪回的功能),这样一条龙便捷服务的工具.

  3. 无法远程连接ubuntu下的mysql

    修改前 无法telnet 2.2.2.128 3306 打开 /etc/mysql/my.cnf 文件,找到 bind-address = 127.0.0.1 修改为 bind-address = 0 ...

  4. 第37讲:List的foldLeft、foldRight、sort操作代码实战

    其实flodLeft和foldRight就是折叠操作,我让们看下下列的函数 折叠操作    def sum(xs:List[Int]):Int = ( 0 /: xs)(_ +_)     def p ...

  5. Omu.AwesomeMvc.dll 和Omu.ValueInjecter.dll 介绍

    AwesomeMvc 让你不写一行js实现下拉列表联动 AwesomeMvc是个开源项目,地址:http://awesome.codeplex.com/ Omu.AwesomeMvc.dll 和Omu ...

  6. slick-pg v0.1.5 发布

    这个版本的更新主要是: 增加了对 json 的支持 (PostgreSQL 9.3 正式版已经发布了,所以我适时加入了对 pg json 的支持.功能其实前两个星期就已经开发测试好了,但公司跟联邦政府 ...

  7. 用c#开发微信 (11) 微统计 - 阅读分享统计系统 1 基础架构搭建

    微信平台自带的统计功能太简单,有时我们需要统计有哪些微信个人用户阅读.分享了微信公众号的手机网页,以及微信个人用户访问手机网页的来源:朋友圈分享访问.好友分享消息访问等.本系统实现了手机网页阅读.分享 ...

  8. ContentControl 与 ViewModel (一)

    前阵子有人问我MVVM模式下,在View中嵌套View,切换View.想一想还是写下来吧. 主要就是用到 ContentControl 和 DataTemplate,这算是一种 ViewModel F ...

  9. NABCD需求分析

    1. N 需求    如今的社会,每个公司每个人都有大量的信息需要处理.保管和查询,这就难免会有些信息在个人电脑中保存的位置被遗忘,需要一款简单并且实用的搜索引擎来搜索个人 所需求的信息. 2. A ...

  10. 【源码笔记】BlogEngine.Net 中的权限管理

    BlogEngine.Net 是个功能点很全面的开源博客系统,容易安装和实现定制,开放接口支持TrackBack,可以定义主题配置数据源等等.可谓五脏俱全,这里先记录一下它基于Membership的权 ...