1. 程式人生 > >淺析多租戶在 Java 平臺和某些 PaaS 上的實現

淺析多租戶在 Java 平臺和某些 PaaS 上的實現

多租戶綜述

多租戶(Multi Tenancy/Tenant)是一種軟體架構,其定義是:

在一臺伺服器上執行單個應用例項,它為多個租戶提供服務。

在這種架構上,應用程式被設計成能將自己的資料、配置進行虛擬的分割槽,以便每個租戶都感覺到自己是在一個私有的、可定製化的應用例項上工作。

這背後代表的是資源的伸縮能力。即在同樣硬體配置,不同租戶在資料分離的情況下,共享同樣的應用程式,還隨著租戶數量的提升,應用程式的水平擴充套件,並維持著類似的效能指標(一致響應時間等)。這同時意味著資源使用效率的提升,以及節省 IT 資產的投入。

在共享與安全之間取得平衡,是多租戶架構最主要的關注點。更多的資源共享有益於靈活性的上升和總體成本的下降,但單個租戶的安全性需求要有額外的技術手段來保證。

多租戶的設計牽涉到兩層:

  • 資料
  • 應用 / 平臺

資料層的多租戶能力是一個很大的主題,主要是指不同的租戶如何共享或分離資料,並滿足安全性。本文則主要關注的是應用 / 平臺層的多租戶規範與方案。

Java PaaS 的多租戶概況

Java 平臺已經在 J2EE 中提供了部分多租戶能力。作為 Oracle 要給 Java 平臺提供 PaaS 的目標中的一部分,多租戶特性在 Java EE 7 最初的規範中有多處體現,見表 1。

表 1. Java EE 7 中涉及多租戶的 JSR
名稱 規範 相關簡述
JSR342 Java EE 7 平臺將定義應用元資料描述符,用以描述 PaaS 的執行環境,例如多租戶,資源共享,服務質量(QoS),和應用間的依賴關係。
JSR338 JPA 2.1 資料層的多租戶支援。
JSR340 Servlets 3.1 安全,會話狀態,資源和 web 應用中其它隔離需求的多租戶支援。
JSR343 Java Message Server 2.0 訊息服務的多租戶支援。
JSR345 EJB 3.2 改進 EJB 架構實現資料層的多租戶支援。

Java EE 7 對 PaaS 模型支援的規範要求:對 PaaS 環境中的同一個 PaaS 應用能夠被多個租戶使用,每個租戶使用不同的應用程式例項,同時又能共享資源。

PaaS 規範中要求每個租戶都有一個 tenantId,這個 ID 對於某個 PaaS 供應商的全部租戶來說,是唯一的。sevlet 容器可以將外部請求正確對映到對應的租戶例項,並在隨後的所有業務流程中以 tenantId 為處理的依據,保證不同租戶所使用資源的隔離。同時租戶的介面等是可以定製化的。

例如帶給 JPA 的影響就包括:

  • 支援共享資料庫、分離 schema:通過元資料可以對 schema/ 表對映進行重配置。
  • 支援共享資料庫、共享 schema:廠商可以使用 tenantId 實現資料行級別的隔離。
  • 程式設計模型的影響:將對本地查詢和直接 JDBC 訪問進行限制。

但在 2012 年 8 月 30 號,Oracle 的 Java EE 7 規範主管 Linda Demichiel 在部落格中宣佈因為雲領域相關的應用方式不夠成熟,以及 Java EE 7 版本的釋出壓力,將把 PaaS 和多租戶支援的部分推遲到 Java EE 8(以下翻譯引用自 InfoQ):

儘管我們的願望很美好,但是在我們日程表中,雲相關的進展仍然很慢。一部分原因在於構建分配(provisioning)、多租戶(multi-tenancy)、彈性(elasticity)等領域以及應用部署部分仍然不成熟;一部分原因是我們保守的做事方式,我們盡力把事情做‘正確’,但是在開展這項工作時,我們在雲領域仍然缺乏足夠的行業經驗。因此,我們認為,若要提供對標準化的基於 PaaS 的程式設計方式和多租戶的完善的支援,就可能會將 Java EE 7 的釋出推遲到 2014 年春天。該時間是兩年之後,比規劃晚了一年。在我們看來,拖得時間太長了。

因此我們向 Java EE 7 專家組提議調整我們的計劃,堅持我們當前的目標釋出日期,而將我們日程表中 PaaS 和多租戶支援的部分推遲到 Java EE 8。”

