Implement multi-tenant architecture based on SpringBoot: support application multi-tenant deployment and management

1. Overview

1 What is a multi-tenant architecture?

Multi-tenant architecture refers to supporting simultaneous access by multiple tenants (Tenant) in an application, each tenant has independent resources and data, and is completely isolated from each other. In layman’s terms, multi-tenancy is to “split” an application into multiple independent instances according to customer needs, and each instance does not interfere with each other.

2 Advantages of multi-tenant architecture

  • Better meet the individual needs of different tenants.

  • It can reduce operation and maintenance costs and reduce investment in infrastructure such as hardware and networks.

  • Save development costs, and quickly launch new tenant instances by reusing code.

  • The scalability and scalability of the system are enhanced, horizontal expansion is supported, and the data and resources of each tenant can be managed and controlled.

3 Technology selection for implementing multi-tenant architecture

What is not the most important thing for realizing multi-tenant architecture technology is the correct architecture idea. But choosing the right technology can lead to a faster multi-tenant architecture.

2. Design ideas

1 Architecture selection

It is recommended to use Spring Boot and Spring Cloud to develop multi-tenant applications based on Java. Spring Boot can quickly build applications and provide many mature plug-ins. Spring Cloud provides many tools and components to implement microservice architecture.

1.1 Spring Boot

Using Spring Boot can simplify the project construction process and automatically configure many common third-party libraries and components, reducing the workload of developers.

@RestController
public class TenantController {

    @GetMapping("/hello")
    public String hello(@RequestHeader("tenant-id") String tenantId) {
        return "Hello, " + tenantId;
    }
}

1.2 Spring Cloud

Spring Cloud will be more useful when architecting multi-tenant systems. Spring Cloud provides some mature solutions, such as Eureka, Zookeeper, Consul, etc., to realize microservice functions such as service discovery and load balancing.

2 Database Design

In a multi-tenant environment the database must store data separately for each tenant and ensure data isolation. We usually use the following two methods to achieve:

  • Multiple tenants share the same database, and each table contains a tenant_id column to distinguish data from different tenants.

  • Create separate databases for each tenant, each database has the same table structure, but the data is isolated from each other.

3 Application multi-tenant deployment

In order to achieve multi-tenancy in application deployment, we need to consider the following two issues.

3.1 Application isolation

In a multi-tenant environment, different tenants need to access different resources, so application isolation is required. This can be achieved by building separate containers or virtual machines, using namespaces, etc. Docker is a very popular technology for isolating containers.

3.2 Application Configuration

Since each tenant has its own configuration requirements, it is necessary to set application configuration information for each tenant, such as port number, SSL certificate, and so on. These configurations can be stored in a database or in a cloud configuration center.

4 Tenant Management

In a multi-tenant system, it is necessary to be able to manage the data and resources of different tenants, and at the same time, it is necessary to assign corresponding permissions to each tenant. Solutions usually include the following two parts.

4.1 Tenant information maintenance

The maintenance of tenant information includes operations such as adding, modifying, deleting, and querying. It is required to be able to quickly find the corresponding tenant information based on the tenant name or tenant ID.

CREATE TABLE tenant (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL UNIQUE,
    description VARCHAR(255),
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

4.2 Tenant permission control

In a multi-tenant application, access to system resources must be set separately for each tenant. For example, A tenant and B tenant cannot access each other’s data.

@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http. authorizeRequests()
                .antMatchers("/api/tenant/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth. userDetailsService(userDetailsService())
                .passwordEncoder(new BCryptPasswordEncoder())
                .and()
                .inMemoryAuthentication()
                .withUser("admin")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("ADMIN");
    }
}

3. Technical implementation

1 Multi-tenancy implementation in Spring Boot

In Spring Boot, multi-tenancy mechanism can be realized through multiple data sources and dynamic routing.

1.1 Implementation of multiple data sources

Multiple data sources refer to configuring different data sources for different tenants, so that each tenant can access its own independent data. The specific implementation method is as follows:

@Configuration
public class DataSourceConfig {
    @Bean(name = "dataSourceA")
    @ConfigurationProperties(prefix = "spring.datasource.a")
    public DataSource dataSourceA() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dataSourceB")
    @ConfigurationProperties(prefix = "spring.datasource.b")
    public DataSource dataSourceB() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dataSourceC")
    @ConfigurationProperties(prefix = "spring.datasource.c")
    public DataSource dataSourceC() {
        return DataSourceBuilder.create().build();
    }
}

The above code is configured with three data sources corresponding to three tenants. Then when using, you can use annotations to mark the data sources that need to be connected.

@Service
public class ProductService {
    @Autowired
    @Qualifier("dataSourceA")
    private DataSource dataSource;

    //...
}

1.2 Dynamic routing implementation

Dynamic routing refers to dynamically switching to the data source of the corresponding tenant according to the requested URL or parameters. The specific implementation is as follows:

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return TenantContextHolder. getTenantId();
    }
}

@Configuration
public class DataSourceConfig {
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().type(DynamicDataSource.class).build();
    }
}

The above is the core code of dynamic routing. DynamicDataSource inherits from AbstractRoutingDataSource, dynamically obtains the tenant ID through the determineCurrentLookupKey() method, and then switches to the corresponding data source .

2 Multi-tenancy implementation in Spring Cloud

In Spring Cloud, the multi-tenant mechanism can be realized through service registration and discovery, configuration center, load balancing, etc.

2.1 Service Registration and Discovery

Use Eureka in Spring Cloud to implement service registration and discovery. Each tenant’s service is registered with a different application name in the registry, and the client can access the service of the corresponding tenant through the service name.

