Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the microkernel architecture?

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "what is the microkernel architecture". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what is the microkernel architecture".

What is the microkernel architecture?

Microkernel is a typical architecture pattern, which is different from ordinary design patterns. Architecture pattern is a high-level pattern, which is used to describe system-level structural composition, interrelationships and related constraints. Micro-kernel architecture is widely used in open source frameworks, such as ShardingSphere and Dubbo, which implement their own micro-kernel architecture. So, before introducing what the microkernel architecture is, it is necessary to explain why these open source frameworks use the microkernel architecture.

Why use the microkernel architecture?

The essence of the micro-kernel architecture is to improve the scalability of the system. Scalability refers to the flexibility of the system when it goes through inevitable changes and the ability to balance the cost of providing such flexibility. In other words, when adding new business to the system, we do not need to change the original components, but only need to seal the new business in a new component to complete the upgrade of the overall business. We think that such a system has good scalability.

As far as architecture design is concerned, expansibility is the eternal topic of software design. In order to achieve system scalability, one idea is to provide a pluggable mechanism to deal with the changes. When an existing component in the system does not meet the requirements, we can implement a new component to replace it, and the whole process should be imperceptible to the operation of the system. We can also complete the replacement of new and old components at any time as needed.

For example, the distributed primary key function provided in ShardingSphere, there may be many kinds of distributed primary key implementation, and the embodiment of expansibility at this point is that we can use any new distributed primary key implementation to replace the original implementation, without relying on the business code of the distributed primary key to make any changes.

The micro-kernel architecture mode provides architecture design support for this idea of scalability, and ShardingSphere achieves a high degree of scalability based on the micro-kernel architecture. Before introducing how to implement the microkernel architecture, we first briefly describe the specific structure and basic principles of the microkernel architecture.

What is the microkernel architecture?

In terms of composition, the microkernel architecture consists of two components: kernel system and plug-in. The kernel system here usually provides the minimum set of functions needed for the system to run, while plug-ins are independent components that contain custom business codes to enhance or extend additional business capabilities to the kernel system. In ShardingSphere, the previously mentioned distributed primary key is the plug-in, while the runtime environment of ShardingSphere makes up the kernel system.

So what exactly does the plug-in here refer to? This requires us to clarify two concepts, one of which is the frequently mentioned API, which is the interface for the system to be exposed to the outside world. Another concept is SPI (Service Provider Interface, service provider interface), which is the extension point of the plug-in itself. In terms of the relationship between the two, API is for business developers, while SPI is for framework developers, both of which make up ShardingSphere itself.

The pluggable implementation mechanism is simple to say, but not easy to do. We need to consider two aspects. On the one hand, we need to comb through the changes in the system and abstract them into multiple SPI extension points. On the other hand, when we implement these SPI extension points, we need to build a concrete implementation that supports this pluggable mechanism to provide a SPI runtime environment.

How to implement the microkernel architecture?

In fact, JDK has provided us with a way to implement a micro-kernel architecture, which is JDK SPI. This implementation method puts forward some development and configuration specifications for how to design and implement SPI. ShardingSphere and Dubbo use this specification, but they are enhanced and optimized on this basis. So to understand how to implement a microkernel architecture, let's take a look at how JDK SPI works.

JDK SPI

SPI (Service Provider Interface) is mainly a technology used by framework developers. For example, when using Java language to access database, we will use java.sql.Driver interface. Different database products have different underlying protocols and provide different java.sql.Driver implementations. When developing java.sql.Driver interface, developers do not know which database users will eventually use. In this case, we can use Java SPI mechanism to find a specific implementation for java.sql.Driver interface in the actual operation process.

Let's demonstrate the use of JDK SPI with a simple example:

First, we define an interface for generating id keys, which is used to simulate id generation.

Public interface IdGenerator {/ * generate id * @ return * / String generateId ();}

Then create two interface implementation classes to simulate the generation of uuid and sequence id respectively

Public class UuidGenerator implements IdGenerator {@ Override public String generateId () {return UUID.randomUUID () .toString ();}} public class SequenceIdGenerator implements IdGenerator {private final AtomicLong atomicId = new AtomicLong (100L); @ Override public String generateId () {long leastId = this.atomicId.incrementAndGet (); return String.valueOf (leastId);}}

Add a file named com.github.jianzh6.spi.IdGenerator under the resources/META-INF/services directory of the project, which is the configuration file that JDK SPI needs to read, as follows:

Com.github.jianzh6.spi.impl.UuidGenerator com.github.jianzh6.spi.impl.SequenceIdGenerator

Create the main method, load the configuration file above, create an instance of all the IdGenerator interface implementations, and execute the method that generates the id.

Public class GeneratorMain {public static void main (String [] args) {ServiceLoader serviceLoader = ServiceLoader.load (IdGenerator.class); Iterator iterator = serviceLoader.iterator (); while (iterator.hasNext ()) {IdGenerator generator = iterator.next (); String id = generator.generateId (); System.out.println (generator.getClass (). GetName () + "> id:" + id) }

The implementation results are as follows:

JDK SPI source code analysis

From the above example, we can see that the entry method of JDK SPI is the ServiceLoader.load () method, in which we first try to get the currently used ClassLoader, and then call the reload () method, as shown in the following figure:

Calling relationship

In the reload () method, you first clean up the providers cache (a collection of LinkedHashMap types), which is used to record the implementation objects created by ServiceLoader, where Key is the full class name of the implementation class and Value is the object of the implementation class. A LazyIterator iterator is then created to read the SPI configuration file and instantiate the implementation class object.

Public void reload () {providers.clear (); lookupIterator = new LazyIterator (service, loader);}

In the previous example, the underlying iterator used in the main () method invokes the ServiceLoader.LazyIterator implementation. The Iterator interface has two key methods: the hasNext () method and the next () method. Here, the next () method in LazyIterator finally calls its nextService () method, and the hasNext () method finally calls the hasNextService () method. Let's take a look at the specific implementation of the hasNextService () method:

Private static final String PREFIX = "META-INF/services/"; Enumeration configs = null; Iterator pending = null; String nextName = null; private boolean hasNextService () {if (nextName! = null) {return true;} if (configs = = null) {try {/ / META-INF/services/com.github.jianzh6.spi.IdGenerator String fullName = PREFIX + service.getName (); if (loader = = null) configs = ClassLoader.getSystemResources (fullName) Else configs = loader.getResources (fullName);} catch (IOException x) {fail (service, "Error locating configuration files", x);}} / / traverse the contents of the configuration file while ((pending = = null) by line SPI) | |! pending.hasNext () {if (! configs.hasMoreElements ()) {return false;} / / parse the configuration file pending = parse (service, configs.nextElement ()) } / / Update the nextName field nextName = pending.next (); return true;}

After parsing the SPI configuration file in the hasNextService () method, take a look at the LazyIterator.nextService () method, which is "responsible for instantiating the implementation class read by the hasNextService () method", where the instantiated object is cached in the providers collection. The core implementation is as follows:

Private S nextService () {String cn = nextName; nextName = null; / / load the class Class c = Class.forName (cn, false, loader) specified in the nextName field; if (! service.isAssignableFrom (c)) {/ / detect type fail (service, "Provider" + cn + "not a subtype");} S p = service.cast (c.newInstance ()) / / create an object of the implementation class providers.put (cn, p); / / add the name of the implementation class and the corresponding instance object to the cache return p;}

This is the underlying implementation of the iterator used in the main () method. Finally, let's take a look at how the iterator obtained using the ServiceLoader.iterator () method in the main () method is implemented, which is an anonymous inner class that relies on the LazyIterator implementation. The core implementation is as follows:

Public Iterator iterator () {return new Iterator () {/ / knownProviders is used to iterate the providers cache Iterator knownProviders = providers.entrySet () .iterator (); public boolean hasNext () {/ / go to query cache first, cache query fails, and then load if (knownProviders.hasNext ()) return true through LazyIterator Return lookupIterator.hasNext ();} public S next () {/ / go to query cache first, cache query failed, and then load if (knownProviders.hasNext ()) return knownProviders.next () .getValue (); return lookupIterator.next () via LazyIterator } / / omit the remove () method};}

Application of JDK SPI in JDBC

After understanding the principle of JDK SPI implementation, let's take a look at how JDBC uses the JDK SPI mechanism to load implementation classes from different database vendors in practice.

Only one java.sql.Driver interface is defined in JDK, and the specific implementation is provided by different database vendors. Here we take the JDBC implementation package provided by MySQL as an example.

In the META-INF/services directory in the mysql-connector-java-*.jar package, there is a java.sql.Driver file with only one line, as follows:

Com.mysql.cj.jdbc.Driver

When using the mysql-connector-java-*.jar package to connect to the MySQL database, we use the following statement to create a database connection:

String url = "jdbc:xxx://xxx:xxx/xxx"; Connection conn = DriverManager.getConnection (url, username, pwd)

"DriverManager is the database driver manager provided by JDK," and the code snippet is as follows:

Static {loadInitialDrivers (); println ("JDBC DriverManager initialized");}

When the getConnection () method is called, the DriverManager class is loaded, parsed and triggered by the Java virtual machine to execute the static code block. In the loadInitialDrivers () method, the class is implemented and instantiated through the java.sql.Driver interface under JDK SPI scan Classpath. The core implementation is as follows:

Private static void loadInitialDrivers () {String drivers = System.getProperty ("jdbc.drivers") / / use JDK SPI mechanism to load all java.sql.Driver implementation classes ServiceLoader loadedDrivers = ServiceLoader.load (Driver.class); Iterator driversIterator = loadedDrivers.iterator (); while (driversIterator.hasNext ()) {driversIterator.next ();} String [] driversList = drivers.split (":") For (String aDriver: driversList) {/ / initialize the Driver implementation class Class.forName (aDriver, true, ClassLoader.getSystemClassLoader ());}}

In the com.mysql.cj.jdbc.Driver implementation class provided by MySQL, there is also a static static code block that creates a com.mysql.cj.jdbc.Driver object and registers it with the DriverManager.registeredDrivers collection (of type CopyOnWriteArrayList), as follows:

Static {java.sql.DriverManager.registerDriver (new Driver ());}

In the getConnection () method, DriverManager gets the corresponding Driver object to create the Connection from the registeredDrivers collection, and the core implementation is as follows:

Private static Connection getConnection (String url, java.util.Properties info, Class caller) throws SQLException {/ / omit try/catch code block and permission handling logic for (DriverInfo aDriver: registeredDrivers) {Connection con = aDriver.driver.connect (url, info); return con }} Thank you for your reading. the above is the content of "what is the microkernel architecture". After the study of this article, I believe you have a deeper understanding of what the microkernel architecture is, and the specific usage needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report