那麼在 Java 8 中,與雲相關的最重要的兩個特性就是多租戶與模組化。具體說就是:

  • 多租戶:指的是在一個 Java 虛擬機器(JVM)中安全執行多個應用的能力。
  • 模組化:指的是把 JDK 重新組織為一套儘管互相依賴但卻是定義清晰的模組。Java 開發人員的一個替代選擇是使用 OSGi。

來自 Red Hat 的 Mark Little 認為下一個 Java 版本支援這兩個特性將使得進行大規模雲部署變得可行。

同時,Oracle 的規範領導 Linda Demichiel 提到,即使因為雲端應用還沒完全做好標準化的準備而導致 Java EE 7 被迫放棄 PaaS 部分,但諸如 Oracle、Red Hat、IBM 和 CloudBees 等供應商已經開始提供在雲上執行 Java EE 程式的能力。

因而本文的剩餘部分將試圖對幾種比較流行的 Java 平臺解決方案中涉及多租戶的部分做出闡述。

Cloud JVM

前面提到,預期 Java 8 中對多租戶的支援需要在 JVM 這一層次中做到。那麼它的細節如何,又原因何在?

對於一個傳統的 J2EE 容器(任意一個應用伺服器)來說,它啟動一個 JVM,然後不同的 WEB 應用部署其上,供併發使用者訪問。這已經在概念上接近了多租戶。見圖 1。

圖 1. J2EE 部署圖
圖 1. J2EE 部署圖

但這種結構在實際中很少被使用到,因為各 Web App 之間沒有隔離機制。對於多數 J2EE 應用來說,上圖的模式通常被簡化為僅有一個應用,執行在一個 JVM 上,後臺一個數據庫 /schema 為之服務,即“one app per app-server per JVM”。但無論哪種模式,都依然離多租戶的資料 / 配置隔離以及共享需求,和應用程式的水平擴充套件能力需求相差甚遠。主要原因在於:

  1. Web 應用彼此的執行時記憶體空間不是獨立的;
  2. 資料庫是分離的,但缺乏共享;
  3. 對載入的類無法完全彼此分開;
  4. 當需要水平擴充套件時,可以做叢集(cluster)和負載平衡,但這種架構下存在很多技術難點,例如 session 複製就相當脆弱。

另外傳統的 J2EE 應用也與雲時代的多租戶在業務模式上也有不同。傳統 J2EE 模式強調的是多使用者,本身的應用例項是一個;而多租戶則在同一個應用例項上做了複製,是多個應用例項(彼此內容相同),一個例項服務於一個租戶。

隨之而來的是傳統的 J2EE 為了應對多租戶場景,會為每一個應用啟動一個 JVM,每個 JVM 彼此獨立,消耗各自的資源。這無法完美實現多租戶的一個典型特徵:在最大共享資源的基礎上做好各例項間的隔離。

因此,現在有一些 IT 廠商做出了自己的嘗試。Waratek 是澳大利亞的一家公司,他們將在新南威爾士大學期間進行的一個關於元迴圈(meta-circular,是指使用語言自身來實現其執行環境)抽象機直譯器和動態編譯框架的專案進行了商業化,開發出 Waratek Cloud VM。這個基於 Java 語言自身開發的虛擬機器給執行在虛擬架構上的 Java 程式提供了一種高密集度宿主模型,即多個應用程式可以同時執行在單個的 JVM 上,每個應用有自己的 Java 虛擬容器(Java Virtual Container,JVC)。如圖 2。

圖 2. Waratek Cloud VM
圖 2. Waratek Cloud VM

Waratek 在 JVM 內部構建了一個多租戶的虛擬容器架構,每個 JVC 包含一個完全隔離又可控的共享 JVM 映象——它是一個元迴圈的虛擬機器,和其它 JVC 一起分享主機 VM 的環境(堆、類、JIT)。就如 hypervisor 對物理機一樣,JVC 對 Java 平臺也做了虛擬化。它具有以下特點:

  • 輕量級
  • 一個 JVM 可以 host 幾十甚至上千個 VC,每個 VC 的大小可以從 1MB 到數 GB
  • VC 執行的每一方面都是隔離的,例如 CPU 優先順序,記憶體上限和頻寬限額等
  • VC 使用的每一方面都是可計量的,例如 CPU 使用了多少 Hz,記憶體 /IO 使用了多少 byte
  • VC 提供了像電力千瓦 - 時的計算指標:CPU 消耗了多少 GHz- 時,記憶體消耗了多少 GB- 時
  • 每個 .war/.ear 都有自己的 VC

每個 VC,有自己的堆空間。Waratek 提供了自動垃圾收集服務,在一臺主機上,只有一個垃圾回收器,它負責給多個 VC 上的堆空間進行記憶體無用物件清理。相比較於多 App/ 多 JVM 模式引起的多個垃圾回收器程序同時工作,Waratek 在 CPU 資源的競用上好很多。

