用 WebSphere eXtreme Scale、Informix 和 DB2 进行 OpenJPA 缓存,第 1 部分: 用 hellojpa 缓存 POJO

使用 IBM WebSphere eXtreme Scale、Informix 和 DB2

OpenJPA™ 是一个 Apache 持久化项目。OpenJPA 的一个优秀特性是让您在无需改变应用程序代码的情况下即可使用 Java™ Cache加速查找并减少后端数据库上的负载。本文将向您展示如何安装、配置和试用 IBM® WebSphere® eXtreme Scale 产品与 OpenJPA 。而这个实践的过程无需花费任何额外的费用,因为 XS 缓存有免费的评估版可用。代码无需更改,配置文件也只是需要几行代码,OpenJPA 的性能即可显著提高。

Marty Lurie, 系统工程师, IBM

Marty Lurie 的计算机生涯始于纸带时期,那时他在 IBM 1130 上尝试编写 Fortran 程序。他的 “正业” 是为 IBM 软件部门做系统工程工作;不过,如果您再多追问几句,他就会承认他主要在玩计算机。他最喜欢的程序就是他自己编写的那个用来将其 Nordic Track 与笔记本连接的程序(这台笔记本重量减少了两磅,减少了 20% 的重量)。Marty 是 IBM 认证的 DB2 DBA、IBM 认证的业务智能解决方案专家、Informix 认证的专家。


developerWorks 投稿作者

2011 年 5 月 17 日

免费下载:IBM® Informix® 11.7 试用版(包括 Ultimate Edition、Developer Edition 和 Innovator-C Edition)
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

概览

想要不更改代码就能获得显著的性能改进?这是缓存的目标所在。但它真能实现这个目标么?OpenJPA 是一个 Apache 持久化项目。OpenJPA 的一个优秀特性是让您在无需改变应用程序代码的情况下即可使用 Java Cache 加速查找并减少后端数据库上的负载。本文将向您展示如何安装、配置和试用 IBM WebSphere eXtreme Scale (XS) 产品与 OpenJPA 。而这个实践的过程无需花费任何额外的费用,因为 XS 缓存有免费的评估版可用。相关的下载链接如下所示。

您可以使用 WebSphere eXtreme Scale (WXS) 代替 OpenJPA 内的缓存来充分利用嵌入的、嵌入分区的远端缓存。

本文是两篇系列文章中的第一篇。本文将会讨论在没有应用服务器的情况下使用 OpenJPA 和 eXtreme Scale。本文的重点是 Plain Old Java Objects (POJO) 和 JDK。第 2 部分将会给出在有应用服务器的情况下的一个示例并尝试类似的测试。

您可以按如下步骤尝试 OpenJPA、IBM WebSphere eXtreme Scale、Informix 和 DB2 的安装、配置和测试:

  1. 进行如下的下载、安装和配置:
    • OpenJPA
    • WebSphere Extreme Scale Cache
    • Informix Innovator C Edition 或 DB2 Express C
  2. 测试 OpenJPA,无缓存。
  3. 将配置修改为使用 WebSphere eXtreme Scale 缓存。
  4. 测试 OpenJPA,有缓存。
  5. 修改 OpenJPA 示例来充当一个简单的测试装具模块(test harness)。
  6. 修改 OpenJPA 配置来连接到 Informix 或 DB2。
  7. 分析结果。

现在就开始享受新发现的性能改进吧!

为了避免混淆,先说明如下:OpenJPA 是一个 Apache 项目。WebSphere eXtreme Scale、Informix 和 DB2 是 IBM 产品。Informix 和 DB2 有许可证免费的下载版本,而 WebSphere eXtreme Scale 则只有免费的试用版下载。试用期结束后,必须购买许可证才可继续使用 XS。问题解决了,让我们回到技术上来!

下载和安装

下载和安装并不太困难。您将需要先在 IBM 网站上注册。为进行本文所需的下载而获得一个 ID 是不需要费用的。所需链接如下:

如只是想尝试 OpenJPA 和 XS 缓存,则无需下载数据库。在进行性能测试时,若能看到用户、SQL、缓冲池命中率等,无疑更为有趣。这里的示例均来自 Informix 和 DB2。我们鼓励您自己挑选一个并开始尝试。选择后,就可以向前跳转来使用与 OpenJPA 捆绑的 Derby 数据库。

