Mycat开发实践—Mycat的网络通信框架

1从一个测试说起

网上有人对Cobar和MyCAT做了一个简单的比较测试,过程如下:
1 测试环境
利用A、B、C三大类服务器,在A台上面安装配置MyCAT及Cobar,这样保证了硬件方面的一致性。B类服务器上安装Apache这一web服务,使用PHP语言。C类安装MySQL数据库,其中B类与C类均不止一台,主要目的是为了作压力的均分。C类服务器安装了4台,存放了相同的数据库,对其中一个表进行分片存储。
测试软件使用的是loadRunner。在对两个中间件分别进行测试的过程中,采用的web服务器执行页面及相关数据库,均未调整,仅在中间件上有分别。比对情况如下图:

这里写图片描述
这里写图片描述
– SocketConnector 发起连接请求类,如MyCAT与MySQL数据库的连接,都是由MyCAT主动发起连接请求
– SocketAcceptor 接收连接请求类,如MyCAT启动9066和8066分别侦听管理员和应用程序的连接请求
– SocketWR读写操作类,SocketConnector和SocketAcceptor只负责socket建立,当socket连接建立后进行字节的读写操作则由SocketWR来完成。

这几个接口分别处理网络通道的四种不同类型的事件:
– Connect客户端连接服务端事件
– Accept 服务端接收客户端连接事件
– Read 读事件
– Write 写事件
NIO主要类调用

这里写图片描述
AIO主要类调用-客户端
这里写图片描述
在高性能IO框架中,大都是采用多Reactor模式,即多个dispatcher,如下图所示:
这里写图片描述
多Reactor区分说明:
通常Reactor实现为一个线程,内部维护一个Selector

3 与Cobar原有NIO细节比较

3.1 Cobar的NIO
Cobar后端是采用BIO,前端采用NIO;Cobar的BIO这儿就不必提了,对于原有NIO实现,跟MyCAT相比,读方式差不多,写的差别比较大。
NIOReactor.postWrite()
这儿传入的参数,不是要写的buffer,而是一个连接对象,只是注册这个对象有内容需要写。要写的buffer,在连接对象自己的缓存队列中
这种方式与MyCAT差不多,连接对象自己维护写队列。
NIOReactor.W内部类
专门负责缓冲队列写,不停循环遍历,等待其它业务线程放入写数据
NIOReactor.R内部类
为一个seletor同时处理读事件和写事件。但是主要负责的是读,只有在网络非常繁忙等极少数情况下,小概率走到读分支。
基于队列的写和基于事件的写

  • 队列写:所有的写请求,放到缓存队列,由独立W线程进行写。如果未写完(比如网络繁忙),则注册写事件,然后会再seleltor发现写事件
  • 事件写:R线程中,seletor探测到写事件后,进行写操作。如果写完了,则立即取消注册写事件,避免继续触发导致循环
  • 总结:主要是W线程进行写,只有在网络繁忙时,才会注册写事件,等待网络写就绪后,R线程就会立即发现写事件,然后R线程再写一部分。

3.2 比较MyCAT和Cobar两种写方式

  • Cobar的写:业务线程把写请求放到缓冲队列,然后由独立写线程W负责,当W在写的时候,网络慢等原因导致未写完,然后注册写事件,由R线程(selector)进行候补写

  • MyCAT的写:业务线程先通过加锁或者AtomicBoolean判断当前channel是否正在写数据,如空闲则由当前线程直接写,否则入缓冲队列交给其他线程写;在写的时候,网络慢等原因导致未写完,
    然后注册写事件,由NIOReactor线程(selector)进行候补写;

  • MyCAT采用这种方式的显著优点:尽可能减少系统调用和线程切换;

4 MyCAT的AIO实现

4.1 JAVA AIO体系
从代码风格上比较,NIO和AIO的差别,就是Reactor和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)

可以看到两者最大的区别,就是到了AIO,用户只管专心负责对读到的数据进行处理,如何读的过程过程就全交给系统层面去完成。
同样对于写操作,在AIO方式中,应用层只管把要写的buffer传递出去,等到系统写完,再回调应用层做其它动作。
而在NIO方式中,应用层要自己控制buffer写入channel的过程。
首先看下AIO引入的新的类和接口:
java.nio.channels.AsynchronousChannel
标记一个channel支持异步IO操作。
java.nio.channels.AsynchronousServerSocketChannel
ServerSocket的aio版本,创建TCP服务端,绑定地址,监听端口等。 java.nio.channels.AsynchronousSocketChannel
面向流的异步socket channel,表示一个连接。 java.nio.channels.AsynchronousChannelGroup
异步channel的分组管理,目的是为了资源共享。一个AsynchronousChannelGroup绑定一个线程池,这个线程池执行两个任务:处理IO事件和派发CompletionHandler。AsynchronousServerSocketChannel创建的时候可以传入一个 AsynchronousChannelGroup,那么通过AsynchronousServerSocketChannel创建的 AsynchronousSocketChannel将同属于一个组,共享资源。 java.nio.channels.CompletionHandler
异步IO操作结果的回调接口,用于定义在IO操作完成后所作的回调工作。
AIO的API允许两种方式来处理异步操作的结果:返回的Future模式或者注册CompletionHandler,MyCAT采用的是CompletionHandler的方式,这些handler的调用是由 AsynchronousChannelGroup的线程池派发的。

文章知识点与官方知识档案匹配,可进一步学习相关知识MySQL入门技能树数据库组成31449 人正在系统学习中

来源:wangshuang1631

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2017年3月22日
下一篇 2017年3月22日

相关推荐