Flexibility Through Modularity: Alibaba’s JarsLink Modular Development Framework
    2018-04-03    Fang Tengfei(方腾飞)

Now open sourced! Find more about it here.

What are development frameworks?

Development frameworks have become an essential part of software and web application development, that include building and deployment standards. They are usually reusable and can be universally applied across applications. Nevertheless, usage has often proved troublesome and has been a drain on resources.

Alibaba’s new JarsLink modular framework has been developed to overcome these issues and has is currently being applied and assessed in real-world applications. Let’s move on to look at the issues it is overcoming, its specific functions and features, and real-world application scenarios.

Common limitations of development frameworks

The requirements of development frameworks are often divided into either too many or too few applications, which can cause problems. Too many applications mean that many applications are published each time, resulting in high maintenance costs. Too few applications cause difficulty in the offline withdrawal of useless functions, leading to high division costs.

Inability to isolate faults is also a major constraint. When multiple developers participate in the development of a system at the same time, one person modifying function A may affect function B, resulting in a fault. Multi-branch development also causes conflicts, where the consolidation after multi-branch development results in function misalignment.

In terms of maintenance, a change in the core code or an upgrade of the underlying JAR file needs to regress to the entire system to avoid framework instability. Furthermore, the upgrade and migration costs are high, specifically the middleware upgrade for each application.

Due to these constraints and limitations, there is a real need for a more flexible and effective approach to framework development.

Designing a new development framework

To overcome the above constraints, the Alibaba tech team looked into how development frameworks could be designed differently. They reasoned that the following features and functions could be incorporated to improve isolation and accessibility and make the framework more dynamic:

  • Class isolation

Class isolation can be achieved by using a separate ClassLoader for the loading of each module's class, where each module can rely on different versions of a same framework.

  • Instance isolation

Instance isolation can be achieved by having the framework create a separate Spring context for each module to load the bean in the module. Failure to instantiate then does not affect other modules.

  • Resource isolation

Using separate CPU and memory resources for each module means that in the future, resource isolation between modules can be supported.

  • Dynamic publishing

This means modules can be dynamically loaded into the system at runtime, without rebooting and the publishing of system newly added functions. The framework must support breaking through the parental delegation mechanism. Classes that have been loaded by the parent class loader are loaded at runtime, enabling the module upgrade dependence package to not require the system to publish.

  • Dynamic unloading

This means that modules can be dynamically unloaded cleanly at run time, enabling unneeded functions to go offline quickly.

  • Accessible, versatile, and flexible API

This would be provided for interaction between the system and modules.

 

Besides identifying potential features and functions for development frameworks, a different development approach was also identified by Alibaba.

A modular development approach

A modular development method can bring a number of advantages over a traditional application development method. The two methods are compared in the figure below.

Comparison of the application and modular development methods for development frameworks.

 

In the modular development method, an application consists of multiple modules, which can be detached and assembled. These modules can be quickly migrated and deployed in multiple systems, and adding or modifying functions is done on a module-by-module basis. Modular development enables isolation between modules, thereby also achieving fault isolation. This is not possible in the application development method.

The potential conflicting codes associated with the application development method cannot occur with the modular approach as a module corresponds to a branch. Furthermore, modules are deployed to applications at run time, so failures can be quickly fixed and publishing efficiency is improved.

With multi-version deployment, developers can deploy both old and new versions of a module at run time to perform AB TEST. Also, resource consumption is reduced due to the reduction in the number of applications and machines through module deployment.

Based on a deep understanding of what was missing in available development frameworks and realizing the importance of the flexibility and efficiency of the modular development method, the Alibaba tech team propose the JarsLink modular development framework.

JarsLink: Alibaba’s modular development framework

Alibaba’s JarsLink framework is based on a modular development method and the outline of which is illustrated below.

Outline of the JarsLink development framework.

 

The main components of the JarsLink framework are:

  • ModuleRefresh

An entry class that is responsible for periodically scanning local and in-memory modules for changes, and if so, updating the module.

  • ModuleLoader

The module loading engine that is responsible for module loading and unloading.

  • ModuleManager

The module manager that is responsible for registering, removing, finding modules and executing actions at run time.

  • Module

A module has multiple actions.

  • Action

The executor in the module.

 

JarsLink features and functions

Module loading

