ShardingSphere parse the source microkernel architecture (under)

By previous introduction, we have a certain understanding of microkernel architecture and SPI mode mechanism JDK offer. On this basis, today we have to achieve in-depth analysis of the principles ShardingSphere used in the microkernel architecture.

Microkernel architecture underlying implementation mechanisms 1. ShardingSphere in

We found that, in the root directory ShardingSphere source, there is a separate project shardingsphere-spi. Clearly, from the naming point of view, this project should be included in the relevant code ShardingSphere implement the SPI. Our quick overview of the project and found that there is only one interface definition and two tools.

Let's look at this interface definition TypeBasedSPI, as follows:

public interface TypeBasedSPI {   

    String getType();   

    Properties getProperties();   

    void setProperties(Properties properties);

}

From the positioning speaking, this interface should be in ShardingSphere a top level interface, shown in its class layer structure, it is clear that we mentioned in a distributed ShardingKeyGenerator for generating primary key data for desensitization ShardingEncryptor, ShardingTransactionManager and registry interfaces RegistryCenter for distributed transactions for database management inherit this interface:

Then, we will look NewInstanceServiceLoader class, from naming point of view, we can easily imagine that this kind of act like one kind ServiceLoader, for loading new target object instance. NewInstanceServiceLoader code as follows:

public final class NewInstanceServiceLoader {   

    private static final Map<Class, Collection<Class<?>>> SERVICE_MAP = new HashMap<>();   

    // By ServiceLoader obtain new SPI service instance and register SERVICE_MAP in   

    public static <T> void register(final Class<T> service) {

        for (T each : ServiceLoader.load(service)) {

            registerServiceClass(service, each);

        }

    }   

    @SuppressWarnings("unchecked")

    private static <T> void registerServiceClass(final Class<T> service, final T instance) {

        Collection<Class<?>> serviceClasses = SERVICE_MAP.get(service);

        if (null == serviceClasses) {

            serviceClasses = new LinkedHashSet<>();

        }

        serviceClasses.add(instance.getClass());

        SERVICE_MAP.put(service, serviceClasses);

    }   

    @SneakyThrows

    @SuppressWarnings("unchecked")

    public static <T> Collection<T> newServiceInstances(final Class<T> service) {

        Collection<T> result = new LinkedList<>();

        if (null == SERVICE_MAP.get(service)) {

            return result;

        }

        for (Class<?> each : SERVICE_MAP.get(service)) {

            result.add((T) each.newInstance());

        }

        return result;

    }

}

Here first to see the familiar ServiceLoader.load (service) approach, which is an application of JDK ServiceLoader tools on one in this article. At the same time, we note that ShardingSphere use the previous example-many relationship is defined to hold the class and the class of a HashMap, you may think that this is a method for increasing the efficiency of accessing cache mechanism.

Finally, we look at TypeBasedSPIServiceLoader implementation depends on such NewInstanceServiceLoader class described earlier, using the following method NewInstanceServiceLoader obtain a list of instance of the class, and the passed as filter type:

    // Use NewInstanceServiceLoader obtain a list of instance of the class, and according to the type as filter

    private Collection<T> loadTypeBasedServices(final String type) {

        return Collections2.filter(NewInstanceServiceLoader.newServiceInstances(classType), new Predicate<T>() {           

            @Override

            public boolean apply(final T input) {

                return type.equalsIgnoreCase(input.getType());

            }

        });

    }

TypeBasedSPIServiceLoader the external interface to the service exposed as shown, disposed corresponding property acquired by the service instance loadTypeBasedServices method then returns:

// By based on the type SPI to create an instance

    public final T newService(final String type, final Properties props) {

        Collection<T> typeBasedServices = loadTypeBasedServices(type);

        if (typeBasedServices.isEmpty()) {

            throw new RuntimeException(String.format("Invalid `%s` SPI type `%s`.", classType.getName(), type));

        }

        T result = typeBasedServices.iterator().next();

        result.setProperties(props);

        return result;

}

Meanwhile, TypeBasedSPIServiceLoader also a need to introduce outside exposure type newService method of using a tool loadFirstTypeBasedService method to obtain a first service instance, the relevant code is as follows:

// based on the type of default by SPI to create an instance

    public final T newService() {

        T result = loadFirstTypeBasedService();

        result.setProperties(new Properties());

        return result;

    }

    private T loadFirstTypeBasedService() {

        Collection<T> instances = NewInstanceServiceLoader.newServiceInstances(classType);

        if (instances.isEmpty()) {

            throw new RuntimeException(String.format("Invalid `%s` SPI, no implementation class load from SPI.", classType.getName()));

        }

        return instances.iterator().next();

    }

