郭慶
(京華信息科技股份有限公司)
企業級應用指的是支持企業、事業單位或者政府等機構各項業務運作的軟件系統[1]。企業級應用主要負責顯示、操作和存儲大量復雜數據,并對這些數據進行支持和自動化[2]。隨著社會的進步和網絡技術的發展,眾多企業和組織為了使業務能夠與供應商、合作伙伴乃至最終用戶更緊密地聯系在一起,紛紛將企業級應用推向互聯網。但面對海量的業務數據處理時,傳統企業級應用架構在擴展性上遇到了瓶頸。近年迅速發展成熟起來的Hadoop平臺以其高效和易擴展等特性受到高度關注,將企業級應用遷移到Hadoop平臺成為應對海量數據處理技術挑戰的新思路。本文圍繞Java EE企業級應用遷移到Hadoop平臺展開研究,分析比較各種技術方法,并根據實際應用情況提出相應的遷移策略。
Java平臺企業版(Java Platform Enterprise Edition,Java EE),是Sun公司為企業級應用推出的標準平臺,現屬于Oracle公司[3]。Java EE自1998年發布以來得到了迅速地發展,已成為企業級應用的主流技術平臺之一。以Java Pet Store[4]為代表,典型的Java EE企業級應用最主要的功能是圍繞業務數據進行存儲、操作和顯示。整個系統一般可分為Web層、業務邏輯層和企業信息系統層(Enterprise Information Systems Tier)。應用運行在Java EE平臺提供的容器中,容器為應用的每個層次提供了相應的功能支持,見表1。

表1 Java EE技術與系統層次的對應關系
容器提供的 API和運行環境的支持使得應用的代碼實現更統一,為應用遷移提供了較清晰的切入點。
Hadoop[5]是由 Apache開源組織的一個分布式計算框架,設計用于在大量(廉價的)硬件設備上構建一個具有高可靠性和良好擴展性的集群系統,以分布式處理大數據集。Hadoop2.0包含以下模塊:
1) Hadoop通用模塊:支持其它Hadoop模塊的通用工具集;
2) Hadoop分布式文件系統(HDFS):支持對應用數據高吞吐量訪問的分布式文件系統;
3) Hadoop YARN:用于作業調度和集群資源管理的框架;
4) Hadoop MapReduce:基于YARN的大數據并行處理系統。
除了Hadoop本身,還有一大批以Hadoop為基礎發展起來的開源項目,它們是Hadoop平臺功能的補充和擴展,集合在一起形成了Hadoop生態系統[6]。
從前面的敘述可見,Hadoop平臺的功能是針對大數據集存儲和操作而設計的,因此本文研究的遷移是指在保持Java EE企業級應用業務功能不變的前提下,將其業務數據轉移到Hadoop中存儲,并使應用通過Hadoop實現對業務數據的訪問和操作。
對于典型的Java EE企業級應用,業務數據的存儲方式主要有2種:存放在關系型數據庫中;以文件的形式存放在文件系統中。
3.1.1 關系型數據庫遷移
考慮到遷移后數據查詢和操作的便捷性及性能,對關系型數據庫的數據遷移一般不直接存放到HDFS中,而是遷移到Hbase[7]、Canssandra[8]等分布式數據庫中。以Hbase為例,從關系型數據庫遷入數據有以下幾類方法:
1) 直接調用Hbase的API
Hbase客戶端包已提供了必要的方法,可編寫Java程序進行調用,程序邏輯如下:
① 通過JDBC讀出關系型數據庫中的數據。
② 假設Hbase里已建立了對應的表。創建org.apache.hadoop.hbase.client.HTable類的實例,并連接到Hbase:
HTable table = new HTable(org.apache.hadoop.hbase.HBaseConfiguration.create(), 〈表名〉);
③ 創建org.apache.hadoop.hbase.client.Put類的實例,并將要寫入Hbase的數據放入實例內:
Put p = new Put(〈主鍵值〉);
p.add(〈列族名〉, 〈列名〉,〈版本號〉, 〈值〉);
④ 將數據寫入Hbase:
table.put(p);
使用這種方法遷移數據可以完成遷移過程,滿足各種特殊需求。但是,當遷移的數據量大時,該方法的性能較低,且有一定的編碼工作量。
2) 使用“Hadoop生態系統”中各項目提供的工具
Sqoop[9]是一個用于在Hadoop和關系型數據庫之間傳輸數據的工具,對主流的關系型數據庫如MySQL、Oracle等均能支持。使用Sqoop進行數據遷移的過程如下:
① 安裝Sqoop,并在sqoop-env.sh中加入Hadoop集群的配置參數:
HADOOP_COMMON_HOME=〈Hadoop 安裝路徑〉
HADOOP_MAPRED_HOME=〈Hadoop MapReduce安裝路徑〉
HBASE_HOME=〈Hbase安裝路徑〉
② 復制hadoop的 core包以及關系型數據庫的JDBC驅動包到sqoop-lib目錄下。
③ 使用 sqoop-import命令進行數據遷移。命令格式如下:
./sqoop-import --connect 〈JDBC Url〉 --table 〈源表名〉 --hbase-create-table --hbase-table 〈Hbase表名〉--column-family 〈列族名〉 --hbase-row-key 〈鍵字段名〉 --split-by 〈字段名〉 --username 〈數據庫用戶名〉--P 〈數據庫密碼〉 --compression-codec 〈壓縮方式〉–z
其中:
--connect 〈JDBC Url〉:指定要遷移數據的來源數據庫;
--table 〈源表名〉:指定源數據庫中要遷移數據的表;--hbase-create-table:表示要在HBase中建立表;--hbase-table 〈Hbase表名〉:指定數據要復制到Hbase中的目標表名稱;
--column-family 〈列族名〉:指定要在目標表中建立的列族名稱;
--hbase-row-key 〈鍵字段名〉:指定源數據表的哪個字段作為目標表的鍵;
--split-by 〈字段名〉:指定根據源數據表的哪個字段對源數據進行區域切分;
--compression-codec 〈壓縮方式〉:指定壓縮方式;
-z:表示采用壓縮方式。
采用該方法遷移數據,其遷移過程使用MapReduce實現了分布并行,當遷移數據量較大時有較好的性能表現。
3) 其它方法
一些軟件產品基于分布式數據庫作了進一步封裝,可將數據遷移到這些產品上,間接實現數據到分布式數據庫的遷移。
例如開源項目Honeycomb[10],它是一個以Hbase為后端的MySQL存儲引擎,能夠使MySQL用Hbase存儲數據,用戶可以通過MySQL用SQL語言訪問數據。使用MySQL+Honeycomb進行數據遷移的方法如下:
① 安裝MySQL+Honeycomb。
② 在Hbase的配置文件hbase-site.xml中增加以下配置:

③ 修改Honeycomb的配置文件honeycomb.xml,將hbase.zookeeper.quorum節點的內容改為與Hbase相同的配置。
④ 啟動 MySQL+Honeycomb,并在 MySQL中建立與源數據表相同結構的表:
create table 〈表名〉 (……表結構……) character set utf8 collate utf8_bin engine=honeycomb;
⑤ 使用MySQL遷移工具或其它ETL工具將源數據庫的數據復制到 MySQL+Honeycomb中對應的表里。
3.1.2 文件遷移
Hadoop客戶端包里的 org.apache.hadoop.fs.FileSystem類提供了必要的方法,可調用于編寫Java程序,程序邏輯如下:
1) 獲取 org.apache.hadoop.fs.FileSystem 類的實例:
FileSystem fs = FileSystem.get(〈HDFS URI〉,new org.apache.hadoop.conf.Configuration ());
2) 獲取輸出流:
fs.create(new org.apache.hadoop.fs.Path(〈HDFS 路徑〉), true);
3) 打開源文件獲取輸入流,讀取數據并寫入到輸出流中。
遷移時要記錄好遷移前后文件路徑的對應關系,以便修改應用進行訪問。
應用數據遷移到Hadoop平臺后,訪問方式也發生了改變,需要相應修改應用對數據的訪問邏輯。
3.2.1 關系型數據訪問
“Hadoop生態系統”中的一些開源項目為用戶提供了類似 SQL語言的數據訪問方式,降低了應用遷移的難度。下面列出幾個項目和 SQL語言的主要差異以及遷移要點:
1) Hive[11]
通過Hive訪問數據有2個途徑:一是通過Hive提供的 JDBC驅動類 org.apache.hadoop.hive.jdbc.HiveDriver進行訪問;二是通過 Hive客戶端類org.apache.hadoop.hive.service.HiveClient進行訪問。
將SQL語句修改為Hive提供的查詢語言HiveQL需要:
① 查詢語句中對列取別名必須加上關鍵字“as”;② 表內連接查詢必須用關鍵字“join”;
③ “in”子查詢改為使用“left semi join”。例如:

④ 插入語句按以下語法修改:

⑤ Hive暫不支持事務,需要把事務相關的代碼去除。
2) Phoenix[12]
應用可通過 Phoenix提供的 JDBC驅動類com.salesforce.phoenix.jdbc.PhoenixDriver對數據進行訪問。應用需要調整的地方包括:
① Phoenix暫不支持表連接查詢和嵌套子查詢,需將SQL拆成多條分別執行;
② Update和Insert合并成Upsert,語法如下:Upsert into 〈表名〉 (〈列名 1〉,〈列名 2〉,……)values (〈值 1〉,〈值 2〉,……);
③ Phoenix暫不支持事務,需要把事務相關的代碼去除;
3) Honeycomb
應用可通過MySQL提供的JDBC驅動類com.mysql.jdbc.Driver對數據進行訪問。應用需要調整的地方包括:
① Honeycomb目前只支持UTF-8編碼,應用需要相應更改;
② Honeycomb對數據表名大小寫敏感,應用需要相應更改;
③ Honeycomb暫不支持事務,需要把事務相關的代碼去除。
3.2.2 文件訪問
Hadoop客戶端包里的 org.apache.hadoop.fs.FileSystem類為用戶訪問HDFS中的文件提供了必要的方法,修改應用程序:
1) 將調用 java.io.File類的地方改為調用org.apache.hadoop.fs.FileSystem類相應的方法,涉及的文件路徑改為HDFS中的路徑;
2) 將使用 java.io.FileInputStream 的地方改為使用org.apache.hadoop.fs.FileSystem的open()方法獲取輸入流;
3) 將使用java.io.FileOutputStream的地方改為使用 org.apache.hadoop.fs.FileSystem 的 create()或append()方法獲取輸出流。
在實際遷移過程中,為降低代碼修改的工作量,可以編寫代理類分別繼承于 java.io.File、java.io.FileInputStream和java.io.FileOutputStream,由代理類完成對Hadoop客戶端包相關類的調用,然后通過動態代理或通過 ASM[13]框架修改字節碼,替換掉應用中對 java.io.File、java.io.FileInputStream 和 java.io.FileOutputStream類的調用。
通過前面敘述的各種技術方法能夠實現將典型的Java EE企業級應用功能遷移到Hadoop平臺上,但實施成本、約束條件和遷移效果等有所不同。各方法的簡要對比如表2、表3所示。

表2 關系型數據庫遷移技術對比

表3 關系型數據訪問邏輯遷移技術對比
對于文件遷移的方法,一般都是通過調用Hadoop客戶端包里提供的org.apache.hadoop.fs.FileSystem等類實現,在此不作展開比較。
在遷移時,需結合應用本身的實際情況以及各種遷移方法的特點,確定合理的遷移策略,力圖使遷移達到代價最小化和收益最大化。遷移策略應遵循以下幾個步驟制定:
1) 評估應用的數據量
Hadoop平臺進行分布式計算時要產生跨多機數據流處理的開銷,當處理的數據量較小時,這種開銷的占比是不可接受的。因此,對數據量未達到TB級的功能應考慮不作遷移,以獲得更佳的性能。對數據量較大的應用繼續進行下一步判斷。
2) 確定是否擁有應用系統源代碼
是否擁有應用系統源代碼決定了遷移工作開展的深度。若不具有應用系統源代碼,應選擇不需要大量修改應用系統代碼的遷移技術方案:對結構化數據采用 Honeycomb進行遷移,對文件數據采用動態代理替換應用原有的訪問邏輯。對于擁有源代碼的應用系統繼續進行下一步判斷。
3) 平衡應用性能要求與遷移成本
在數據量極大的場景下,各種遷移技術的性能表現不一,總的來說遷移工作量較小的技術其性能也相對較差。針對不同的性能成本比要求,采用的遷移策略如表4所示。
以某OA系統為例子驗證Java EE企業級應用遷移到Hadoop平臺的可行性。進行遷移前已獲得該系統的源代碼,分析其數據訪問邏輯結果如下:
1) 對結構化數據的訪問兼容MySQL;
2) 文件數據分為業務數據和配置文件2類;
3) 系統存在用戶上傳文件的功能,該功能使用Apache的commons-fileupload.jar實現。
針對應用的特點采用如下遷移方法:

表4 性能成本比與遷移策略
1) 對結構化數據采用MySQL+Honeycomb進行遷移;
2) 調用Hadoop客戶端包里的org.apache.hadoop.fs.FileSystem類將文件數據中的業務數據復制到HDFS中,并記錄復制前后的目錄對應關系;
3) 編寫代理類,分別繼承于java.io.File、java.io.FileInputStream、java.io.FileOutputStream、java.io.FileReader和java.io.FileWriter,覆蓋其中的公有方法,將對文件系統的訪問改為對 org.apache.hadoop.fs.FileSystem類相應方法的調用;
4) 對文件數據中的業務數據的訪問邏輯通過ASM框架修改字節碼替換為對代理類的訪問;
5) 對文件數據中的配置文件的訪問邏輯不作更改;
6) 對Apache的commons-fileupload.jar中讀寫臨時文件的邏輯不作更改,僅將 write方法中對java.io.FileOutputStream類的調用通過ASM框架修改字節碼替換為對代理類的訪問。
修改完成后運行系統,確認結構化數據均存放在Hbase中,業務數據文件均正確存放在HDFS中,應用系統各功能運行正常,說明Java EE企業級應用遷移到Hadoop平臺是可行的。
Hadoop平臺及相關的開源項目為應用遷移提供了豐富的支持,借助本文列舉的各種技術方法能夠實現將典型的Java EE企業級應用遷移到Hadoop平臺上。但同時應注意到各種遷移技術均有其優缺點,在實際進行應用遷移時,要充分考慮應用數據量、性能要求和遷移工作量等因素,選擇合適的技術方案,保障遷移的成功,使 Java EE企業級應用真正享受到
Hadoop平臺的強大功能。
[1]Gartner Group: IT Glossary - enterprise application software[EB/OL]. [2014-02-13]. http://www.gartner.com/it-glossary/enterprise-application-software.
[2]Martin Fowler: Patterns of Enterprise Application Architecture[M]Addison-Wesley Educational Publishers Inc, 2002.
[3]Java Community Process: JSR-000342 JavaTM Platform,Enterprise Edition 7 (Final Release) [EB/OL]. [2014-02-13].https://www.jcp.org/aboutJava/communityprocess/final/jsr342/index.html.
[4]Oracle Corporation: The Java Pet Store Referance Application[EB/OL].[2014-02-13]. http://www.oracle.com/technetwork/java/index-136650.html.
[5]Apache Foundation: Apache Hadoop [EB/OL]. [2014-02-13].http://hadoop.apache.org.
[6]Kai W?hner: Spoilt for Choice – How to choose the right Big Data / Hadoop Platform [EB/OL]. 2013.9 [2014-02-13].http://www.infoq.com/articles/BigDataPlatform.
[7]Apache Foundation: Apache Hbase [EB/OL]. [2014-02-13].http://hbase.apache.org.
[8]Apache Foundation: Apache Cassandra [EB/OL]. [2014-02-13].http://cassandra.apache.org.
[9]Apache Foundation: Apache Sqoop [EB/OL]. [2014-02-13].http://sqoop.apache.org.
[10]Altamira Corp: Honycomb [EB/OL]. [2014-02-13].https://github.com/altamiracorp/honeycomb.
[11]Apache Foundation: Apache Hive [EB/OL]. [2014-02-13].http://hive.apache.org.
[12]Apache Foundation: Apache Phoenix [EB/OL]. [2014-02-13].http://phoenix.incubator.apache.org.
[13]E. Kuleshov: Using the ASM Framework to Implement Common Java Bytecode Transformation Patterns:proceedings of the Sixth International Conference on Aspect-Oriented Software Development, Vancouver, Canada,March 2007[C/OL]. [2014-02-13]. http://asm.ow2.org/current/asm-transformations.pdf.