由于目前已经有很多资料讲述如何安装此软件,因此本文不再赘述。下载后,若想获得更多信息,可以查找有关安装向导和其他文档的链接。

完成全部下载后,Linux 系统上的目录列表应该类似于清单 1,也可以使用 md5sum 来确认目录列表如否如您所愿。

清单 1. Linux 系统上的下载目录列表
-rw-r--r-- 1 lurie lurie  29418160 2010-12-31 16:47 apache-openjpa-2.0.1-binary.zip
-rw-r--r-- 1 lurie lurie 427579388 2010-12-31 17:35 db2exc_972_LNX_x86.tar.gz
-rw-r--r-- 1 lurie lurie  69655311 2010-12-31 17:08 extremescaletrial710.zip
-rw-r--r-- 1 lurie lurie 356157440 2010-12-31 17:34 iif.11.70.UC1IE.Linux-RHEL5.tar

将这些文件解压缩到分级目录。表 1 列出了启动每个安装所需的软件和安装命令。

表 1. 安装快速入门, .sh 命令是针对 UNIX/Linux 的,.bat 是针对 Windows
软件安装或执行命令
OpenJPAapache-openjpa-2.0.1/examples/hellojpa/ant
WebSphere eXtreme ScaleObjectGrid/gettingstarted/env.sh, runcat.sh, runcontainer.sh c1, runclient.sh i hello world
Informix Dynamic Serversudo informix/ids_install
DB2expc/db2setup

遵循针对 Informix 和 DB2 的默认设置。让脚本为您创建一个示例数据库实例。DB2 的图形入口点如图 1 所示。

图 1. DB2 的安装入口点
此屏幕快照显示了 DB2 设置 launchpad

无缓存的情况下测试 OpenJPA

运行 OpenJPA 提供的 ant 脚本的结果如清单 2 所示。虽然缓存尚未引入,但创建一个表也只花了 115 毫秒。基于持久化一个 Java 对象,插入一行花了 12 毫秒。而将这个对象读回则花了 1 毫秒。也许,说这些数据令人兴奋未免有些夸大其辞,但随着我们向前进展,事情会逐渐有趣起来。

清单 2. 来自基线测试的 OpenJPA 输出
lurie@merlin:/work/dwOpenJPA/work/openjpa/apache-openjpa-2.0.1/examples/hellojpa$ ant
Buildfile: build.xml

pre-compile:

compile:
    [javac] Compiling 2 source files

run:
     [java] 4232  hellojpa  TRACE  [main] openjpa.jdbc.SQL - t 8204368, conn 15666395 
executing stmnt 22424679 CREATE TABLE Message (id BIGINT NOT NULL, created TIMESTAMP, 
message VARCHAR(255), PRIMARY KEY (id))

     [java] 4347  hellojpa  TRACE  [main] openjpa.jdbc.SQL - t 8204368, conn 15666395 
[115 ms] spent

     [java] 4683  hellojpa  TRACE  [main] openjpa.jdbc.SQL - t 8204368, conn 15975876 
executing prepstmnt 29412736 INSERT INTO Message 
(id, created, message) VALUES (?, ?, ?) [params=?, ?, ?]

     [java] 4695  hellojpa  TRACE  [main] openjpa.jdbc.SQL - t 8204368, conn 15975876 
[12 ms] spent

     [java] 4969  hellojpa  TRACE  [main] openjpa.jdbc.SQL - t 8204368, conn 20336357 
executing prepstmnt 32685187 SELECT t0.id, t0.created, t0.message FROM Message t0

     [java] 4970  hellojpa  TRACE  [main] openjpa.jdbc.SQL - t 8204368, conn 20336357 
[1 ms] spent

     [java] Hello Persistence! (created on: Mon Jan 03 13:18:48 EST 2011)

BUILD SUCCESSFUL
Total time: 10 seconds

将配置修改为使用 WebSphere eXtreme Scale 缓存