2.2 Configuration Center

Use Spring Cloud Config as the configuration center. Configuration files are distinguished by tenant ID, and the client obtains configuration information by reading the configuration file of the corresponding tenant.

2.3 Load balancing

Use Spring Cloud Ribbon as a load balancer. Select the service instance corresponding to the tenant according to the requested URL or parameters to forward the request.

2.4 API

The multi-tenancy mechanism is implemented at the API gateway level to determine the tenant according to the URL or parameters of the request, and forward it to the service instance of the corresponding tenant.

4. Application scenarios

1 Private cloud environment

The private cloud environment refers to the cloud environment built by the enterprise itself, which does not provide external services and is mainly used for data storage, management, sharing and security control within the enterprise. Compared with the public cloud, the advantage of the private cloud is that it can better protect the core data of the enterprise, and it can also meet the requirements of the enterprise for data security and controllability.

2 Public cloud environment

The public cloud environment refers to the cloud environment built by cloud service providers and provides external services. Users can purchase corresponding cloud services according to their needs, such as cloud storage, cloud computing, cloud database, etc. Compared with private clouds, public clouds have the advantages of low cost, elastic scalability, and global deployment, which can better meet the needs of rapid development of enterprises.

3 Enterprise applications

Enterprise-level applications refer to applications for enterprise customers, mainly including a series of application systems such as ERP, CRM, and OA. This type of application is characterized by powerful functions, complex processes, and a large amount of data, and needs to meet the requirements of high efficiency, high reliability, high security, and easy maintenance of the enterprise. In the cloud computing environment, enterprises can deploy these applications on private clouds or public clouds, which reduces the investment and maintenance costs of hardware equipment and improves management efficiency.

5. Implementation steps

1 Build Spring Boot and Spring Cloud environment

First, the following dependencies need to be introduced into the Maven project:

<!-- Spring Boot -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Cloud -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>2020.0.3</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

Then you need to configure the corresponding parameters in application.yml, as follows:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/appdb?useUnicode=true &characterEncoding=utf-8 &serverTimezone=Asia/Shanghai
    username: root
    password: 123456

mybatis:
  type-aliases-package: com.example.demo.model
  mapper-locations: classpath:mapper/*.xml

server:
  port: 8080

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

management:
  endpoints:
    web:
      exposure:
        include: "*"

Among them, datasource.url is the URL of the database connection, username and password are the account number and password of the database connection; server.port is the port started by the Spring Boot application; eureka .client.serviceUrl.defaultZone is the URL of the Eureka service registry.

2 Modify the database design

The database will then need to be modified accordingly to support multi-tenant deployments. Specifically, we need to add a tenant-related field in the database to distinguish different tenants in the application.

3 Realize application multi-tenant deployment

Then you need to implement the multi-tenant deployment function of the application in the code. Specifically, we need to instantiate the corresponding Spring Bean for each tenant, and route the request to the corresponding Bean for processing according to the tenant ID.

Here is an example of a simple implementation:

@Configuration
public class MultiTenantConfig {
 
    // Provide the data source corresponding to the tenant
    @Bean
    public DataSource dataSource(TenantRegistry tenantRegistry) {
        return new TenantAwareDataSource(tenantRegistry);
    }
 
    // multi-tenant Session factory
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        return sessionFactory. getObject();
    }
 
    // Dynamically switch tenants
    @Bean
    public MultiTenantInterceptor multiTenantInterceptor(TenantResolver tenantResolver) {
        MultiTenantInterceptor interceptor = new MultiTenantInterceptor();
        interceptor.setTenantResolver(tenantResolver);
        return interceptor;
    }
 
    // register interceptor
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(multiTenantInterceptor());
    }
 
    // Register tenant information
    @Bean
    public TenantRegistry tenantRegistry() {
        return new TenantRegistryImpl();
    }
     
    // parse the tenant ID
    @Bean
    public TenantResolver tenantResolver() {
        return new HeaderTenantResolver();
    }
 
}

Among them, MultiTenantConfig is the core configuration class for multi-tenant deployment, which provides functions such as corresponding tenant data source, multi-tenant Session factory, and dynamic switching of tenants.

4 Realize tenant management

Finally, a tenant management function needs to be implemented to manage different tenants in the system. Specifically, we can use Spring Cloud’s service registration and discovery component Eureka to register each tenant’s instance and perform corresponding operations in the management interface. In addition, we also need to provide an independent database for each tenant to ensure data isolation.

6. Summary review

This article details how to use Spring Boot and Spring Cloud to implement an application that supports multi-tenant deployment. It mainly includes building Spring Boot and Spring Cloud environments, modifying database design, implementing multi-tenant deployment of applications, and implementing tenant management.

Application scenarios mainly include SaaS applications, multi-tenant cloud services, etc. The advantages and disadvantages are mainly reflected in improving the scalability and maintainability of the application, but also increasing the complexity of deployment and management. Future improvement directions can consider further improving the automation of multi-tenant management to reduce manual intervention and error rates.

Source: blog.csdn.net/u010349629/article/

details/130737253

Back-end exclusive technology group

Build a high-quality technical exchange community, welcome to join the group who are engaged in programming development and technical recruitment HR, and also welcome everyone to share your company’s referral information, help each other, and make progress together!

Civilized speech, mainly focusing on communication technology, job referral, industry discussion

Advertisers do not enter, do not trust private chats, to prevent being cheated

f96658ec80f707413a8a8e28d06cd5e7.jpeg

Add me as a friend and pull you into the group
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Java skill treeHomepageOverview 118926 people are studying systematically