JarsLink creates a new URLClassLoader for each module for loading JAR. It also supports breaking through the parental delegation mechanism setting that the overridePackages are loaded by subclass loaders and not taking priority to use packages that have been loaded by the parent class loader.

Module unloading

Unloading a module can only occur when certain conditions are met. Specifically, the instance object, classes, and class loaders cannot be referenced in the module. Therefore, the instances, classes, and class loaders need to be unloaded. The sequence of unloading the entire module is shown below.

 

JarsLink module unloading sequence.

Different functions are performed at each step of the sequence:

  • Close resources

Close the HTTP connection pool or thread pool.

  • Close IOC Containers

Call the applicationContext.close() method to close IOC Containers.

  • Remove class loaders

Remove the reference of the module.

  • Unload JVM Tenants (in development)

Unload the JVM tenants used by this module to free up resources.

 

Isolation between modules

To prevent modules influencing each other, a key attribute of modular development is module isolation. There are three levels of isolation between modules:

  • Class isolation

Create a class loader for each module to implement class isolation.

  • Instance isolation

Create a new IOC container for each module to load the bean in the module.

  • Resource isolation

Only use the specified CPU and memory for each module.

 

The relationships between these are illustrated below.

 

Module isolation in the JarsLink framework.

 

Currently, class isolation and instance isolation have been realized for JarsLink. Resource isolation is still in the planning stage and will potentially be solved by introducing ALIJVM multi-tenancy.

 

Communications between modules

The main methods to facilitate communications between modules include:

  • Local calls

This required that the module class loaders and IOC containers have a parent-child relationship. Currently, JarsLink's doAction uses this communication method.

  • RPC calls

This is used for cross-JVM module calls using SOFA 4 dynamic APIs to publish and reference TR services in the modules.

  • Deep cloning/reflection

Deeply clone and reflect the input parameters of other modules to achieve the call.

 

An illustration of these communications is outlined below.

 

Module communication in the JarsLink Framework.

 

Class loading mechanism

The OSGi class loading mechanism uses a mesh structure. Each module uses Export-Package to declare which classes it will give to others and uses Import-Package to declare which classes it wants to use. JarsLink adopts flat management. Each module has a common parent class. The parent class loader is used to load the ModuleLoader class. If it is a SOFA application, the parent loader of the module is KernelAceClassLoader.

The relationship of class loaders is as follows:


Classes that are needed by all modules can be loaded through the Application ClassLoader.

JarsLink application scenarios

One of the major possible applications of JarsLink is in data management centers. These systems usually collect data from various system structures, with such interfaces as RPC, HTTP, etc., and various sources that need docking and developing. Frequent modification and publishing of the code is required due to a poor quality of data.

In this scenario, modular development can be applied to achieve the docking of one data source with one module, so that releasing new data sources online only requires adding new modules. Moreover, modifying bugs only requires the modification of certain modules which can then be quickly put back online.

Another possible application of JarsLink is in the background management systems of Internet applications. For instance, customer service inquiries usually involve the function of checking background data to troubleshoot system bugs and for operation departments to push operational activities. The publishing frequency of these functions is greater than the core system and if they are put in the core system, the core system’s stability is affected. Therefore, systems must have background functions.

This, however, introduces the problem that many development activities will use this background system, which produces many branches, causing code conflicts and resulting in that business B is affected by the bugs of business A. Therefore, if each business line corresponds to one module and each module uses a separate branch for development, the isolated development can be carried out and the development speed can be increased. After development, the module can be loaded into the system at run time.

Microservices integration tests utilize fat JARs, and if dozens of microservices are tested, many processes need to be started and many debug ports are required. By using the JarsLink framework to consolidate the fat JARs and route the request to other JARs, the debug testing can be carried out with only one process being started.

JarsLink applied in real-world scenarios

Currently the Microfinance Division of Alibaba’s Ant Financial uses the JarsLink framework on several of its systems, including dozens of modules. Results of this application are still being collected and analyzed and will be reported on in the not too distant future.

If JarsLink performs as expected, Alibaba plans to make the framework open source in the hope that it can be applied in a diverse range of contexts as a flexible and efficient approach to application development.

Open Source
Alibaba has made JarsLink open source. Find more about it here.

(Original article by Fang Tengfei方腾飞)

.      .      .

 
Alibaba Tech
First hand, detailed, and in-depth information about Alibaba’s latest technology → Search “Alibaba Tech” on Facebook