下一步是在不对 Java 代码进行更改的情况下激活 WebSphere eXtreme Scale 缓存!做法是:修改 OpenJPA persistence.xml 文件,以及将 XS jar 添加到 build.xml 的 classpath 内,如清单 3 和清单 4 所示。请注意 hellojpa 构建文件使用的是父目录内的构建文件。

在使用 eXtreme Scale 缓存时,请确保使用 IBM JDK。

清单 3. 对 apache-openjpa-2.0.1/examples/META-INF/persistence.xml 的修改
        <property name="openjpa.ConnectionPassword" 
                value="secret"/>


		<property name="openjpa.DataCache"
	          value="com.ibm.websphere.objectgrid.openjpa.ObjectGridDataCache(
       		   ObjectGridName=BasicTestObjectGrid,ObjectGridType=EMBEDDED,
       		   maxNumberOfReplicas=4)"/>
		<property name="openjpa.QueryCache"
          	value="com.ibm.websphere.objectgrid.openjpa.ObjectGridQueryCache()"/>
		<property name="openjpa.RemoteCommitProvider" value="sjvm"/>



        <properties>
    <persistence-unit>
清单 4. 对 apache-openjpa-2.0.1/examples/build.xml 的修改
 <fileset dir="${root}">
            <include name="openjpa-all-*.jar"/>
            <include name="lib/derby*.jar"/>
        <fileset>
        <!-- add path to the eXtreme Scale jar file -->
         <pathelement path="xs"/>
        <fileset dir="/home/lurie/tmp/xs71/ObjectGrid/lib">
            <include name="objectgrid.jar"/>
        <fileset>
        <!-- end of mods to find  eXtreme Scale jar file -->

    </path>

现在缓存已启用,对 Java 程序则没有进行任何更改,缓存就已经准备就绪了。

缓存启用后运行 hellojpa

好了!现在是时候运行示例了。在这之前,确保将路径配置为使用 IBM JVM,然后通过在命令行键入 ant 重新运行这个示例,如清单 5 所示。

清单 5. 在启用了 eXtreme Scale 缓存的情况下运行 OpenJPA 示例程序
/work/dwOpenJPA/work/openjpa/apache-openjpa-2.0.1/examples/hellojpa$ ant
[java]  ReplicatedPar I CWOBJ1511I: BasicTestObjectGrid:IBM_SYSTEM_ENTITYMANAGER_MAPSET:0
		 (primary) is open for business.
     [java]  ReplicatedPar I CWOBJ1511I: BasicTestObjectGrid:MAPSET_BasicTestObjectGrid:0
		 (primary) is open for business.
     [java]  ObjectGridRes I CWOBJ3134I: The ObjectGrid type is embedded and the default 
		maximum number of replicas is 47.  The maximum number of replicas must be 
		greater than or equal to the number of JVMs in the system.
     [java] hellojpa  TRACE  [P=324170:O=0:CT] openjpa.jdbc.SQL - <t 1720215176, 
		conn 362616221> executing prepstmnt 652224224 INSERT INTO Message 
		(id, created, message) VALUES (?, ?, ?) [params=?, ?, ?]
     [java] hellojpa  TRACE  [P=324170:O=0:CT] openjpa.jdbc.SQL - <t 1720215176, 
		conn 362616221> [212 ms] spent
... lines deleted ...
     [java] hellojpa  TRACE  [P=324170:O=0:CT] openjpa.jdbc.SQL - <t 1720215176, 
		conn 696330625> executing prepstmnt 856306442 SELECT t0.id, t0.created, 
		t0.message FROM Message t0
     [java] hellojpa  TRACE  [P=324170:O=0:CT] openjpa.jdbc.SQL - <t 1720215176, 
		conn 696330625> [1 ms] spent

其结果与第一种情况无异。为什么?如果数据库内只有一行,那么有无缓存的意义不大。如果这里所展示的对您而言太明显不过,那么就对不起了。为了让事情更为有趣,我们需要一个更好的包含了几千行代码的测试。

您可能厌烦了所有的 SQL TRACE 消息在您屏幕上滚动。为了切换到只显示警告消息,可以对 build.xml 文件进行编辑,使其类似如下所示: value="DefaultLevel=WARN,SQL=WARN"

修改 OpenJPA 示例充当一个简单的测试装具模块:向 Main.java 添加循环