VC 在執行時的記憶體片彼此隔離則保證了應用間的安全性。傳統的 J2EE 多應用由於堆記憶體空間是共用的,很難避免一個正常執行的應用的記憶體區域被惡意侵佔。或者由於一個應用呼叫了 System.exit(0),導致同一個 JVM 上所有的應用被迫一起退出。

對於核心的 JDK 庫,每個 VC 不需要重複載入,而是彼此共享,這極大的簡化了應用的啟動。

單個 VC 的資源可配置和可計量對於雲應用至關重要,這等同於對物理機器和作業系統的虛擬化後,每個虛機的可配置和可計量。它支援通過對主機的 JVM 進行 JVMTI(Java Virtual Machine Tool Interface)呼叫獲取每個 VC 上應用程式的資源耗費情況。

同時,這類 JVC 對於 Scala、Jython 和 JRuby 等運行於 JVM 之上的語言也是同樣直接支援的,而且由於是二進位制程式碼級別的相容,因而無需為遷移到 Cloud VM 而改動程式。

在解決了共享與隔離的問題後,Waratek 甚至可以讓 64 個 JBoss 的應用伺服器執行在一個 JVM 之上,這樣的效能很驚人。

Waratek 公司的這個產品可以在 RHEL 和 CentOS 上安裝。由於它是在 JVM 之上實現的虛擬化,因而不需要再在作業系統層面安裝任何虛擬化支援。出於測試目的,可以在一臺乾淨的物理伺服器上安裝 Linux,然後僅僅執行一個 JVM,並配置多個 JVC,每個 JVC 上執行一個不同的應用伺服器例項。

Waratek 公司為它的產品申請了約 150 項專利,其中 50 個已經被授權。目前尚不清楚這些專利會否對 Hotspot、JRockit、J9、Zing 等 JVM 的雲化開發構成影響。

Java PaaS

當前市面上支援 Java 語言的 PaaS 很多,包括 Amazon Elastic Beanstalk、CloudBees、Cloud Foundry、Google App Engine、Red Hat OpenShift、Jelastic、Heroku 等。它們各有特點,例如 GAE 線性擴充套件能力很強,在大規模訪問量時依然有良好效能表現,但它對 Java 程式做了諸多限制,像檔案與網路 IO 包等就不可使用,以及不支援很多常用的框架(如 Spring、Struts)。Beanstalk 是基於 EC2 的,它提供 Tomcat 例項,並與 Amazon 的 Rest API 整合可訪問後臺關係資料庫。在表 2 中給出一些關於它們的具體資料。

表 2. PaaS 對比圖
Amazon Elastic Beanstalk CloudBees Cloud Foundry Google App Engine Heroku Jelastic Red Hat OpenShift
支援語言 Java, .Net, PHP Java Java/Spring, Groovy/Grails, Ruby Rails & Sinatra, Node.js, .Net via extension Java, Python Ruby, Java Java, PHP, Ruby, Scala, Groovy Java, Java EE, Python, Perl, PHP, Ruby, node.js
開源 N N Y N N Y
儲存庫 Maven, Git, SVN https://github.com/cloudfoundry Maven, Git, SVN Git, SSH, Rsync, Maven, sftp
資料庫 MySQL MongoDB, MySQL and Redis Amazon RDS (MySQL), MongoDB, Redis, CouchDB... Maria DB, MySQL, PostgreSQL, MongoDB, CouchDB MySQL, PostgreSQL, MongoDB

以 CloudBees、Jelastic 和 OpenShift 為例,對於 Java 應用開發人員來說,它們對純 Java 的支援極好:即程式碼無需修改,支援流行的 Java 應用伺服器。它們也不會導致平臺繫結,而是易於在不同 PaaS 間遷移。

這些 PaaS 的使用模式都比較相似。首先註冊賬號,然後申請應用程式,獲得免費的配額、域名、程式碼庫 URL,再上傳自己的程式碼,進行持續整合。

先來看一下通用的多租戶,從 SaaS 角度講,多租戶牽涉到多個層面:底層硬體、作業系統、應用伺服器、資料層、應用程式碼等。每個層面的虛擬化策略,甚至是沒有任何虛擬化僅僅是邏輯上的分離策略,都是這個架構的一部分。

PaaS 的多租戶主要體現在應用伺服器這個層面,又有兩類部署模型:

  1. 專用容器部署:一個租戶應用有一個或多個專用的 Java 應用伺服器,應用對容器是一對多的關係。
  2. 共享容器部署:多個租戶應用共享一組 Java 應用伺服器,每個 Java 容器為不止一個租戶提供服務。應用對容器是多對多的關係。

