成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我對實現多租戶系統的一點思考

開發 項目管理
目前大部分的企業信息化都是私有化部署,局限于企業的內部網絡,無法實現遠程協同辦公,所以越來越多的 To B 企業逐步轉向 SaaS(Software-as-a-Service,軟件即服務),SaaS 最早是美國Salesforce公司(1999年創立)創造的新軟件服務模式。

[[399862]]

本文轉載自微信公眾號「不止dotNET」,作者不止dotNET。轉載本文請聯系不止dotNET公眾號。

2020年突發的新冠疫情,讓在線協同辦公在疫情期間成為了剛需。我們也從 2020 年的 2月3 日開始在家遠程辦公,直到四月份。協同辦公軟件一下子火爆了起來,釘釘、企業微信、特別是騰訊會議等都在疫情期間表現突出,呈現出井噴式的發展。

目前大部分的企業信息化都是私有化部署,局限于企業的內部網絡,無法實現遠程協同辦公,所以越來越多的 To B 企業逐步轉向 SaaS(Software-as-a-Service,軟件即服務),SaaS 最早是美國Salesforce公司(1999年創立)創造的新軟件服務模式。這家公司的市值在 2019 年已經超過1000億美元,國內現在還處在發展中階段,前景還是十分廣闊的。

要將傳統的私有化部署的軟件重構成支持 SaaS 模式,多租戶是一個邁不過去的坎,首先需要將系統改造成多租戶模式,然后再逐步實現計費、系統監控、用戶行為分析等功能。

我覺得多租戶的設計應該分為三個層面來進行討論,應用、數據庫和中間件。

應用

現在的項目或產品開發幾乎都是前后端分離的開發模式,應用層主要指的是 WebAPI ,WebAPI 的改造有兩種方式:

1、每個租戶部署一套 WebAPI、上層通過域名或 Url 地址的解析進行路由,當有新租戶注冊的時候就動態進行對應的 WebAPI 的部署,這種方式改造成本低,但運維成本高,不建議使用,如果時間緊,可以當過度階段的臨時方案。

2、所有的租戶共用一套 WebAPI ,在 WebAPI 中需要獲取到租戶信息(域名、Url參數、請求頭信息、Cookie 等),然后進行租戶信息配置的切換。有新租戶創建的時候無需進行新的 WebAPI 的創建,只需要初始化租戶基本信息即可。

在這種方式下,如果 Cluster1 的負載超過限度了,也要能夠進行動態切換,將其中的某些租戶切換到其他的 Cluester 中,如上圖。

在 WebAPI 的代碼實現上,可以參考 Abp 框架中多租戶的實現,這里給出一個簡化版本:

TenantConfiguration:租戶配置信息

  1. [Serializable
  2. public class TenantConfiguration 
  3.     public Guid Id { get; set; } 
  4.  
  5.     public string Code { get; set; } 
  6.  
  7.     public string Name { get; set; } 
  8.  
  9.     public TenantStatus TenantStatus { get; set; } 
  10.  
  11.     public string DBConfig { get; set; } 
  12.  
  13.     public string CacheConfig { get; set; } 
  14.  
  15.     public string MQConfig { get; set; } 
  16.  
  17.     public string MongoConfig { get; set; } 
  18.  
  19.     public TenantConfiguration() 
  20.     { 
  21.         TenantStatus = TenantStatus.Enable; 
  22.     } 
  23.  
  24.     public TenantConfiguration(Guid id, string name
  25.         : this() 
  26.     { 
  27.         
  28.         Id = id; 
  29.         Name = name
  30.     } 

TenantStore:從緩存或數據庫中獲取租戶配置信息

  1. public interface ITenantStore 
  2.     TenantConfiguration Find(string code); 
  3. public class TenantStore : ITenantStore 
  4.     public TenantConfiguration Find(string code) 
  5.     { 
  6.         //從緩存或數據庫進行租戶配置信息獲取 
  7.         throw new NotImplementedException(); 
  8.     } 

CurrentTenant:當前租戶類,用來存儲當前租戶信息,以及切換租戶

  1. public interface ICurrentTenant 
  2.  
  3.     TenantConfiguration Config { get;} 
  4.     IDisposable Change(string code); 
  5. /// <summary> 
  6. /// 當前租戶 
  7. /// </summary> 
  8. public class CurrentTenant:ICurrentTenant 
  9.     public ITenantStore _tenantStore; 
  10.     public CurrentTenant(ITenantStore tenantStore) 
  11.     { 
  12.         _tenantStore = tenantStore; 
  13.     } 
  14.  
  15.     public TenantConfiguration _config; 
  16.     public TenantConfiguration Config => _config; 
  17.  
  18.     /// <summary> 
  19.     /// 切換租戶 
  20.     /// </summary> 
  21.     /// <param name="code"></param> 
  22.     /// <returns></returns
  23.     public IDisposable Change(string code) 
  24.     { 
  25.         TenantConfiguration tenantConfig= _tenantStore.Find(code); 
  26.         if (tenantConfig == null
  27.         { 
  28.             throw new Exception("Tenant not found"); 
  29.         } 
  30.  
  31.         if (tenantConfig.TenantStatus != TenantStatus.Enable) 
  32.         { 
  33.             throw new Exception("Tenant is disabled or deleted"); 
  34.         } 
  35.  
  36.         return new DisposeAction(() => 
  37.         { 
  38.             _config = tenantConfig; 
  39.         }); 
  40.     } 

UrlTenantResolve:根據 Url 參數進行租戶解析

  1. public interface ITenantResolve 
  2.     string Resolve(HttpContext httpContext); 
  3. /// <summary> 
  4. ///  
  5. /// </summary> 
  6. public class UrlTenantResolve:ITenantResolve 
  7.  
  8.     public string Resolve(HttpContext httpContext) 
  9.     { 
  10.         return httpContext.Request.QueryString.HasValue 
  11.            ? httpContext.Request.Query["__tenant"].ToString() 
  12.            : null
  13.     } 

MultiTenancyMiddleware:租戶中間件,關于在 dotNET Core 中自定義中間件可以參考《dotNET Core 3.X 請求處理管道和中間件的理解》

  1. public class MultiTenancyMiddleware: IMiddleware 
  2.     protected readonly ITenantResolve _tenantResolve; 
  3.     private readonly ICurrentTenant _currentTenant; 
  4.  
  5.     public MultiTenancyMiddleware( 
  6.        ITenantResolve tenantResolve, 
  7.        ICurrentTenant currentTenant) 
  8.     { 
  9.         _tenantResolve = tenantResolve; 
  10.         _currentTenant = currentTenant; 
  11.     } 
  12.  
  13.     public async Task InvokeAsync(HttpContext context, RequestDelegate next
  14.     { 
  15.         var tenantCode = _tenantResolve.Resolve(context); 
  16.  
  17.         if (tenantCode != _currentTenant.Config.Code) 
  18.         { 
  19.             using (_currentTenant.Change(tenantCode)) 
  20.             { 
  21.                 await next(context); 
  22.             } 
  23.         } 
  24.         else 
  25.         { 
  26.             await next(context); 
  27.         } 
  28.  
  29.         await next(context); 
  30.     } 

數據庫

數據庫在這里指的是關系型數據庫,用來存儲業務數據,實現多租戶,就要對數據進行隔離,通常的數據隔離方式有三種模式:

1、完全隔離,每個租戶使用獨立數據庫;

2、部分共享,租戶共享一個數據庫,以 schema 或者 table 區分;

3、完全共享,租戶共享相同的數據庫表,以 tenant_id 進行區分

推薦使用第一種或第二種,隔離程度比較高,也比較容易做橫向擴展,如果是第三種,需要處理數據的隔離問題,需要處理單表大數據的問題等,對技術要求比較高。

中間件

除了數據庫,一個系統還需要依賴其他的一些中間件,比如緩存、消息隊列、文件存儲:

  • 緩存:Redi
  • 消息隊列:RabbitMQ
  • 文件存儲:MongoDB 的 GridFS

Redis

1、Redis 中使用數據庫的方式進行租戶隔離;

2、Redis 可以通過修改配置文件的方式進行數據庫的擴展,默認為 16 個;3、通過 Redis 分片集群的方式進行部署,可以進行橫向擴展;3、在 Redis 集群中,官方推薦節點數量不超過 1000 個,這個對于多租戶系統的前期來說應該是夠用了,如果到了租戶數量的爆發期,再進行架構的擴展,比如,不同的租戶路由到不同的 Redis 集群中。

RabbitMQ

在 Rabbitmq 有 vhost 機制,可以一個租戶創建一個vhost,通過 vhost 來進行租戶的隔離,目前還沒查詢到 vhost 是否有上限,需要做進一步驗證。

MongoDB

MongoDB 中主要使用 GridFS 來進行非結構化數據的存儲,通過創建數據庫的方式來進行租戶的隔離,而且 MongoDB 支持分片的集群部署方式,可以進行擴展橫擴展,在前期,一個 MongoDB 集群應該就夠用了。

最后

技術方案和架構沒有最好的,只有最適合的,符合當下的業務場景、團隊的技術能力就可以,然后要做的就是做 MVP (最小可行性產品),進而進行系統的改造。

希望本文對您有所幫助!

 

責任編輯:武曉燕 來源: 不止dotNET
相關推薦

2014-09-17 10:30:25

代碼

2011-07-04 09:33:04

惠普轉型李艾科

2011-12-23 09:16:19

2014-09-23 11:21:05

代碼命名程序員架構設計

2022-07-13 08:45:29

云原生容器網絡

2013-05-13 11:25:44

系統架構

2013-05-14 12:06:26

.Net系統架構架構設計

2019-03-22 14:38:03

容器安全隔離

2013-03-06 10:19:56

重構架構設計

2022-04-06 07:14:29

區塊鏈網絡生態系統

2013-06-26 10:13:32

C語言結構體結構體偏移

2011-07-18 16:33:20

sqlite

2014-07-24 13:32:01

Google NowSiri

2014-11-25 11:52:15

.NET

2025-05-14 03:00:00

2015-03-26 09:23:17

天璣科技融合架構

2021-05-20 09:11:00

5G5G網絡5G終端

2023-04-11 14:42:14

2015-11-02 09:43:25

ASP.NET異步編程

2023-06-07 13:50:00

SaaS多租戶系統
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美福利 | 日韩精品人成在线播放 | 欧美一级片在线看 | 日韩在线欧美 | 成人免费福利视频 | 午夜精品导航 | 久久成人久久 | 一级毛片观看 | 成人午夜黄色 | www.av在线 | 欧美aⅴ| 一本一道久久a久久精品综合 | 国产区第一页 | 国产精品美女久久久久久免费 | 日韩精品一区二区三区视频播放 | 成人精品一区二区三区中文字幕 | 国内自拍视频在线观看 | 日韩伦理电影免费在线观看 | 国产毛片久久久 | 欧洲尺码日本国产精品 | 男人的天堂视频网站 | 亚洲高清视频在线 | 日产精品久久久一区二区福利 | 国产区视频在线观看 | 视频在线一区二区 | 精品久久久久久亚洲综合网 | 久久久人成影片免费观看 | 一区二区三区不卡视频 | 欧美精品一区在线 | 五月婷婷婷 | 午夜爱爱毛片xxxx视频免费看 | 成人免费视频7777777 | 欧美在线一区二区三区 | 国产精品日韩一区二区 | 在线免费观看毛片 | 午夜免费av | 五月免费视频 | 超碰成人免费观看 | 韩日一区二区 | 琪琪午夜伦伦电影福利片 | 在线视频 亚洲 |