一、概述
1.什么是多租戶架構?
多租戶架構是指在一個應用中支持多個租戶(Tenant)同時訪問,每個租戶擁有獨立的資源和資料,并且彼此之間完全隔離,通俗來說,多租戶就是把一個應用按照客戶的需求“分割”成多個獨立的實體,每個實體互不干擾,
2. 多租戶架構的優勢
- 更好地滿足不同租戶的個性化需求,
- 可以降低運維成本,減少硬體、網路等基礎設施的投入,
- 節約開發成本,通過復用代碼,快速上線新的租戶實體,
- 增強了系統的可擴展性和可伸縮性,支持水平擴展,每個租戶的資料和資源均可管理和控制,
3. 實作多租戶架構的技術選擇
對于實作多租戶架構技術不是最重要的最重要的是正確的架構思路,但是選擇正確的技術可以更快地實作多租戶架構,
二、設計思路
1. 架構選型
基于Java開發多租戶應用推薦使用Spring Boot和Spring Cloud,Spring Boot能快速搭建應用并提供許多成熟的插件,Spring Cloud則提供了許多實作微服務架構的工具和組件,
1.1 Spring Boot
使用Spring Boot可以簡化專案的搭建程序自動配置許多常見的第三方庫和組件,減少了開發人員的作業量,
@RestController
public class TenantController {
@GetMapping("/hello")
public String hello(@RequestHeader("tenant-id") String tenantId) {
return "Hello, " + tenantId;
}
}
1.2 Spring Cloud
在架構多租戶的系統時Spring Cloud會更加有用,Spring Cloud提供了一些成熟的解決方案,如Eureka、Zookeeper、Consul等,以實作服務發現、負載均衡等微服務功能,
2. 資料庫設計
在多租戶環境中資料庫必須為每個租戶分別存盤資料并確保資料隔離,我們通常使用以下兩種方式實作:
- 多個租戶共享相同的資料庫,每個表中都包含tenant_id這一列,用于區分不同租戶的資料,
- 為每個租戶創建單獨的資料庫,每個資料庫內的表結構相同,但資料相互隔離,
3. 應用多租戶部署
為了實作多租戶在應用部署時我們需要考慮以下兩個問題,
3.1 應用隔離
在多租戶環境中不同租戶需要訪問不同的資源,因此需要進行應用隔離,可以通過構建獨立的容器或虛擬機、使用命名空間等方式實作,Docker就是一種非常流行的隔離容器技術,
3.2 應用配置
由于每個租戶都有自己的配置需求因此需要為每個租戶分別設定應用配置資訊,例如埠號、SSL證書等等,這些配置可以存盤在資料庫中,也可以存盤在云配置中心中,
4. 租戶管理
在多租戶系統中需要能夠管理不同租戶的資料和資源,同時需要為每個租戶分配相應的權限,解決方案通常包括以下兩部分,
4.1 租戶資訊維護
租戶資訊的維護包括添加、修改、洗掉、查詢等操作,要求能夠根據租戶名稱或租戶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 租戶權限控制
在多租戶應用中必須為每個租戶分別設定對系統資源的訪問權限,例如,A租戶和B租戶不能訪問彼此的資料,
@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");
}
}
三、技術實作
1. Spring Boot中的多租戶實作
在Spring Boot中可以通過多資料源和動態路由來實作多租戶機制,
Spring Boot 基礎就不介紹了,推薦看這個實戰專案:
https://github.com/javastacks/spring-boot-best-practice
1.1 多資料源實作
多資料源是指為不同的租戶配置不同的資料源,使得每個租戶都可以訪問自己的獨立資料,具體實作方法如下:
@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();
}
}
以上代碼是配置了三個資料源分別對應三個租戶,然后在使用時,可以使用注解標記需要連接的資料源,
@Service
public class ProductService {
@Autowired
@Qualifier("dataSourceA")
private DataSource dataSource;
// ...
}
1.2 動態路由實作
動態路由是指根據請求的URL或引數動態地切換到對應租戶的資料源,具體實作如下:
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();
}
}
以上是動態路由的核心代碼DynamicDataSource繼承自AbstractRoutingDataSource,通過determineCurrentLookupKey()方法動態獲得租戶ID,然后切換到對應的資料源,
2. Spring Cloud中的多租戶實作
在Spring Cloud中可以通過服務注冊與發現、配置中心、負載均衡等方式實作多租戶機制,
2.1 服務注冊與發現
使用Spring Cloud中的Eureka實作服務注冊與發現,每個租戶的服務都在注冊中心以不同的應用名稱進行注冊,客戶端可以通過服務名稱來訪問對應租戶的服務,
2.2 配置中心
使用Spring Cloud Config作為配置中心,組態檔以租戶ID進行區分,客戶端通過讀取對應租戶的組態檔來獲取配置資訊,
2.3 負載均衡
使用Spring Cloud Ribbon作為負載均衡器,根據請求的URL或引數選擇對應租戶的服務實體進行請求轉發,
2.4 API
在API網關層面實作多租戶機制根據請求的URL或引數判斷所屬租戶,并轉發到對應租戶的服務實體,
四、 應用場景
1. 私有云環境
私有云環境指的是由企業自行搭建的云環境,不對外提供服務,主要應用于企業內部的資料存盤、管理、共享和安全控制,相較于公有云,私有云的優點在于可以更好地保護企業核心資料,同時也能夠滿足企業對于資料安全性和可控性的要求,
2. 公有云環境
公有云環境指的是由云服務商搭建并對外提供服務的云環境,用戶可以根據需要購買相應的云服務,如云存盤、云計算、云資料庫等,相較于私有云,公有云的優點在于具有成本低廉、彈性伸縮、全球化部署等特點,能夠更好地滿足企業快速發展的需求,
3. 企業級應用
企業級應用是指面向企業客戶的應用程式,主要包括ERP、CRM、OA等一系列應用系統,這類應用的特點在于功能強大、流程復雜、資料量大,需要滿足企業的高效率、高可靠性、高安全性和易維護性等要求,在云計算環境下,企業可以將這些應用部署在私有云或公有云上,減少了硬體設備的投入和維護成本,提高了管理效率,
五、實作步驟
1. 搭建Spring Boot和Spring Cloud環境
首先需要在Maven專案中引入以下依賴:
<!-- 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>
然后需要在application.yml中配置相應的引數,如下所示:
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: "*"
其中datasource.url為資料庫連接的URL,username和password為資料庫連接的賬號和密碼;server.port為Spring Boot應用啟動的埠;eureka.client.serviceUrl.defaultZone為Eureka服務注冊中心的URL,
Java指南:java-family.cn
2. 修改資料庫設計
接下來需要對資料庫進行相應的修改,以支持多租戶部署,具體來說,我們需要在資料庫中添加一個與租戶相關的欄位,以便在應用中區分不同的租戶,
3. 實作應用多租戶部署
接著需要在代碼中實作應用的多租戶部署功能,具體來說,我們需要為每個租戶實體化對應的Spring Bean,并根據租戶ID將請求路由到相應的Bean中去處理,
以下是一個簡單的實作示例:
@Configuration
public class MultiTenantConfig {
// 提供對應租戶的資料源
@Bean
public DataSource dataSource(TenantRegistry tenantRegistry) {
return new TenantAwareDataSource(tenantRegistry);
}
// 多租戶Session工廠
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
return sessionFactory.getObject();
}
// 動態切換租戶
@Bean
public MultiTenantInterceptor multiTenantInterceptor(TenantResolver tenantResolver) {
MultiTenantInterceptor interceptor = new MultiTenantInterceptor();
interceptor.setTenantResolver(tenantResolver);
return interceptor;
}
// 注冊攔截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(multiTenantInterceptor());
}
// 注冊租戶資訊
@Bean
public TenantRegistry tenantRegistry() {
return new TenantRegistryImpl();
}
// 決議租戶ID
@Bean
public TenantResolver tenantResolver() {
return new HeaderTenantResolver();
}
}
其中MultiTenantConfig是多租戶部署的核心配置類,它提供了對應租戶資料源、多租戶Session工廠、動態切換租戶等功能,
4. 實作租戶管理
最后需要實作一個租戶管理的功能,以便在系統中管理不同的租戶,具體來說,我們可以使用Spring Cloud的服務注冊與發現組件Eureka來注冊每個租戶的實體,并在管理界面中進行相應的操作,另外,我們還需要為每個租戶提供一個獨立的資料庫,以保證資料隔離性,
六、小結回顧
本文詳細介紹了如何使用Spring Boot和Spring Cloud實作一個支持多租戶部署的應用,主要包括搭建Spring Boot和Spring Cloud環境、修改資料庫設計、實作應用多租戶部署、實作租戶管理等方面,
應用場景主要包括SaaS應用、多租戶云服務等,優劣勢主要體現在提升了應用的可擴展性和可維護性,但也增加了部署和管理的復雜度,未來的改進方向可以考慮進一步提升多租戶管理的自動化程度,減少人工干預和錯誤率,
著作權宣告:本文為CSDN博主「格林希爾」的原創文章,遵循CC 4.0 BY-SA著作權協議,轉載請附上原文出處鏈接及本宣告,原文鏈接:https://blog.csdn.net/u010349629/article/details/130737253
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555545.html
標籤:其他
上一篇:Scala高階語法
下一篇:返回列表
