mycat 后期mysql服务器_一步一步编写mysql中间件(学习Cobar和MyCat)-第四篇----实现伪MySQL服务器,基于MySQL协议的HelloWorld...

第二篇的剩下四个部分实现:

(2)然后启动AIO的read,进行客户端包的接收,接收的第一个包是AuthPacket,需要对接收的二进制数据包进行解析,并校验登录信息。

(3)     校验成功后返回OkPacket给客户端(AIO write)

(4)接收客户端会默认发送的查询命令:Select @@version_comment limit 1,需要编写相应的解析。

(5)对于查询返回结果,需要组成成结果集的包(ResultsetPacket),返回给客户端

各部分实现简要说明:

(2)增加AuthServerHandler对AuthPacket进行处理,主要是解析Authpacket和校验登录信息,增加的相关类:

SecurityUtil:mysql的密码解密工具类,实际拷贝来自Cobar,加密的原理应该是,利用服务端返回的HandshakePacket里面的salt和restOfSalt组成的20个byte进行加密,该20个byte实际需要随机生成,我们现在代码里面是写死,减少复杂度,主要是了解框架。所有解密的时候也需要用到该byte数组。

AuthServerHandler:解析生成AuthPacket对象,同时进行用户名、密码、数据库等校验。

MySQLMessage:对获取的byte数组的处理封装,用于字节解析,Packet通过该工具类从byte数组中解析自己的属性。

(3)返回OKPacket,这个OKPacket由于比较简单,就没有组装对应的OKPacket对象,直接将其byte数组写入byteBuffer,然后写回给客户端了。

用截包工具截获对比下即可理解。

private static final byte[] AUTH_OK = newbyte[] { 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0 };

source.write(AUTH_OK);

(4)     由于客户端登陆成功后,会默认发一条命令过来。Select @@version_comment limit 1,由于sql的解析是一个非常非常庞大的工程,后面再慢慢研究,暂时就简单的equal判断下该语句。然后返回一个结果集给客户端。

CommandServerHandler:处理常规的命令。

if(sql.equalsIgnoreCase("select @@version_comment limit 1"))

{

//返回结果集

ResultSetHeaderPacket resultSetHeaderPacket = new ResultSetHeaderPacket();

resultSetHeaderPacket.packetNum = 1;

resultSetHeaderPacket.fieldCount = 1;

FieldPacket fieldPacket = new FieldPacket();

fieldPacket.packetNum = 2;

fieldPacket.name = "@@version_comment".getBytes();

EOFPacket midEofPacket = new EOFPacket();

midEofPacket.packetNum = 3;

RowDataPacket rowDataPacket = new RowDataPacket();

rowDataPacket.packetNum=4;

rowDataPacket.fieldCount=1;

rowDataPacket.fieldValues = new ArrayList();

rowDataPacket.fieldValues.add("test".getBytes());

EOFPacket endEofPacket = new EOFPacket();

endEofPacket.packetNum = 5;

ResultsetPacket resultsetPacket = new ResultsetPacket(resultSetHeaderPacket,fieldPacket,midEofPacket,rowDataPacket,endEofPacket);

source.write(resultsetPacket);

}

完成这步的时候,cmd客户端即可以和这个Server建立连接了。如下图所示:

0818b9ca8b590ca3270a3433284dd417.png

(5)     成功建立连接之后还不够,还需要和客户端进行交互是把,那么最经典的HelloWorld结构模式就是第一步交互了。

上面第四步贴的代码里面已经有结果集包相关的结构,这里再简要说明下:

MySQL结果集包的组成模式是:(具体实例结合截包和代码对应分析)

一个头包(ResultSetHeaderPacket)

多个字段包(FieldPacket)

一个分隔包(EOFPacket)

多个行数据包(RowDataPacket)

一个分隔包(EOFPacket)

那么HelloWorld的简单实现如下:

接收需要处理的语句,然后自段名称为Hello,行数据为需要处理的语句。逻辑如下:

//返回结果集

ResultSetHeaderPacket resultSetHeaderPacket = new ResultSetHeaderPacket();

resultSetHeaderPacket.packetNum = 1;

resultSetHeaderPacket.fieldCount = 1;

FieldPacket fieldPacket = new FieldPacket();

fieldPacket.packetNum = 2;

fieldPacket.name = "Hello".getBytes();

EOFPacket midEofPacket = new EOFPacket();

midEofPacket.packetNum = 3;

RowDataPacket rowDataPacket = new RowDataPacket();

rowDataPacket.packetNum=4;

rowDataPacket.fieldCount=1;

rowDataPacket.fieldValues = new ArrayList();

rowDataPacket.fieldValues.add(sql.getBytes());

EOFPacket endEofPacket = new EOFPacket();

endEofPacket.packetNum = 5;

ResultsetPacket resultsetPacket = new ResultsetPacket(resultSetHeaderPacket,fieldPacket,midEofPacket,rowDataPacket,endEofPacket);

source.write(resultsetPacket);

现在的效果展示:

0818b9ca8b590ca3270a3433284dd417.png

这样基于MySQL协议,java AIO框架的伪MySQL服务器初步建立。

变化或者新增的代码贴下:

0818b9ca8b590ca3270a3433284dd417.png

后面的路还很长,主要是两个大的方面:SQL解析和后端连接的建立和管理。

这两个方面是最大的难题,咱还是先再仔细深入的研究了解下前面已经完成的代码,进行一定的重构和优化思考看看,所以两大部分暂时先不整,接下来有时间研究下AIO的读写性能优化,就是引入ByteBuffer的缓存处理机制,同时建立简单的测试手段,测试一下重构优化是否提高了性能,提高了哪一方面。 未完待续,时间待定,最近好忙。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值