分库分表2).ShardingSphere-proxy 源码笔记

参考1: https://blog.csdn.net/LZN51/article/details/111031194

参考2:https://www.cnblogs.com/binarylei/p/12233756.html

整体运行流程

    • org.apache.shardingsphere.proxy.Bootstrap.mian()启动;
    • AbstractBootstrapInitializer :创建netty3307服务,从该服务器接收到一条指令开始。
    • FrontendChannelInboundHandler : 接收客户端指令, 这里会验证是否有登录,如果有登录, 创建一个CommandExecutorTask线程解析指令。核心流程也在这里:
//org.apache.shardingsphere.proxy.frontend.command。CommandExecutorTask#
private boolean executeCommand(final ChannelHandlerContext context, final PacketPayload payload, final BackendConnection backendConnection) throws SQLException {
    // 1.获得sql命令执行引擎; DatabaseProtocolFrontendEngine ⽤于ShardingSphere-Proxy 解析与适配访问数据库的协议。
    CommandExecuteEngine commandExecuteEngine = databaseProtocolFrontendEngine.getCommandExecuteEngine();
    // 2.SQL命令类型;
    CommandPacketType type = commandExecuteEngine.getCommandPacketType(payload);
    // 3.SQL命令包;
    CommandPacket commandPacket = commandExecuteEngine.getCommandPacket(payload, type, backendConnection);
    // 4.SQL命令执行器
    CommandExecutor commandExecutor = commandExecuteEngine.getCommandExecutor(type, commandPacket, backendConnection);
    // 5.SQL命令执行器执行命令并返回结果包;
    Collection<DatabasePacket<?>> responsePackets = commandExecutor.execute();
    if (responsePackets.isEmpty()) {
        return false;
    }
    // 写入列信息
    responsePackets.forEach(context::write);
    if (commandExecutor instanceof QueryCommandExecutor) {
        // 写入行信息
        commandExecuteEngine.writeQueryData(context, backendConnection, (QueryCommandExecutor) commandExecutor, responsePackets.size());
        return true;
    }
    return databaseProtocolFrontendEngine.getFrontendContext().isFlushForPerCommandPacket();
}
  • SQL命令执行引擎:
    • 看方法实现方法proxy 支持了mysql 和 postgreSql的执行引擎;org.apache.shardingsphere.proxy.frontend.spi.DatabaseProtocolFrontendEngine#getCommandExecuteEngine

  • SQL命令类型:
    • MySQLCommandPacketType 枚举了所有的MYSQL指令类型, getCommandPacketType 是通过SQL 请求命令包的一个字节来判定 SQL 请求类型。
    • MySQLCommandPacketTypeLoader.getCommandPacketType() 与枚举的匹配当前是哪种指令。
  • SQL命令包:
    • MySQLCommandPacketFactory#newInstance 会根据不同的 SQL 请求类型返回不同的 SQL 命令包。
  • SQL命令执行器:
    • commandExecuteEngine.getCommandExecutor 也是genuine不同的SQL请求类型返回不同的SQL命令执行器;
    • 需要注意的是: 在org.apache.shardingsphere.proxy.backend.text.TextProtocolBackendHandlerFactory#newInstance中:
public static TextProtocolBackendHandler newInstance(final DatabaseType databaseType, final String sql, final BackendConnection backendConnection) {
    if (Strings.isNullOrEmpty(sql)) {
        return new SkipBackendHandler();
    }
    // TODO Parse sctl SQL with ANTLR
    String trimSQL = SCTLUtils.trimComment(sql);
    // 对于前缀为 'SCTL:' 的 SQL 请求,直接返回 ShardingCTLxxxHandler 处理器
    if (trimSQL.toUpperCase().startsWith(ShardingCTLBackendHandlerFactory.SCTL)) {
        return ShardingCTLBackendHandlerFactory.newInstance(trimSQL, backendConnection);
    }
    SQLStatement sqlStatement = new ShardingSphereSQLParserEngine(databaseType.getName()).parse(sql, false);
    //  建库、删库的sql请求
    if (sqlStatement instanceof RDLStatement || sqlStatement instanceof CreateDatabaseStatement || sqlStatement instanceof DropDatabaseStatement) {
        return new RDLBackendHandler(backendConnection, sqlStatement);
    }
    // 事务控制相关请求
    if (sqlStatement instanceof TCLStatement) {
        return TransactionBackendHandlerFactory.newInstance(sql, (TCLStatement) sqlStatement, backendConnection);
    }
    //DAL相关请求 show databases,show tables...
    if (sqlStatement instanceof DALStatement) {
        return DALBackendHandlerFactory.newInstance(sql, (DALStatement) sqlStatement, backendConnection);
    }
    // 查询请求 直接返回QueryBackendHandler
    return new QueryBackendHandler(sql, sqlStatement, backendConnection);
    • 经过上一步,一条select查询请求使用的是 QueryBackendHandler,使用执行器执行语句则是 org.apache.shardingsphere.proxy.backend.text.query.QueryBackendHandler#execute
    • 上一步中execute 获取数据库执行引擎, MySQL 对应 JDBCDatabaseCommunicationEngine。 调用
    • org.apache.shardingsphere.proxy.backend.communication.jdbc.JDBCDatabaseCommunicationEngine#execute , 其它过程见下方时序图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值