对于产品应用程序,研究预期的工作负载并开发一个最接近现实的测试装具模块十分关键。用大量的仿真历史数据,比如一年的数据,对事务系统进行足尺测试是一个基本常识,除非您想要产品系统出现紧急情况。

在本例中,您可以简单创建一个循环来插入很多对象,然后再将这些对象读回。虽然它将展示缓存的有效性,但是只有在产品环境中运行 helloJPA 它才能代表一个合适的测试装具模块。

清单 6 显示了对 Main.java 程序的修改,以及如何插入 100 行。这不是什么大的挑战。由于此次测试关乎的是性能,所以您将需要在下一节内将 Informix 添加到配置内。Derby 对于开发而言很好,但如果就起重而言,Informix 无疑是更好的选择。样例文件还包含了在 DB2 上运行所需的配置。在用 Informix 进行测试时,此循环会插入更多行,这也让它变得更为有趣。

清单 6. 修改 openjpa Main.java 加入 100 行
        EntityManager em = factory.createEntityManager();

        // *** loop here to put a bunch of rows in the database
            for ( int i=0; i<100;i++)
        {
        
        // *** don't forget to put a closing } below

        // Begin a new local transaction so that we can persist a new entity
        em.getTransaction().begin();

        // Create and persist a new Message entbity
        em.persist(new Message("Hello Persistence!"));

        // Commit the transaction, which will cause the entity to
        // be stored in the database
        em.getTransaction().commit();

        // *** end of loop
        }

如果您只需读取这些条目一次,那么缓存实际上帮助不大。如清单 7 所示修改 Main.java 来读取并报告您已经持久到磁盘的两个传递的时机。