第一種模式是比較傳統的租戶模式,它在安全性隔離上做的很好,定義了一個租戶所能訪問的資源,應用本身修改小或不用修改,但不夠靈活。而對於第二種共享容器多租戶模型來說,通常使用基於 OSGI 的分割槽、租戶資源上下文、和租戶元件的按需載入來共享 JVM 資源,能有更低的成本和更高的靈活性,但需要程式上相應的變化。總體來說,決定採用哪種租戶架構,還要有更多的考慮。

Jelastic 使用的是基於容器的虛擬化方案,這與傳統基於虛機的方式不同。(若不考慮 PHP)它是一個 Java 的宿主系統,對於雲使用者來說,他們得到的是 J2EE 容器(Tomcat、Glassfish、Jetty)。顯而易見,多租戶的實現依賴於容器的例項數量,即每個應用程式都是彼此獨立的,租戶 A 的應用所在的 JVM 不同於租戶 B,包括後臺的資料庫也各不相同。這個隔離的粒度是 App Server 級別的(當然一個租戶擁有多個容器例項也很常見)。

順帶一提的是 Jelastic 資源管理方式的不同,即它獨特的自動垂直擴充套件(automatic vertical scaling)能力:基於應用的負載狀況,動態分配 RAM 和 CPU,當負載增多時,系統會主動給應用增加資源,而負載減少時,將資源自動返回給作業系統。其背後的機制是在 Java 7 中首先匯入並在 Java 6 update 中也加入的 G1(Garbage First)垃圾收集器。

Red Hat 的 OpenShift 使用了一種“multi-tenant in the OS”(而不是“multi-tenant hypervisor”)的方法,它採用了兩層多租戶機制:

  • 第一層:多個虛機執行在一臺物理機上
  • 第二層:多個應用執行在一個虛機上

具體說,就是利用 RHEL 作業系統自身的控制組和 SELinux 來實現隔離的安全機制;用 RHEL 的資源管理實現多租戶環境設定;用 RHEV(Red Hat Enterprise Virtualization)實現虛擬化;用 JBoss 中介軟體實現 J2EE 全支援。OpenShift 的基礎就是 RHEL。

那麼從 Java 應用的角度來看,它的多租戶體現在多個 RHEL 例項 + 執行在 JBoss 上的多個應用組合上。這種 RHEL 作業系統級別的虛擬化方案比基於 hypervisor 的虛擬化方案強在無需硬體層面的虛擬能力支援,沒有額外開銷,但弱點是不夠靈活,難以支援其它 OS,例如 windows。

現狀與展望

多租戶對成本的節省是很顯著的,尤其是對於一些分佈在不同時區的大企業尤其如此。其內部資料中心的硬體資源利用率能達到很高(例如 70%~80%)的程度。

傳統的租戶實現通常是專用的現有的 PaaS 在多租戶實現上主要是依賴於作業系統或者 Java 容器,同時在底層也常常依賴於 IaaS,多租戶的能力和虛擬化的目標(包括了硬體、OS、應用伺服器、資料庫等)相關。但類似於 Waratek 在 JVM 的虛擬化嘗試則是最近的趨勢,它對 PaaS 層面的多租戶支援提升了資源的利用效率。Oracle 注意傾聽了 PaaS 廠商對雲平臺的建議,我們期待在 Java EE 8 中能看到這部分功能。


相關推薦

淺析租戶Java 平臺某些 PaaS 實現

多租戶綜述 多租戶(Multi Tenancy/Tenant)是一種軟體架構,其定義是: 在一臺伺服器上執行單個應用例項,它為多個租戶提供服務。 在這種架構上,應用程式被設計成能將自己的資料、配置進行虛擬的分割槽,以便每個租戶都感覺到自己是在一個私有的、可定製化的應用例項上

echarts條折線圖柱狀圖實現

// 基於準備好的dom,初始化echarts例項 var myChart = echarts.init(document.getElementById('main')); // 指定圖表的配置項和資料 myChart.setOption({

Linux:使用執行緒程式設計訊息佇列,實現兩個程序之間的聊天

思路: 一個檔案:建立一個執行緒和主函式,或者建立兩個執行緒主函式呼叫(我用這種)。 建立兩個訊息佇列, 一共兩個檔案,兩個佇列,四個程序 a.c    一個程序寫(訊息型別為1)   ---->>佇列     一個程序讀(訊息型別為2) b.c   一

python、scala、java分別實現在spark實現WordCount

