簡體   English   中英

使用Spring和Hibernate和Tomcat在無狀態環境中實現多租戶

[英]Implement multi tenancy in a stateless environment using Spring and Hibernate and Tomcat

我試圖了解我們如何為涉及多租戶的SaaS產品構建RESTful API。 該技術棧是使用Spring和Hibernate並將Java部署到Tomcat的Java。

我的主要問題是如何在REST調用中維護tenant_id,以便應用程序在執行CRUD時使用正確的數據庫連接。 看到Tomcat使用線程池並重用線程,我們不應該使用ThreadLocal。

我已經閱讀到slf4j通過MDC實現來支持此功能以進行日志記錄。 一個servelet過濾器確實會預先維護tenant_id並在過濾器退出時將其清除。 因此,記錄器在消息中使用正確的tenant_id。

同時使用ThreadLocal違反了無狀態原理,因為它隱式地添加了一個狀態。

此外,創建某種類型的ContextSession對象(包含tenant_id)並將其傳遞的想法似乎無法解決我的問題。 由於此對象將向下傳遞到DAL和DAO的各層以加載對象。 我想避免在此ContextSession類上的這種高度耦合,以及必須將其包括在許多方法簽名中。

如何在無狀態環境中實施多租戶?

當用戶登錄到您的應用程序時,他們將以某種方式與租戶相關聯。 因此,應該可以從spring SecurityContext中訪問租戶信息。

例如,如果我有一個包含2個租戶的應用程序; 租戶A和租戶B。 登錄時,用戶需要以某種方式指示他們屬於哪個租戶。 這可以通過多種方式來完成,例如使用不同的主機名(例如tenantA.myapp.com,tenantB.myapp.com)或url參數,或者以登錄形式輸入租戶信息。 在對用戶進行身份驗證時,您需要使用與特定租戶關聯的身份驗證領域。 作為身份驗證的一部分,應該將spring SecurityContext設置為包含一些信息,這些信息使您可以在用戶隨后的服務調用中確定用戶屬於哪個租戶。 應該可以從應用程序的不同服務層訪問SecurityContext,而無需顯式編寫任何程序以實現此目的。

有多種方法可以將當前的HttpSession與特定的租戶相關聯。

  1. 在URL上提供某種類型的client_id參數,該參數用於通過集中式公共客戶端數據庫反向查找指定的后端tenant

  2. 將經過身份驗證的用戶與特定tenant關聯。 當用戶通過集中式用戶數據庫進行身份驗證時,將根據用戶帳戶查找租戶。

tenant_id如何傳遞給較低的應用程序層確實是一個問題。

我的第一個選擇是使用ThreadLocal 如果您已經在使用Spring Security,那么您已經在使用ThreadLocal變量,甚至可能不知道它。

使用ThreadLocal變量不會破壞應用程序的無狀態設計。 您只有一段代碼期望變量包含必須使用的特定值。 這只是一種在整個應用程序層之間傳遞狀態而不實際將狀態作為方法簽名上的參數顯式傳遞的奇特方法。

顯然,其他兩個選項是使用某些Context對象或僅將值直接傳遞到下游。

在Web應用程序中,我通常會通過一些攔截器或過濾器來執行此操作,該攔截器或過濾器將按請求查找請求參數client_id並獲取關聯的tenantId並將其設置在特殊的ThreadLocal變量中。

一旦調用chain.doFilter( request, response ); 返回或引發異常,您只需清除ThreadLocal變量即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM