设为首页 加入收藏

TOP

分布式数据库中间件?(3)Cobar对简单select命令的处理过程(一)
2014-11-24 00:04:34 来源: 作者: 【 】 浏览:37
Tags:分布式 数据库 中间件 Cobar 简单 select 命令 处理 过程

在认证成功后Cobar会将该连接的回调处理函数由FrontendAuthenticator(前端认证处理器)设置成FrontendCommandHanler(前端命令处理器)。

所以在客户端再次向Cobar发送请求报文的时候,前端命令处理器会处理该连接。下面详细分析一下简单select语句的执行过程。

1、事件的产生

NIOReactor的R线程一直在监听selector上的每个连接的感兴趣事件是否发生,当客户端发送了一条select * from tb1,select函数会返回,然后获取到该连接SelectionKey,并且该SelectKey的兴趣事件是OP_READ。此时会调用read(NIOConnection)函数。

01 public void run() {
02 final Selector selector = this.selector;
03 for (;;) {
04 ++reactCount;
05 try {
06 int res = selector.select();
07 LOGGER.debug(reactCount + ">>NIOReactor接受连接数:" + res);
08 register(selector);
09 Set keys = selector.selectedKeys();
10 try {
11 for (SelectionKey key : keys) {
12 Object att = key.attachment();
13 if (att != null && key.isValid()) {
14 int readyOps = key.readyOps();
15 if ((readyOps & SelectionKey.OP_READ) != 0) {
16 LOGGER.debug("select读事件");
17 read((NIOConnection) att);
18 ..............................
19 }
20 ...........................
21 }
22 } ..................
23 } ............
24 }
25 }

2、调用该连接的read函数进行处理

该函数在上一篇中提到过,该函数的实现在AbstractConnection中,实现从channel中读取数据到缓冲区,然后从缓冲区完整的取出整包数据交给FrontendConnection类的handle()函数处理。

该函数交给processor进行异步处理。从processor中的线程池获取一个线程来执行该任务。这里调用具体的handler来进行处理。

刚开始提到的,当认证成功后,Cobar将连接的回调处理函数设置为FrontendCommandHandler。所以这里会调用前端命令处理器的handler函数进行数据的处理。

在这里需要先了解MySQL数据包的格式:

MySQL客户端命令请求报文

MySQL客户端命令请求报文

该处理函数如下:

01 public void handle(byte[] data) {
02 LOGGER.info("data[4]:"+data[4]);
03 switch (data[4]) {
04 case MySQLPacket.COM_INIT_DB:
05 commands.doInitDB();
06 source.initDB(data);
07 break;
08 case MySQLPacket.COM_QUERY:
09 commands.doQuery();
10 source.query(data);
11 break;
12 case MySQLPacket.COM_PING:
13 commands.doPing();
14 source.ping();
15 break;
16 case MySQLPacket.COM_QUIT:
17 commands.doQuit();
18 source.close();
19 break;
20 case MySQLPacket.COM_PROCESS_KILL:
21 commands.doKill();
22 source.kill(data);
23 break;
24 case MySQLPacket.COM_STMT_PREPARE:
25 commands.doStmtPrepare();
26 source.stmtPrepare(data);
27 break;
28 case MySQLPacket.COM_STMT_EXECUTE:
29 commands.doStmtExecute();
30 source.stmtExecute(data);
31 break;
32 case MySQLPacket.COM_STMT_CLOSE:
33 commands.doStmtClose();
34 source.stmtClose(data);
35 break;
36 case MySQLPacket.COM_HEARTBEAT:
37 commands.doHeartbeat();
38 source.heartbeat(data);
39 break;
40 default:
41 commands.doOther();
42 source.writeErrMessage(ErrorCode.ER_UNKNOWN_COM_ERROR, "Unknown command");
43 }
44 }

由于每个报文都有消息头,消息头固定的是4个字节,前3个字节是消息长度,后面的一个字节是报文序号,如下所示

mysql_protocol_struct

所以data[4]是第五个字节。也就是消息体的第一个字节。客户端向Cobar端发送的是命令报文,第一个字节是具体的命令。

如果是select语句,那么data[4]就是COM_QUERY,然后会调用具体连接的query成员函数,其定义在FrontendConnection类中。

01 public void query(byte[] data) {
02 if (queryHandler != null) {
03 // 取得语句
04 MySQLM
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇MongoDB中shard key的选择 下一篇海量数据检索的一些思考

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: