X-Admin&ABP框架開發-租戶管理

  軟件即服務概念的推進,定製化到通用化的發展,用一套代碼完成適應不一樣企業的需求,利用多租戶技術能夠去作到這一點。ABP裏提供了多租戶這一律念而且也在Zero模塊中實現了這一律念。java

 

1、多租戶的概念

  單部署-單數據庫:部署應用程序的單個實例和單個數據庫。在每一個數據表(關係型數據庫)裏用一個TenantId(租戶Id或相似的如企業Id)字段來隔離區分每一個租戶數據。git

 

  單部署-多數據庫:部署應用的單一實例,用一個主(宿主)數據庫存儲租戶元數據(像租戶名和子域),併爲每一個租戶創建並維護一個隔離的數據庫。操做上經過識別當前租戶並從主數據庫中讀取相對應的存儲數據庫地址,切換到該租戶獨有的數據庫中執行操做。數據庫

 

 

  多部署-多數據庫:爲每一個租戶部署應用的一個實例並使用一個獨立的數據庫,那麼咱們就能夠在一臺服務器上爲多個租戶服務,只需確保相同應用的多個實例在一個服務器的環境下不會互相沖突就行。服務器

 

  還有兩種多租戶形式,諸如單部署-混搭數據庫、集羣部署-單/多/混搭數據庫,再也不說起,ABP針對於這五種多租戶形式均可以使用。cookie

 

  宿主與租戶:對於這兩個概念,最好的理解方式即是酒店,酒店老闆便是宿主,租戶只擁有房間權限,酒店老闆能夠提供管理全部租戶和房間。ide

 

2、ABP中多租戶配置

一、啓用/禁用多租戶網站

  若是不須要多租戶,好比說沒有多租戶情形,應用部署在企業私有服務器上,那麼也能夠不考慮多租戶的使用,能夠在ABP中關閉多租戶(儘管關閉了,但默認仍是會使用一個租戶,默認租戶Id爲1,此時只有這個默認租戶沒有宿主)。在WebCoreModule中PreInitialize方法內能夠添加以下代碼啓用或關閉多租戶,默認是啓用的。spa

public override void PreInitialize()
{
   ...

    Configuration.MultiTenancy.IsEnabled = true;

    ...
}

 

二、偵測當前租戶並在Session中獲取租戶3d

 ABP中租戶名稱是惟一的,對於識別當前租戶或是宿主身份,ABP沒有使用Asp.Net 提供的Session,聲明瞭IAbpSession接口並提供了默認的實現(ClaimAbpSession)去測定當前租戶信息,按照以下思路去肯定租戶。code

  • 若是當前用戶登陸了系統,那麼能夠從當前用戶的聲明信息中讀取到當前租戶信息,若是沒有讀取到租戶信息,那麼能夠判定是宿主。
  • 若是當前用戶沒有登陸系統,那麼會有幾種方式去獲取,若是如下幾種方式仍未獲取到租戶Id,則認爲是使用宿主登陸。
  • 從當前域名或是子域名去獲取域名名稱,而後經過租戶倉儲去查詢是否存在相關的域名或子域名存在則能夠肯定租戶Id。
  • 從Http請求頭中獲取在ABP中默認配置項Abp.TenantId(該配置項可更換名稱)。
  • 從Http請求的cookie中獲取Abp.TenantId

 IAbpSession聲明瞭獲取當前用戶和租戶信息的方法,該方法容許咱們獲取當前登陸的用戶及當前的租戶信息。而且獲取到的信息按照不一樣的規則,有着不一樣的做用。

  • 若是獲取到的用戶和租戶Id都是空的,那麼意味着當前用戶沒有登陸系統,所以也沒法判定出當前是宿主仍是租戶。
  • 若是用戶Id是空的,可是租戶Id不是空的,那麼能夠知道是哪一個租戶,可是用戶仍然是沒有登陸的,只是選擇了租戶。
  • 若是用戶Id不是空的,可是租戶Id是空的,那麼能夠知道是用戶使用宿主登陸了系統。
  • 若是用戶Id且租戶Id不是空的,那麼就知道是選擇了租戶而且是租戶中的某個用戶登陸了系統。

 

三、數據過濾

  若是使用了多租戶,那麼在讀取數據時,會依據當前租戶Id加上額外的過濾條件,這一點ABP已經處理好了,咱們無需在linq中敲代碼,可是有個前提條件是,讀取數據的這個實體有設置多租戶。

  一、若是實體使用的是IMustHaveTenant接口,那麼讀取時會依照當前租戶Id進行條件過濾。

  二、若是實體使用的是IMayHaveTenant接口,那麼讀取到的數據會依照當前租戶Id的有無值進行區分,若是當前租戶Id爲空,那麼將讀取到宿主的數據,若是租戶Id不爲空,則讀取相應租戶數據。

  三、若是實體沒使用這兩個接口,則讀取到的數據不區分宿主和租戶。

  這兩個接口使用場景:若是是宿主和租戶都須要的,好比角色、用戶、部門等,那麼使用IMayHaveTenant接口,若是僅是租戶所須要的那隻需使用IMustHaveTenant接口。

 

四、宿主與租戶間切換

  此處切換能夠這麼理解,給我一個其它租戶Id,我能夠在個人租戶中獲取到其它租戶的數據,相應的,其它租戶也能夠獲取到我租戶的數據,或是宿主獲取租戶數據。若是不給定租戶Id,租戶能夠獲取宿主數據。

public class ProductService : ITransientDependency
{
    private readonly IRepository<Product> _productRepository;
    private readonly IUnitOfWorkManager _unitOfWorkManager;

    public ProductService(IRepository<Product> productRepository, IUnitOfWorkManager unitOfWorkManager)
    {
        _productRepository = productRepository;
        _unitOfWorkManager = unitOfWorkManager;
    }

    [UnitOfWork]
    public virtual List<Product> GetProducts(int tenantId)
    {
        using (_unitOfWorkManager.Current.SetTenantId(tenantId))
        {
            return _productRepository.GetAllList();
        }
    }
}

 

3、配置一個多租戶實體

  基於以前的數據字典進行改造,以便適用於多個租戶使用,而且考慮到宿主無需使用數據字典,將其繼承IMustHaveTenant接口後,更新數據庫即可。

public class DataDictionary : Entity<long>, IMustHaveTenant
{
    public const int MaxNameLength = 30;

    /// <summary>
    /// 租戶Id
    /// </summary>
    public int? TenantId { get; set; }

    /// <summary>
    /// 字典類型
    /// </summary>
    [StringLength(MaxNameLength)]
    public string TypeName { get; set; }

    /// <summary>
    /// 關聯數據字典項
    /// </summary>
    public virtual ICollection<DataDictionaryItem> DataDictionaryItem { get; set; }
}

   我設置了默認當前租戶,而且不提供選擇租戶的頁面,經過Url去區分宿主和默認租戶,登陸當前租戶帳號後,查看當前網站內的數據字典看到以前已有數據所有消失,獲取數據字典數據時,默認是ABP將當前租戶Id帶入做爲查詢條件了。

  

 

   修改添加方法,添加當前租戶Id的賦值,再次爲當前租戶添加幾條相應的數據字典,頁面中便可存在相關數據了。

dataDictionary.TenantId = AbpSession.TenantId.Value;

   最後兩條數據是指定租戶Id爲1下的,以前的數據能夠手動清除。

   

 至此,對於ABP中租戶的相關使用瞭解的清楚了,對於多租戶下數據存儲量大,拆分紅集羣部署-多數據庫情形沒有作嘗試,但願有機會可使用一番。

 

 倉庫地址:https://gitee.com/530521314/Partner.Surround.git

2020-01-11,望技術有成後能回來看見本身的腳步
相關文章
相關標籤/搜索