it_worker365

   ::  ::  ::  ::  :: 管理

功能的注册与配置加载

以Governance分布式治理的注册中心为例

代码包整体是按照功能点划分,具体到每个功能,比如治理-代码大致分为spring-boot-starter启动加载相关;context上下文信息定义;core核心执行逻辑,比如对于注册中心,core包含了各类事件,监听的定义,等;api定义了基本的对外交互模型;对于注册中心,不同的实现又具有单独的repository-etcd类似结构目录,结构间的依赖关系源码已经定义好了

每个主要功能都有对应的启动加载类(sharding/shadow/readwrite/encrypt/db-discovery相同),注册中心起始于shardingsphere-jdbc-governance-spring-boot-starter

大体逻辑都是通过判断配置文件逻辑是否符合规范,符合则加载配置,创建对应的资源

  1 /*
  2  * Licensed to the Apache Software Foundation (ASF) under one or more
  3  * contributor license agreements.  See the NOTICE file distributed with
  4  * this work for additional information regarding copyright ownership.
  5  * The ASF licenses this file to You under the Apache License, Version 2.0
  6  * (the "License"); you may not use this file except in compliance with
  7  * the License.  You may obtain a copy of the License at
  8  *
  9  *     http://www.apache.org/licenses/LICENSE-2.0
 10  *
 11  * Unless required by applicable law or agreed to in writing, software
 12  * distributed under the License is distributed on an "AS IS" BASIS,
 13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  * See the License for the specific language governing permissions and
 15  * limitations under the License.
 16  */
 17 
 18 package org.apache.shardingsphere.spring.boot.governance;
 19 
 20 import com.google.common.base.Preconditions;
 21 import lombok.RequiredArgsConstructor;
 22 import org.apache.shardingsphere.driver.governance.internal.datasource.GovernanceShardingSphereDataSource;
 23 import org.apache.shardingsphere.infra.config.RuleConfiguration;
 24 import org.apache.shardingsphere.governance.core.yaml.config.swapper.RegistryCenterConfigurationYamlSwapper;
 25 import org.apache.shardingsphere.governance.repository.api.config.GovernanceConfiguration;
 26 import org.apache.shardingsphere.spring.boot.datasource.DataSourceMapSetter;
 27 import org.apache.shardingsphere.spring.boot.governance.common.GovernanceSpringBootRootConfiguration;
 28 import org.apache.shardingsphere.spring.boot.governance.rule.LocalRulesCondition;
 29 import org.springframework.beans.factory.ObjectProvider;
 30 import org.springframework.beans.factory.annotation.Autowired;
 31 import org.springframework.boot.autoconfigure.AutoConfigureBefore;
 32 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 33 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 34 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 35 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 36 import org.springframework.context.EnvironmentAware;
 37 import org.springframework.context.annotation.Bean;
 38 import org.springframework.context.annotation.ComponentScan;
 39 import org.springframework.context.annotation.Conditional;
 40 import org.springframework.context.annotation.Configuration;
 41 import org.springframework.core.env.Environment;
 42 
 43 import javax.sql.DataSource;
 44 import java.sql.SQLException;
 45 import java.util.Collections;
 46 import java.util.LinkedHashMap;
 47 import java.util.List;
 48 import java.util.Map;
 49 import java.util.Objects;
 50 import java.util.Optional;
 51 
 52 /**
 53  * Governance spring boot configuration.
 54  */
 55 @Configuration
 56 @ComponentScan("org.apache.shardingsphere.spring.boot.converter")
 57 @EnableConfigurationProperties(GovernanceSpringBootRootConfiguration.class)
 58 @ConditionalOnProperty(prefix = "spring.shardingsphere", name = "enabled", havingValue = "true", matchIfMissing = true)
 59 @RequiredArgsConstructor
 60 @AutoConfigureBefore(DataSourceAutoConfiguration.class)
 61 public class ShardingSphereGovernanceAutoConfiguration implements EnvironmentAware {
 62     
 63     private final Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
 64     
 65     private final GovernanceSpringBootRootConfiguration root;
 66     
 67     private final RegistryCenterConfigurationYamlSwapper swapper = new RegistryCenterConfigurationYamlSwapper();
 68     
 69     /**
 70      * Get governance configuration.
 71      *
 72      * @return governance configuration
 73      */
 74     @Bean
 75     public GovernanceConfiguration governanceConfiguration() {
 76         Preconditions.checkState(Objects.nonNull(root.getGovernance()), "The governance configuration is invalid, please configure governance");
 77         return new GovernanceConfiguration(root.getGovernance().getName(), swapper.swapToObject(root.getGovernance().getRegistryCenter()), root.getGovernance().isOverwrite());
 78     }
 79     
 80     /**
 81      * Get governance ShardingSphere data source bean by local configuration.
 82      *
 83      * @param rules rules configuration
 84      * @param governanceConfig governance configuration
 85      * @return governance sharding data source bean
 86      * @throws SQLException SQL exception
 87      */
 88     @Bean
 89     @Conditional(LocalRulesCondition.class)
 90     @Autowired(required = false)
 91     public DataSource localShardingSphereDataSource(final ObjectProvider<List<RuleConfiguration>> rules, final GovernanceConfiguration governanceConfig) throws SQLException {
 92         List<RuleConfiguration> ruleConfigurations = Optional.ofNullable(rules.getIfAvailable()).orElse(Collections.emptyList());
 93         return createDataSourceWithRules(ruleConfigurations, governanceConfig);
 94     }
 95     
 96     /**
 97      * Get data source bean from registry center.
 98      *
 99      * @param governanceConfig governance configuration
100      * @return data source bean
101      * @throws SQLException SQL Exception
102      */
103     @Bean
104     @ConditionalOnMissingBean(DataSource.class)
105     public DataSource dataSource(final GovernanceConfiguration governanceConfig) throws SQLException {
106         return createDataSourceWithoutRules(governanceConfig);
107     }
108     
109     @Override
110     public final void setEnvironment(final Environment environment) {
111         dataSourceMap.putAll(DataSourceMapSetter.getDataSourceMap(environment));
112     }
113     
114     private DataSource createDataSourceWithRules(final List<RuleConfiguration> ruleConfigs, final GovernanceConfiguration governanceConfig) throws SQLException {
115         return new GovernanceShardingSphereDataSource(dataSourceMap, ruleConfigs, root.getProps(), governanceConfig);
116     }
117     
118     private DataSource createDataSourceWithoutRules(final GovernanceConfiguration governanceConfig) throws SQLException {
119         return new GovernanceShardingSphereDataSource(governanceConfig);
120     }
121 }
View Code