清单 7. Main.java 进行了被持久化对象的两次读取
 // Create a fresh, new EntityManager
        EntityManager em2 = factory.createEntityManager();

        // **** set up a timer of how long the queries take
        long starttm = System.currentTimeMillis();


        // Perform a simple query for all the Message entities
        Query q = em2.createQuery("select m from Message m");

        // Go through each of the entities and print out each of their
        // messages, as well as the date on which it was created
        for (Message m : (List<Message> q.getResultList()) {

        // *** better comment this out or 20,000 prints are coming back!
        //  System.out.println(m.getMessage()
        //      + " (created on: " + m.getCreated() + ")");

        }
        // *** report on the first run
       long end1sttm = System.currentTimeMillis();
       System.out.println("\n\nfirst run took: " + (end1sttm-starttm) +
		"  millisec\n\n\n");

        
        // **** second run should be in local cache
        // Perform a simple query for all the Message entities
        Query q2 = em2.createQuery("select m from Message m");

        // Go through each of the entities and print out each of their
        // messages, as well as the date on which it was created
        for (Message m : (List<Message> q2.getResultList()) {
         //System.out.println(m.getMessage() 
		//+ " (created on: " + m.getCreated() + ")");
        }
        long end2ndtm = System.currentTimeMillis();
        System.out.println("\n\nsecond run, from cache took: " 
		+ (end2ndtm-end1sttm) + "  millisec\n\n\n");


        // Again, it is always good to clean up after ourselves
        em2.close();

结果如清单 8 所示,显示了使用 WebSphere eXtreme Scale Cache 后的显著加速。并且请记住,其中完全没有涉及任何的应用程序代码更改!我知道因添加循环来生成较重的工作负载,您还是会认同我所说的没有进行代码更改

清单 8. 测试运行的输出:联合使用 WebSphere eXtreme Scale 与 Derby 数据库而获得的明显加速
 [java] [1/26/11 11:00:11:776 EST] 3a883a88 SystemOut     O 
     [java] 
     [java] first run took: 3761  millisec
     [java] 
     [java] 
     [java] 
     [java] [1/26/11 11:00:11:865 EST] 3a883a88 SystemOut     O 
     [java] 
     [java] second run, from cache took: 89  millisec
     [java] 
     [java]

性能的改善超过 40 倍:3761 毫秒对 89 毫秒。当然,这取决于硬件,所以您的具体数据可能会与此不同。 还有其他几个环境因素,也会影响性能。比如,如果您在调整/调换任何相关的性能,那么数据就没有讨论的意义了。

修改 OpenJPA 配置连接到 Informix 或 DB2

一个更为实际的测试是对一个具有行业强度的数据库使用 OpenJPA。好的消息是把数据库从 Derby 更改为 Informix 只需对 build.xml 文件进行一些简单的修改,如清单 9 所示。不仅数据库的指标更改了,并且还要求有到 jdbc jar 的路径。

清单 9. 修改 build.xml 以使用 Informix Dynamic Server
build.xml

<project default="usagewarning">>

    <property name="parent" value="${basedir}/.."/>
    <property name="root" value="${parent}/.."/>

    <!-- database connection properties
    <property name="dbdriver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
    <property name="dburl"
        value="jdbc:derby:${basedir}/${example}-database;create=true"/>
    <property name="dbuser" value=""/>
    <property name="dbpass" value=""/>

-->
<!-- database connection properties -->
<!-- informix instead of derby -->

    <property name="dbdriver" value="com.informix.jdbc.IfxDriver"/>
    <property name="dburl"
        value="jdbc:informix-sqli://merlin:54321/idsopenjpa:informixserver=ids115"/>
    <property name="dbuser" value="informix"/>
    <property name="dbpass" value="idsr0cks"/>

    <target name="usagewarning">


PATH CHANGES

<path id="classpath"
        description="The classpath to use for compiling and running">
        <pathelement path="${parent}"/>
        <fileset dir="${root}">
            <include name="**/*.jar"/>
        </fileset>
        <pathelement path="xs"/>
        <fileset dir="/home/lurie/tmp/xs71/ObjectGrid/lib">
            <include name="objectgrid.jar"/>
        </fileset>
        <pathelement path="ifx"/>
        <fileset dir="/opt/IBM/informix/jdbc/lib">
            <include name="ifxjdbc.jar"/>
        </fileset>
    </path>

Informix Configuration

Don't create any tables, just a database.  It seems almost too easy.

informix@merlin:~$ dbaccess - - 
> create database idsopenjpa with buffered log;

Database created.

结果分析

它真的变快了么?如果没有变快,阅读本文岂不是浪费时间!如清单 10 所示,对 Main.java 程序进行修改以插入 10,000 行。Informix 在 1 秒内就能制作出 10,000 行,因为它具有高级的缓冲池管理和行业强度的架构。此外,通过将数据保存在地址空间与 Java 应用程序相同的缓存内,也会显著提高性能。对于任何一个数据库而言,能够突破 49 毫秒的缓存存取底线同时又能完成 TCP/IP 的双向遍历都是一个极大的挑战。

清单 10. 测试运行的输出:联合使用 WebSphere eXtreme Scale 与 Informix 数据库而获得的明显加速
  [java] [1/26/11 17:28:38:751 EST] 72887288 SystemOut     O 
     [java] 
     [java] first run took: 1096  millisec rows processed= 10000
     [java] 
     [java] 
     [java] 
     [java] [1/26/11 17:28:38:800 EST] 72887288 SystemOut     O 
     [java] 
     [java] second run, from cache took: 49  millisec
     [java]

如果您对数据库层面发生的事情感兴趣,那么可以参看清单 11 所示的这个模式。

清单 11. Informix 数据库模式
create table "informix".message 
  (
    id decimal(32,0) not null ,
    created datetime year to fraction(3),
    message varchar(255),
    primary key (id) 
  );

结论:享受您新发现的性能改进吧!

本文通过对 OpenJPA、 WebSphere eXtreme Scale 及 Java 缓存与 Informix Dynamic Server 数据库结合使用的快速介绍让您对它们有了基本的了解。所提供的样例文件包括上述的所有代码,当然也包括了用 DB2 做相应实现的内容。

请您自己尽情尝试吧!

如果您想要了解有关此主题的更多信息,那么千万不要错过 Informix International Users Group(参见 参考资料 获得更多细节),在那里 Marty 继续为我们阐述这个主题。


下载

描述名字大小
本文的示例文件sampleFiles.tar50B

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management, WebSphere, Java technology, Open source
ArticleID=659794
ArticleTitle=用 WebSphere eXtreme Scale、Informix 和 DB2 进行 OpenJPA 缓存,第 1 部分: 用 hellojpa 缓存 POJO
publish-date=05172011