In this way, the content ShardingSphere shardingsphere-spi project on the finished presentation. This section is equivalent underlying implementation mechanisms microkernel architecture, here we come to a typical application scenarios look at the specific usage.

2. Application of microkernel architecture in the ShardingSphere

We recall "ShardingSphere source parsing of SQL parsing engine (two)" content, mentioned specific SQLParser generation responsible SQLParserFactory, SQLParserFactory defined as follows:

public final class SQLParserFactory {   

    public static SQLParser newInstance(final String databaseTypeName, final String sql) {

    // by SPI loads all extension mechanism

    for (SQLParserEntry each : NewInstanceServiceLoader.newServiceInstances(SQLParserEntry.class)) {

       

    }

It can be seen here and did not use TypeBasedSPIServiceLoader described earlier to load an instance, but a more direct use of the underlying NewInstanceServiceLoader.

The interface incorporated SQLParserEntry located org.apache.shardingsphere.sql.parser.spi packet shardingsphere-sql-parser-spi works in. Obviously, from the point of view of the package name, the interface is an SPI interface, defined as follows:

public interface SQLParserEntry {   

    String getDatabaseTypeName();   

    Class<? extends Lexer> getLexerClass();   

    Class<? extends SQLParser> getParserClass();

}

There are a number of interfaces implemented SQLParserEntry which tier structure is shown below:

We first look for Mysql code works shardingsphere-sql-parser-mysql, we found under the META-INF / services directory a org.apache.shardingsphere.sql.parser.spi.SQLParserEntry file as follows:

Here you can see the point org.apache.shardingsphere.sql.parser.MySQLParserEntry class. Then we came to the Oracle code works shardingsphere-sql-parser-oracle, likewise found a org.apache.shardingsphere.sql.parser.spi.SQLParserEntry file in the META-INF / services directory, as follows:

Obviously, this should point org.apache.shardingsphere.sql.parser.OracleParserEntry class. In this manner, the system will dynamically loaded at runtime according SPI class path.

We note SQLParserEntry interface class layer structure does not actually use the TypeBasedSPI, but entirely based SPI mechanism JDK native. Next, we come to one example TypeBasedSPI use, say ConfigCenter (located in org.apache.shardingsphere.orchestration.config.api package), the interface of the statement is as follows:

public interface ConfigCenter extends TypeBasedSPI

See ConfigCenter TypeBasedSPI interface extends the interface, but there is also achieved in a number of ConfigCenter ShardingSphere interface, it tier structure is shown below:

To ApolloConfigCenter for example, we look to it to use, we find ConfigCenterServiceLoader class sharding-orchestration-core engineering org.apache.shardingsphere.orchestration.internal.configcenter, the class extends the class TypeBasedSPIServiceLoader mentioned earlier:

public final class ConfigCenterServiceLoader extends TypeBasedSPIServiceLoader<ConfigCenter> {   

    static {

        NewInstanceServiceLoader.register(ConfigCenter.class);

    }   

    public ConfigCenterServiceLoader() {

        super(ConfigCenter.class);

    }   

    // based SPI load ConfigCenter

    public ConfigCenter load(final ConfigCenterConfiguration configCenterConfig) {

        Preconditions.checkNotNull(configCenterConfig, "Config center configuration cannot be null.");

        ConfigCenter result = newService(configCenterConfig.getType(), configCenterConfig.getProperties());

        result.init(configCenterConfig);

        return result;

    }

}

First, ConfigCenterServiceLoader class by NewInstanceServiceLoader.register (ConfigCenter.class) statement all ConfigCenter registered into the system, this step will ConfigCenter all instances by the JDK tools ServiceLoader load the class path.

Then, we can see above the load method, based on the type created by newService SPI instances of the parent class TypeBasedSPIServiceLoader.

Not difficult to imagine, there should be a configuration file named org.apache.shardingsphere.orchestration.config.api.ConfigCenter at sharding-orchestration-config-apollo project META-INF / services directory, point ApolloConfigCenter class, as follows :

Other ConfigCenter achieve is the same, you can access the SPI configuration file sharding-orchestration-config-zookeeper-curator and other projects of their own.

At this point, we have a comprehensive understanding of ShardingSphere the microkernel architecture. Indeed, compared to other frame Dubbo achieve ShardingSphere the microkernel architecture is not complicated, the package is of substantially the JDK SPI mechanism.

I can focus more public numbers: Programmer's transition to an architect.

发布了94 篇原创文章 · 获赞 9 · 访问量 11万+

Guess you like

Origin blog.csdn.net/lantian08251/article/details/104511053