如果是加了@***Condition的,会做逻辑配置逻辑检查

public final class ReadwriteSplittingSpringBootCondition extends SpringBootCondition {
    
    private static final String PREFIX = "spring.shardingsphere.rules.readwrite-splitting";
    
    @Override
    public ConditionOutcome getMatchOutcome(final ConditionContext conditionContext, final AnnotatedTypeMetadata annotatedTypeMetadata) {
        return PropertyUtil.containPropertyPrefix(conditionContext.getEnvironment(), PREFIX)
                ? ConditionOutcome.match() : ConditionOutcome.noMatch("Can't find ShardingSphere readwrite-splitting rule configuration in local file.");
    }
}
View Code

通过反射判断

    @SneakyThrows(ReflectiveOperationException.class)
    private static Object v2(final Environment environment, final String prefix, final Class<?> targetClass) {
        Class<?> binderClass = Class.forName("org.springframework.boot.context.properties.bind.Binder");
        Method getMethod = binderClass.getDeclaredMethod("get", Environment.class);
        Method bindMethod = binderClass.getDeclaredMethod("bind", String.class, Class.class);
        Object binderObject = getMethod.invoke(null, environment);
        String prefixParam = prefix.endsWith(".") ? prefix.substring(0, prefix.length() - 1) : prefix;
        Object bindResultObject = bindMethod.invoke(binderObject, prefixParam, targetClass);
        Method resultGetMethod = bindResultObject.getClass().getDeclaredMethod("get");
        return resultGetMethod.invoke(bindResultObject);
    }

最终通过按照转换后的配置对象构建对应的服务资源对象

--------------------------------------------------------------------------

注册中心目前支持zookeeper/etcd

服务加载方式全部是基于ServiceLoader,有些是默认在源码包里加载的,比如org.apache.shardingsphere.governance.repository.zookeeper.CuratorZookeeperRepository就通过下图文件启动,也有些可以自己实现然后添加的

加载方式

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class RegistryCenterRepositoryFactory {
    
    static {
        ShardingSphereServiceLoader.register(RegistryCenterRepository.class);
    }
    
    /**
     * Create new instance of Registry center repository.
     * 
     * @param config governance configuration
     * @return new instance of Registry center repository
     */
    public static RegistryCenterRepository newInstance(final GovernanceConfiguration config) {
        RegistryCenterConfiguration registryCenterConfig = config.getRegistryCenterConfiguration();
        Preconditions.checkNotNull(registryCenterConfig, "Registry center configuration cannot be null.");
        RegistryCenterRepository result = TypedSPIRegistry.getRegisteredService(RegistryCenterRepository.class, registryCenterConfig.getType(), registryCenterConfig.getProps());
        result.init(config.getName(), registryCenterConfig);
        return result;
    }
}

 

 注册中心需要实现的逻辑也很简单,看图就知道了

 

整个注册中心基于临时节点跟session生命周期相同的特性实现实例和数据库的注册发现,基于监听机制实现配置变更的发现通知

通过google eventbus事件机制传递到观察者实现配置动态化

zk治理节点

posted on 2021-07-09 16:19  it_worker365  阅读(122)  评论(0编辑  收藏  举报