afredlyj / mynote

idea and note
1 stars 0 forks source link

sharding-jdbc相关 #19

Open afredlyj opened 8 years ago

afredlyj commented 8 years ago

sharding-jdbc 源码分析

SpringShardingDataSource

基于Spring命名空间的分片数据源。sharding-jdbc采用自定义Spring Schema的方式,提高了配置的便捷性。shards-jdbc自定义了三个Spring Schema:

public final class ShardingJdbcNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("strategy", new ShardingJdbcStrategyBeanDefinitionParser());
        registerBeanDefinitionParser("data-source", new ShardingJdbcDataSourceBeanDefinitionParser());
        registerBeanDefinitionParser("master-slave-data-source", new MasterSlaveDataSourceBeanDefinitionParser());
    }
}

SpringShardingDatdaSource类的解析由ShardingJdbcDataSourceBeanDefinitionParser完成,BeanDefinition的解析代码如下:

 @Override
 //CHECKSTYLE:OFF
 protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
 //CHECKSTYLE:ON
        BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(SpringShardingDataSource.class);
        factory.addConstructorArgValue(parseShardingRuleConfig(element, parserContext));
        factory.addConstructorArgValue(parseProperties(element, parserContext));
        return factory.getBeanDefinition();
    }

随着IOC容器初始化完成,业务代码就可以引用SpringShardingDataSource了,这对于sharding-jdbc来说,才刚刚开始。

接下来根据官网的example,来看看整个调用流程,这里从简单的jdbc入手分析。调用流程如下:

    @Override
    public void select() {
        String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?";
        try (
        // 从这里入手分析
            Connection conn = shardingDataSource.getConnection();
            PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
            preparedStatement.setInt(1, 1);
            preparedStatement.setInt(2, 2);
            try (ResultSet rs = preparedStatement.executeQuery()) {
                while (rs.next()) {
                    System.out.println("orderItemId:" + rs.getInt(1) + ",orderId:" + rs.getInt(2) 
                        + ",userId:" + rs.getInt(3) + ",status:" + rs.getString(4));
                }
            }
        // CHECKSTYLE:OFF
        } catch (final Exception ex) {
        // CHECKSTYLE:ON
            ex.printStackTrace();
        }
    }

// SpringShardingDataSource的父类ShardingDataSource
    @Override
    public ShardingConnection getConnection() throws SQLException {
        MetricsContext.init(shardingProperties);
        return new ShardingConnection(shardingContext);
    }

SQLRouteEngine

解析sql之后,由SQLRouteEngine负责路由。

MasterSlaveDataSource

sharding-jdbc支持主从配置,由MasterSlaveDataSource完成这部分工作,该类的属性如下:

 private static final ThreadLocal<Boolean> DML_FLAG = new ThreadLocal<Boolean>() {

        @Override
        protected Boolean initialValue() {
            return false;
        }
    };

    private final String name;

    private final DataSource masterDataSource;

    private final List<DataSource> slaveDataSources;

    private final SlaveLoadBalanceStrategy slaveLoadBalanceStrategy = new RoundRobinSlaveLoadBalanceStrategy();

标志位DML_FLAG是一个ThreadLocal变量,如果当前线程处理过或将要处理非查询sql,则将该标志位设为true,并返回master数据源,否则使用从库的负载均衡策略(默认采用轮询调度算法),从slave数据源列表中选取一个数据源并返回:

public DataSource getDataSource(final SQLStatementType sqlStatementType) {
        if (SQLStatementType.SELECT != sqlStatementType || DML_FLAG.get() || HintManagerHolder.isMasterRouteOnly()) {
            DML_FLAG.set(true);
            return masterDataSource;
        }
        return slaveLoadBalanceStrategy.getDataSource(name, slaveDataSources);
    }

lombok

lombok旨在通过注解的方式减少或消除冗余的JAVA代码,需要注意的是,自动生成的代码并不会在源码中体现,lombak是通过修改字节码达到目的。 官网链接:https://projectlombok.org

Spring自定义Schema

自定义Schema包括如下几个步骤:

  1. 设计配置属性和JavaBean
  2. 编写XSD文件
  3. 编写NamespaceHandler和BeanDefinitionParser完成解析工作
  4. 编写spring.handlers和spring.schemas串联起所有部件
  5. 在Bean文件中应用

    TODO

MoreExecutors.getExitingExecutorService

afredlyj commented 8 years ago

sjdbc 配置值

配置值在类ShardingPropertiesConstant中。