下面分別貼出python、scala、java版本的wordcount程式: python版: import logging from operator import add from pyspark import SparkContext logging.basicCo

PaaS平臺——租戶的RBAC許可權管理(一)基本概念

公司(Company)   公司包含了體系結構集合與使用者集合。   公司可以存在上下級關係,這種關係僅限於展現形式,公司與公司之間沒有許可權繼承,也就是說在授權管理中公司之間全部是扁平關係。 公司的屬性有以下內容: 屬性 型別

java B2B2C Springcloud租戶電子商城系統(八):配置中心服務化高可用

server端改造 1、新增依賴 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifact

java版spring cloud+spring boot+redis租戶社交電子商務平臺(十二)斷路器監控(Hystrix Dashboard)

電子商務社交平臺原始碼請加企鵝求求:一零三八七七四六二六.在我的第四篇文章斷路器講述瞭如何使用斷路器,並簡單的介紹了下Hystri

Java - Thread Runnable實現線程

abs java jdk1 public adt system 轉載 作用 final Java多線程系列--“基礎篇”02之 常用的實現多線程的兩種方式 概要 本章,我們學習“常用的實現多線程的2種方式”:Thread 和 Runnable。之所以說是常用的,是因為通

深入.NET平臺C#編程筆記 第七章 深入理解

定義 方式 目前 rtu ride 筆記 總結 理解 hello 第七章 深入理解多態 1.裏氏替換原則: 在一個軟件系統中,如果子類出現在父類出現的位置,而整個軟件功能又沒有影響,那麽咱們稱為裏氏替換。 父類變量指向子類對象!! 2.Is 和as Is

基於容器微服務的PaaS平臺設計(一) 實現容器微服務持續集成

顯示 一次 target 全部 ext neu openshift svn客戶端 enc 版權聲明:本文為博主原創文章,歡迎轉載,轉載請註明作者、原文超鏈接 ,博主地址:http://www.cnblogs.com/SuperXJ/ 前言:關於什麽是容器微服務Paa

JAVA-初步認識-第十四章-線程-waitsleep的區別

分享圖片 thread long img wait方法 object 安全 截圖 也會 一. wait和sleep的方法有些類似,我們現在要對其進行描述,區分它們。 wait方法在object類中,而且有兩種形式,分別是wait()和wait(long timeout),我

EEPlat PaaS中的租戶數據隔離模式

-i dap png color 項目 attach 管理 uda 全部 EEPlat PaaS支持三種租戶的數據隔離技術:Sparce

Java線程CallableFuture類詳解

完成後 使用 str this In ret 類型 all 線程池 public interface Callable<V> 返回結果並且可能拋出異常的任務。實現者定義了一個不帶任何參數的叫做 call 的方法 public inter

Java繼承型的底層原理

當子類繼承父類以後,子類的物件為什麼可以訪問到父類中定義的方法?當子類Override了父類中的方法以後,訪問的是子類Override以後的方法,這是怎麼實現的?當子類Override了父類的方法以後,還有辦法得到父類的方法嗎?部落格:重寫(overwrite)、過載(overload)

Java 執行緒 joininterrupt 方法

簡述: 使用Java多執行緒中join和interrupt函式 《Java程式設計思想》 P669 ~ P670 一個執行緒可以再其他執行緒上呼叫join()方法,其效果是等待一段時間直到第二個執行緒結束才繼續執行。 如果某個執行緒在另一個執行緒t上呼叫t.join(), 此

Java

note 問控制 部分 老師 訪問控制權限 private 擴展 ati oid *********************第八章 復用類和多態****************************** 可復用 一.方法 二.復用 類 1.組合 2.繼承 ********

Java

*********************第八章 複用類和多型****************************** 可複用 一.方法 二.複用 類 1.組合 2.繼承 *****************************組合 has a************************

java:繼承

一.繼承 1.繼承 ①繼承是面向物件程式設計的三大特徵之一,是一種基於已有類來建立新類的機制。由繼承而得到的類稱為子類(或派生類),被繼承的類稱為父類(或超類)。 ② Java中每個類只允許有一個父類。語法如下:class <子類> extends <父類>

小白學JAVA,與你們感同身受,JAVA---day5:關於型的理解分析。魯迅的一句話:總之歲月漫長,然而值得等待。

魯迅的一句話:總之歲月漫長,然而值得等待。 至於是不是他說的,就看大家的了。   /* 多型:事物存在的多種形態。 多型的前提: 1.要有繼承關係。 2.要有方法的重寫。 3.要有父類引用指向子類物件。 向上轉型和向下轉型: 1.父類引用指向子類物件   &nbs