如何从 JRuby 应用程序访问 Oracle Coherence 缓存

作者:Pas Apicella

作为 Coherence Extend 客户端访问 Coherence 网格有一些显著的性能优势。

2011 年 2 月发布

Oracle Coherence 内存中数据网格是一个数据管理系统,它为多台服务器间共享的应用程序对象提供 服务,旨在满足这些对象对快速响应、极高的吞吐量、可预测的伸缩性、持续的可用性和信息可靠 性的要求。凭借这些功能,Oracle Coherence 非常适用于计算密集型的会话状态中间层应用程序。 Coherence 旨在运行于应用程序层,通常与应用程序本身一起在进程中运行(例如在应用服务器集 群中)。

以下方法文档介绍如何从 JRuby 作为 Coherence Extend 客户端使用可移植对象格式 (POF) 访问 Coherence 缓存。我们使用 extend 客户端和 POF 的原因是:

  • 示例应用程序是一个控制台应用程序,每天多次连接/断开缓存。Extend 客户端通过连接到代 理服务器本身,可避免集群成员信息维护所需的开销。(见下图;关于此架构的更多信息可在此处找到。)
  • 使用 extend 客户端时,默认情况下禁用存储,因此可避免在本地存储数据所需的任何开 销。
  • 使用 POF 有许多优点,如性能优点、语言无关性等等,即使在本例中我们是从支持 Java 的客 户端来使用它。在 Coherence 中,由于数据需要在网络中移动,因此序列化(将对象编码成二进制 文件格式的过程)是其中的一个重要组件。POF 的设计使得它在空间和时间上效率极高,它已成为 与 Coherence 一起工作时的基本元素。(有关 POF 的更多信息,可以查看这里 。)

jruby-coherence-

f1

本演示将使用大家熟悉的 HR 模式数据,此数据从 Oracle 数据库 加载到 Coherence 集群中。然后我们将从 JRuby 脚本作为一个 extend 客户端来访问集群数据, 以避免加入集群作为其成员的开销。

软件要求

可以使用以下软件:

Oracle Database 11g 第 2 版 Oracle Database 软件下载
Oracle Coherence for Java 3.6.1 版 Oracle Coherence 软件下载
JDK 1.6 Java SE 下 载
JRuby 1.5.6 jruby.org
Oracle Database 11g 第 2 版 JDBC 驱动程序 Oracle Database 11g 第 2 版 JDBC 驱动程序下载 ojdbc6.jar。可以从 JDBC 驱动程序下载页面下载适用于其他版本的 Oracle Database 或 JDK 的驱动程序。
Apache Ant apache.org 或通过操作系统程序包 管理程序
示例代码 可以从这里 下载示例代码。解压缩到主目录。这将创建两个目录:jruby_coherence 和 hr_demo


这些示例也适用于其他版本。

安装每个组件时需遵循推荐的安装说明。

演示安装

在一个终端窗口中,设置 Oracle 环境并验证已安装了 Oracle 标准的人力资源 (HR) 演示模式 。

$ sqlplus hr/welcome

[. . .]
SQL> select table_name from user_tables;

TABLE_NAME
------------------------------
COUNTRIES
JOBS
EMPLOYEES
LOCATIONS
DEPARTMENTS
JOB_HISTORY
REGIONS
      

如果没有该模式,请参阅 Oracle Database Sample Schemas 11g Release 2 (11.2) 指南中的 Installing the HR Schema

验证是否已在文件系统上解压缩 Oracle Coherence for Java 3.6.1:

$ ls -l $HOME/coherence
total 16
drwxr-xr-x 2 pas     usergrp 4096 Feb 14 13:07 bin
drwxr-xr-x 3 pas     usergrp 4096 Feb 14 13:07 doc
drwxr-xr-x 3 pas     usergrp 4096 Feb 14 13:07 lib
-rw-r--r-- 1 pas     usergrp  100 Nov  9 14:49 product.xml
      

验证是否已安装 JDK 1.6:

$ java -version
java version "1.6.0_23"
Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)
      

将 JRUBY_HOME 设置为 JRuby 的安装目录,并验证 JRuby 是否在路径中:

$ export JRUBY_HOME=$HOME/jruby-1.5.6
$ export PATH=$PATH:$JRUBY_HOME/bin
$ jruby -v

jruby 1.5.6 (ruby 1.8.7 patchlevel 249) (2010-12-03 9cf97c3) 
(Java HotSpot(TM) 64-Bit Server VM 1.6.0_23) [amd64-java]
      

需要在三个终端窗口中设置相同的环境,以便跟踪所设置的变量。

验证 Apache Ant 是否已安装并在路径中可用:

$ export PATH=$PATH:$HOME/apache-ant-1.8.2/bin
$ ant -version
Apache Ant(TM) version 1.8.2 compiled on December 20 2010
      

运行演示:安装 Coherence

编辑示例代码文件 jruby_coherence/build.properties 以定义运行演示所需的 Coherence 主 目录。如果计算机上的内存不足,也可以减小 JVM 的堆大小。

# oracle.coherence.home
#
oracle.coherence.home=/home/pas/coherence

# jvmargs
#
# JVM args to pass into the command at runtime to set heap size etc

jvmargs=-server -showversion -Xms512m -Xmx512m
      

编辑 jruby_coherence/src/db.properties 以连接 HR 数据库模式。仅当将数据从数据库加载 到缓存中时才需要这样做,因此这只需使用一次:

# db properties
dburl=jdbc:oracle:thin:@localhost/orcl
dbuser=hr
dbpassword=welcome
      

编辑 jruby_coherence/build.xml 并在 Run SECONDRun THIRD 注释中找到两个代理-主机设置。设置此值以指定您的计算机的节点主机名或 IP 地址:

  . . .
  <!-- Run SECOND
       Starts a storage disabled coherence proxy server node , enabling
       clients to access the coherence cluster. It does not store any data but
       is a member of the cluster to provide access to remote clients -->
  <target name="run-default-extend" depends="package" 
          description="Run a proxy server">
  . . .

      <sysproperty key="proxy.host" 

value="localhost"/>
  . . .
  <!-- Run THIRD
       This is the remote client node which loads data into the cache connecting
       to the proxy server node -->
  <target name="run-default-extend-client" depends="package" 
           description="Run the extend client to load data">
  . . .

      <sysproperty key="proxy.host" 

value="localhost"/>
  . . .
      

同时将 ojdbc6.jar 复制到解压缩的演示目录 jruby_coherence/lib 中:

$ cp ojdbc6.jar jruby_coherence/lib
$ ls -l jruby_coherence/lib
total 2128
-rw-r--r-- 1 pas usergrp 2152051 Oct 14 09:22 ojdbc6.jar
      

转到演示目录并启动缓存服务器。只需键入 ant,随即会运行该演示的 build.xml 中的默认 Ant 任务(在注释 Run FIRST 下)。这将启动缓存服务器节点。运行时不会返 回命令提示符。(注意:这是第一个启动缓存服务器的请求,在执行之前,必须在启动缓存服务器 之前编译所需的服务器/客户端类,然后将其打包成 oraclehrdemo.jar 文件。此客户端 JAR 文件 是必需的,因为它包含稍后将要执行的查询缓存数据所需的类和 XML 文件。)

$ cd jruby_coherence
$ ant

Buildfile: /home/pas/jruby_coherence/jruby_coherence/build.xml

init:
    [mkdir] Created dir: /home/pas/jruby_coherence/jruby_coherence/classes

compile:

. . .

package:
      [jar] Building jar: 

/home/pas/jruby_coherence/jruby_coherence/lib/oraclehrdemo.jar

run-default:
     [echo] Starting cache server with jvm args : -server -showversion 
            -Xms512m -Xmx512m
     [java] java version "1.6.0_23"
     [java] Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
     [java] Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)
     [java]

. . .

     [java]   (
     [java]   ClusterService{Name=Cluster, State=(SERVICE_STARTED, 
		STATE_JOINED), Id=0, Version=3.6, OldestMemberId=1}
     [java]   InvocationService{Name=Management, State=(SERVICE_STARTED), 
			Id=1, Version=3.1, OldestMemberId=1}
     [java]   PartitionedCache{Name=DistributedCache, State=(SERVICE_STARTED), 
		LocalStorage=enabled, PartitionCount=257, BackupCount=1, 
                AssignedPartitions=257, BackupPartitions=0}
     [java]   )
     [java]
     [java] Started DefaultCacheServer...
      

可以启动多个缓存服务器(甚至在多台计算机上)。对于此演示,我们只需一个缓存服务器节点 。

如果您遇到原因为“package oracle.jdbc.pool does not exist”的编译错误,请 确认是否已将 ojdbc6.jar 复制到 jruby_coherence/lib。

此时,我们将启动代理服务器。此服务器将禁用存储,只能用于为 Extend 客户端查询缓存。请 在启动缓存服务器的节点上启动代理服务器。有关更多信息,请参见《Oracle Coherence Client Guide Release 3.6.1》手册中的 Setting Up Coherence*Extend 一节。

Coherence 集群必须包括 extend 代理服务才能接受 extend 客户端连接,并且必须包括缓存, 以便客户端用来检索和存储数据。exted 代理服务和缓存都是在集群的缓存配置部署描述符文件中 配置。Extend 代理服务和缓存将作为缓存服务器 (DefaultCacheServer) 进程的一部分启动。

启动一个新的 shell,再次设置 JRUBY_PATH 和 PATH 环境变量。使用 ant 目标 run-default -extend 运行代理服务器节点,如下所示。同样,此操作不会返回命令提示符:

$ ant run-default-extend

Buildfile: /home/cjones/jruby_coherence/build.xml

init:

compile:

...

package:

run-default-extend:
     [echo] Starting cache server proxy with jvm args : 
                  -server -showversion -Xms512m -Xmx512m
     [java] java version "1.6.0_23"
     [java] Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
     [java] Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)
     [java]
     [java] 2011-02-14 16:38:44.205/0.832 Oracle Coherence 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded operational configuration from 
"jar:file:/home/cjones/coherence/lib/coherence.jar!/tangosol-coherence.xml"
     [java] 2011-02-14 16:38:44.263/0.890 Oracle Coherence 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded operational overrides from 
"jar:file:/home/cjones/coherence/lib/coherence.jar!/tangosol-coherence-override-

dev.xml"
     [java] 2011-02-14 16:38:44.274/0.901 Oracle Coherence 3.6.1.0 <D5> 
(thread=main, member=n/a): Optional configuration override 
"/tangosol-coherence-override.xml" is not specified
     [java] 2011-02-14 16:38:44.306/0.933 Oracle Coherence 3.6.1.0 <D5> 
(thread=main, member=n/a): Optional configuration override "/custom-

mbeans.xml" 
is not specified
     [java]
     [java] Oracle Coherence Version 3.6.1.0 Build 19636
     [java]  Grid Edition: Development mode
     [java] Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights 

reserved.
     [java]
     [java] 2011-02-14 16:38:45.081/1.708 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded cache configuration from 
"jar:file:/home/cjones/jruby_coherence/lib/oraclehrdemo.jar!/coherence-cache-

config.xml"
     [java] 2011-02-14 16:38:45.972/2.599 Oracle Coherence GE 3.6.1.0 <D4> 
(thread=main, member=n/a): TCMP bound to /130.35.70.193:8090 using SystemSocketProvider
     [java] 2011-02-14 16:38:49.439/6.066 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=Cluster, member=n/a): Created a new cluster "cluster:0xC4DB" with 

Member(Id=1, 
Timestamp=2011-02-14 16:38:45.981, Address=130.35.70.193:8090, MachineId=59329, 
Location=site:usdhcp.oraclecorp.com,machine:dhcp-5op3-5op4-west-130-35-70-

19,process:6490, 
Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=1, 

SocketCount=1) 
UID=0x822346C10000012E26C14DDDE7C11F9A
     [java] 2011-02-14 16:38:49.450/6.077 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=main, member=n/a): Started cluster Name=cluster:0xC4DB
     [java]
     [java] Group{Address=224.3.6.0, Port=36000, TTL=4}
     [java]
     [java] MasterMemberSet
[java] (
[java] ThisMember=Member(Id=1, Timestamp=2011-02-14 16:38:45.981,
Address=130.35.70.193:8090, MachineId=59329,
Location=site:usdhcp.oraclecorp.com,machine:dhcp-5op3-5op4-west-130-35-70- 19,process:6490,
Role=CoherenceServer)
[java] OldestMember=Member (Id=1, Timestamp=2011-02-14 16:38:45.981,
Address=130.35.70.193:8090, MachineId=59329, Location=site:usdhcp.oraclecorp.com,
machine:dhcp-5op3-5op4-west -130-35-70-19,process:6490, Role=CoherenceServer)
[java] ActualMemberSet=MemberSet(Size=1, BitSetCount=2
[java] Member(Id=1, Timestamp=2011-02-14 16:38:45.981, Address=130.35.70.193:8090,
MachineId=59329, Location=site:usdhcp.oraclecorp.com,
machine:dhcp-5op3-5op4-west-130-35-70- 19,process:6490, Role=CoherenceServer)
[java] )
[java] RecycleMillis=1200000
[java] RecycleSet=MemberSet(Size=0, BitSetCount=0
[java] )
[java] )
[java]
[java] TcpRing {Connections=[]}
[java] IpMonitor{AddressListSize=0}
[java] [java] 2011-02-14 16:38:49.518/6.145 Oracle Coherence GE 3.6.1.0 <Info> (thread=Cluster, member=1): Loaded POF configuration from "jar:file:/home/cjones/jruby_coherence/lib/oraclehrdemo.jar!/hr-pof- config.xml" [java] 2011-02-14 16:38:49.572/6.199 Oracle Coherence GE 3.6.1.0 <Info> (thread=Cluster, member=1): Loaded included POF configuration from "jar:file:/home/cjones/coherence/lib/coherence.jar!/coherence-pof-config.xml" [java] 2011-02-14 16:38:49.922/6.549 Oracle Coherence GE 3.6.1.0 <D5> (thread=Invocation:Management, member=1): Service Management joined the cluster with senior service member 1 [java] 2011-02-14 16:38:50.397/7.024 Oracle Coherence GE 3.6.1.0 <D5> (thread=DistributedCache, member=1): Service DistributedCache joined the cluster with senior service member 1 [java] 2011-02-14 16:38:50.923/7.550 Oracle Coherence GE 3.6.1.0 <Info> (thread=Proxy:ExtendTcpProxyService:TcpAcceptor, member=1): TcpAcceptor now listening for connections on 130.35.70.193:9099 [java] 2011-02-14 16:38:50.939/7.570 Oracle Coherence GE 3.6.1.0 <D5> (thread=Proxy:ExtendTcpProxyService:TcpAcceptor, member=1): Started: TcpAcceptor{Name=Proxy:ExtendTcpProxyService:TcpAcceptor, State=(SERVICE_STARTED), ThreadCount=5, HungThreshold=0, TaskTimeout=0, Codec=Codec(Format=POF), Serializer=com.tangosol.io.pof.ConfigurablePofContext, PingInterval=0, PingTimeout=0, RequestTimeout=0, SocketProvider=SystemSocketProvider, LocalAddress= [/130.35.70.193:9099], SocketOptions{LingerTimeout=0, KeepAliveEnabled=true, TcpDelayEnabled=false}, ListenBacklog=0, BufferPoolIn=BufferPool(BufferSize=2KB, BufferType=DIRECT, Capacity=Unlimited), BufferPoolOut=BufferPool(BufferSize=2KB, BufferType=DIRECT, Capacity=Unlimited)} [java] 2011-02-14 16:38:50.954/7.581 Oracle Coherence GE 3.6.1.0 <D5> (thread=Proxy:ExtendTcpProxyService, member=1): Service ExtendTcpProxyService joined the cluster with senior service member 1 [java] 2011-02-14 16:38:50.959/7.586 Oracle Coherence GE 3.6.1.0 <Info> (thread=main, member=1): [java] Services [java] ( [java] ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.6, OldestMemberId=1} [java] InvocationService{Name=Management, State=(SERVICE_STARTED), Id=1, Version=3.1, OldestMemberId=1} [java] PartitionedCache{Name=DistributedCache, State=(SERVICE_STARTED), LocalStorage=disabled} [java] ProxyService{Name=ExtendTcpProxyService, State=(SERVICE_STARTED), Id=3, Version=3.2, OldestMemberId=1} [java] ) [java] [java] Started DefaultCacheServer... [java]

从日志中的 MasterMemberSet 部分,可以看到该节点已加入集群并开始等待请求。在仍在运行 的缓存服务器节点的输出日志的末尾(第一个终端窗口),也可以看到新节点加入了集群:

     [java] 2011-03-07 15:33:09.132/1332.883 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=Cluster, member=1): Member(Id=2, Timestamp=2011-03-07 15:33:08.97, 
Address=10.0.2.15:8090, MachineId=2063, Location=process:7380, Role=CoherenceServer) 
joined Cluster with senior member 1
     [java] 2011-03-07 15:33:09.757/1333.506 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=Cluster, member=1): Member 2 joined Service Management with senior member 1
     [java] 2011-03-07 15:33:10.592/1334.341 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=Cluster, member=1): Member 2 joined Service DistributedCache with senior member 

1
     [java] 2011-03-07 15:33:10.947/1334.696 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=Cluster, member=1): Member 2 joined Service ExtendTcpProxyService with senior 

member 2


打开第三个终端窗口,再次设置环境。现在,运行 extend 客户端将数据加载到缓存中 。这只是将表 DEPARTMENTS 和 EMPLOYEES 加载到缓存中,提供一些数据让我们可以从 JRuby 进行 访问:

$ ant run-default-extend-client
Buildfile: /home/cjones/jruby_coherence/build.xml

init:

compile:

...   

package:

run-default-extend-client:
     [echo] Starting extend client with jvm args : -server -showversion -Xms512m -

Xmx512m
     . . .

     [java] Oracle Coherence Version 3.6.1.0 Build 19636
     [java]  Grid Edition: Development mode
     [java] Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights 

reserved.
     . . .
     [java] INFO: Connected to db with URL : jdbc:oracle:thin:@localhost/orcl
     [java] Mar 7, 2011 4:23:01 PM pas.au.coherence.hr.client.LoadDataIntoCoherence 
doLogMessage
     [java] INFO: DEPT CACHE size : 27
     [java] Mar 7, 2011 4:23:01 PM pas.au.coherence.hr.client.LoadDataIntoCoherence 
doLogMessage
     [java] INFO: EMP CACHE size : 107

BUILD SUCCESSFUL
Total time: 2 seconds
      

如果使用的是默认的模式数据,输出将显示有 27 条部门记录和 107 条员工记录加载到了缓存 服务器。

运行演示:从 JRuby 访问 Coherence

现在,我们可以创建一个 JRuby extend 客户端脚本,该脚本会将缓存中的一些数据显示到控制 台上。

将步骤 2.5 中创建的 oraclehrdemo.jar 复制到 hr_demo 目录:

$ cp ~/jruby_coherence/lib/oraclehrdemo.jar ~/hr_demo
      

查看示例文件 hr_demo/jruby_cohextendclient.rb 并根据系统的实际情况更改 Coherence jar 的位置。如果需要,同时更新 proxy.host:JRuby 脚本将作为 extend 客户端连接到代理服务器节 点,查询两个已知缓存的名称,并将缓存数据输出到控制台。

# jruby_cohextendclient.rb

require 'java'
require File.dirname(__FILE__) + '/oraclehrdemo.jar'
# Update for your environment
require '/home/cjones/coherence/lib/coherence.jar'  

import com.tangosol.net.CacheFactory
import com.tangosol.net.NamedCache
import java.lang.System
import java.lang.Integer

puts "*********************************************************"
puts "Coherence 3.6 Oracle HR Extend Client Example from JRuby"
puts "*********************************************************"

print "Started at ", Time.now, "\n"

begin

  # setup required properties to connect to proxy server as extend client
  System.setProperty("tangosol.coherence.cacheconfig", "client-cache-

config.xml")
  System.setProperty("tangosol.pof.enabled", "true")
  System.setProperty("tangosol.pof.config", "hr-pof-config.xml")
  System.setProperty("proxy.host", "localhost")  # Update   for your environment

  # get named caches
  depscache = CacheFactory.getCache("dep-cache")
  empscache = CacheFactory.getCache("emp-cache")

  #retrieve size of caches
  print "\nCache [depscache] size  = " , depscache.size()
  print "\nCache [empscache] size  = " , empscache.size() , "\n\n"

  #show all departments
  print "** All DEPARTMENT Records **\n"
  deptiterator = depscache.entrySet().iterator

  while deptiterator.hasNext()
    entry = deptiterator.next()
    print "Key : [" , entry.getKey() , "] "
    print "Value : " , entry.getValue()
    puts
  end

  #get department 10
  deptid = Integer.new(10)
  deptrecord = depscache.get(deptid)
  print "\n** DEPARTMENT 10 **\n"
  print deptrecord
  puts

  #show all employees who have a JOB ROLE = 'SH_CLERK'
  print "\n** All EMPLOYEE Records with job role = 'SH_CLERK' **\n"
  filter = com.tangosol.util.filter.EqualsFilter.new("getJobId", 

"SH_CLERK")
  employees = empscache.entrySet(filter)

  print "Size of employees after filter applied = " , employees.size() , 

"\n"

  empiterator = employees.iterator()
  i = 0
  while empiterator.hasNext()
    empentry = empiterator.next()
    i = i + 1
    print "- Record " , i , "\n"
    print "Key : " , empentry.getKey() , " \n"
    print "Employee [employeeId=" , empentry.getValue().getEmployeeId() ,
          ", firstName=" , empentry.getValue().getFirstName() ,
          ", lastName=" , empentry.getValue().getLastName() ,
          ", jobId=" , empentry.getValue().getJobId() , "]\n"
  end

rescue
  print "\n** Error occured **\n"
	print "Failed to display HR data from cache ", $!, "\n\n"

end

print "\nEnded at ", Time.now, "\n"
      

在第三个终端中,更改到 hr_demo 目录并运行 jruby_cohextendclient.rb。


$ cd ~/hr_demo
$ jruby jruby_cohextendclient.rb
/home/cjones/jruby-1.5.6/lib/ruby/site_ruby/shared/builtin/javasupport/
core_ext/object.rb:99 warning: already initialized constant Integer
*********************************************************
Coherence 3.6 Oracle HR Extend Client Example from JRuby
*********************************************************
Started at Mon Mar 07 17:27:28 -0800 2011
2011-03-07 17:27:28.976/3.819 Oracle Coherence 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded operational configuration from 
"jar:file:/home/cjones/coherence/lib/coherence.jar!/tangosol-coherence.xml"
2011-03-07 17:27:29.037/3.880 Oracle Coherence 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded operational overrides from 
"jar:file:/home/cjones/coherence/lib/coherence.jar!/
tangosol-coherence-override-dev.xml"
2011-03-07 17:27:29.041/3.884 Oracle Coherence 3.6.1.0 <D5> 
(thread=main, member=n/a): Optional configuration override 
"/tangosol-coherence-override.xml" is not specified
2011-03-07 17:27:29.103/3.946 Oracle Coherence 3.6.1.0 <D5> 
(thread=main, member=n/a): Optional configuration override 
"/custom-mbeans.xml" is not specified

Oracle Coherence Version 3.6.1.0 Build 19636
 Grid Edition: Development mode
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

2011-03-07 17:27:29.718/4.561 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded cache configuration from 
"jar:file:/home/cjones/hr_demo/./oraclehrdemo.jar!/client-cache-config.xml"
2011-03-07 17:27:30.183/5.026 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=RemoteCache:TcpInitiator, member=n/a): Loaded POF configuration from 
"jar:file:/home/cjones/hr_demo/./oraclehrdemo.jar!/hr-pof-config.xml"
2011-03-07 17:27:30.232/5.075 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=RemoteCache:TcpInitiator, member=n/a): Loaded included POF configuration from 
"jar:file:/home/cjones/coherence/lib/coherence.jar!/coherence-pof-config.xml"
2011-03-07 17:27:30.834/5.677 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=RemoteCache:TcpInitiator, member=n/a): Started: 
TcpInitiator{Name=RemoteCache:TcpInitiator, State=(SERVICE_STARTED), ThreadCount=0, 
Codec=Codec(Format=POF), Serializer=com.tangosol.io.pof.ConfigurablePofContext, 
PingInterval=0, PingTimeout=0, RequestTimeout=0, ConnectTimeout=0, 
SocketProvider=SystemSocketProvider, RemoteAddresses=[/10.0.2.15:9099], 
SocketOptions{LingerTimeout=0, KeepAliveEnabled=true, TcpDelayEnabled=false}}
2011-03-07 17:27:30.861/5.704 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=main, member=n/a): Connecting Socket to 10.0.2.15:9099
2011-03-07 17:27:30.872/5.716 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=main, member=n/a): Connected Socket to 10.0.2.15:9099

Cache [depscache] size  = 27
Cache [empscache] size  = 107

** All DEPARTMENT Records **
Key : [100] Value : Department [departmentId=100 ,departmentName=Finance ,
managerId=108 ,locationId=1700]
Key : [20] Value : Department [departmentId=20 ,departmentName=Marketing ,
managerId=201 ,locationId=1800]
Key : [270] Value : Department [departmentId=270 ,departmentName=Payroll ,
managerId=0 ,locationId=1700]
Key : [90] Value : Department [departmentId=90 ,departmentName=Executive ,
managerId=100 ,locationId=1700]
Key : [150] Value : Department [departmentId=150 ,departmentName=Shareholder Services ,
managerId=0 ,locationId=1700]
Key : [250] Value : Department [departmentId=250 ,departmentName=Retail Sales ,
managerId=0 ,locationId=1700]
Key : [80] Value : Department [departmentId=80 ,departmentName=Sales ,
managerId=145 ,locationId=2500]
Key : [110] Value : Department [departmentId=110 ,departmentName=Accounting ,
managerId=205 ,locationId=1700]
Key : [50] Value : Department [departmentId=50 ,departmentName=Shipping ,
managerId=121 ,locationId=1500]
Key : [140] Value : Department [departmentId=140 ,departmentName=Control And Credit ,
managerId=0 ,locationId=1700]
Key : [60] Value : Department [departmentId=60 ,departmentName=IT ,managerId=103 ,
locationId=1400]
Key : [260] Value : Department [departmentId=260 ,departmentName=Recruiting ,
managerId=0 ,locationId=1700]
Key : [40] Value : Department [departmentId=40 ,departmentName=Human Resources ,
managerId=203 ,locationId=2400]
Key : [240] Value : Department [departmentId=240 ,departmentName=Government Sales ,
managerId=0 ,locationId=1700]
Key : [130] Value : Department [departmentId=130 ,departmentName=Corporate Tax ,
managerId=0 ,locationId=1700]
Key : [180] Value : Department [departmentId=180 ,departmentName=Construction ,
managerId=0 ,locationId=1700]
Key : [120] Value : Department [departmentId=120 ,departmentName=Treasury ,
managerId=0 ,locationId=1700]
Key : [70] Value : Department [departmentId=70 ,departmentName=Public Relations ,
managerId=204 ,locationId=2700]
Key : [200] Value : Department [departmentId=200 ,departmentName=Operations ,
managerId=0 ,locationId=1700]
Key : [230] Value : Department [departmentId=230 ,departmentName=IT Helpdesk ,
managerId=0 ,locationId=1700]
Key : [170] Value : Department [departmentId=170 ,departmentName=Manufacturing ,
managerId=0 ,locationId=1700]
Key : [220] Value : Department [departmentId=220 ,departmentName=NOC ,
managerId=0 ,locationId=1700]
Key : [190] Value : Department [departmentId=190 ,departmentName=Contracting ,
managerId=0 ,locationId=1700]
Key : [10] Value : Department [departmentId=10 ,departmentName=Administration ,
managerId=200 ,locationId=1700]
Key : [210] Value : Department [departmentId=210 ,departmentName=IT Support ,
managerId=0 ,locationId=1700]
Key : [160] Value : Department [departmentId=160 ,departmentName=Benefits ,
managerId=0 ,locationId=1700]
Key : [30] Value : Department [departmentId=30 ,departmentName=Purchasing ,
managerId=114 ,locationId=1700]

** DEPARTMENT 10 **
Department [departmentId=10 ,departmentName=Administration ,managerId=200 ,
locationId=1700]

** All EMPLOYEE Records with job role = 'SH_CLERK' **
Size of employees after filter applied = 20
- Record 1
Key : DepertmentIdKey [departmentId=50, employeeId=189]
Employee [employeeId=189, firstName=Jennifer, lastName=Dilly, jobId=SH_CLERK]
- Record 2
Key : DepertmentIdKey [departmentId=50, employeeId=182]
Employee [employeeId=182, firstName=Martha, lastName=Sullivan, jobId=SH_CLERK]
- Record 3
Key : DepertmentIdKey [departmentId=50, employeeId=197]
Employee [employeeId=197, firstName=Kevin, lastName=Feeney, jobId=SH_CLERK]
- Record 4
Key : DepertmentIdKey [departmentId=50, employeeId=191]
Employee [employeeId=191, firstName=Randall, lastName=Perkins, jobId=SH_CLERK]
- Record 5
Key : DepertmentIdKey [departmentId=50, employeeId=183]
Employee [employeeId=183, firstName=Girard, lastName=Geoni, jobId=SH_CLERK]
- Record 6
Key : DepertmentIdKey [departmentId=50, employeeId=187]
Employee [employeeId=187, firstName=Anthony, lastName=Cabrio, jobId=SH_CLERK]
- Record 7
Key : DepertmentIdKey [departmentId=50, employeeId=186]
Employee [employeeId=186, firstName=Julia, lastName=Dellinger, jobId=SH_CLERK]
- Record 8
Key : DepertmentIdKey [departmentId=50, employeeId=180]
Employee [employeeId=180, firstName=Winston, lastName=Taylor, jobId=SH_CLERK]
- Record 9
Key : DepertmentIdKey [departmentId=50, employeeId=199]
Employee [employeeId=199, firstName=Douglas, lastName=Grant, jobId=SH_CLERK]
- Record 10
Key : DepertmentIdKey [departmentId=50, employeeId=181]
Employee [employeeId=181, firstName=Jean, lastName=Fleaur, jobId=SH_CLERK]
- Record 11
Key : DepertmentIdKey [departmentId=50, employeeId=184]
Employee [employeeId=184, firstName=Nandita, lastName=Sarchand, jobId=SH_CLERK]
- Record 12
Key : DepertmentIdKey [departmentId=50, employeeId=185]
Employee [employeeId=185, firstName=Alexis, lastName=Bull, jobId=SH_CLERK]
- Record 13
Key : DepertmentIdKey [departmentId=50, employeeId=188]
Employee [employeeId=188, firstName=Kelly, lastName=Chung, jobId=SH_CLERK]
- Record 14
Key : DepertmentIdKey [departmentId=50, employeeId=194]
Employee [employeeId=194, firstName=Samuel, lastName=McCain, jobId=SH_CLERK]
- Record 15
Key : DepertmentIdKey [departmentId=50, employeeId=195]
Employee [employeeId=195, firstName=Vance, lastName=Jones, jobId=SH_CLERK]
- Record 16
Key : DepertmentIdKey [departmentId=50, employeeId=193]
Employee [employeeId=193, firstName=Britney, lastName=Everett, jobId=SH_CLERK]
- Record 17
Key : DepertmentIdKey [departmentId=50, employeeId=190]
Employee [employeeId=190, firstName=Timothy, lastName=Gates, jobId=SH_CLERK]
- Record 18
Key : DepertmentIdKey [departmentId=50, employeeId=196]
Employee [employeeId=196, firstName=Alana, lastName=Walsh, jobId=SH_CLERK]
- Record 19
Key : DepertmentIdKey [departmentId=50, employeeId=192]
Employee [employeeId=192, firstName=Sarah, lastName=Bell, jobId=SH_CLERK]
- Record 20
Key : DepertmentIdKey [departmentId=50, employeeId=198]
Employee [employeeId=198, firstName=Donald, lastName=OConnell, jobId=SH_CLERK]

Ended at Mon Mar 07 17:27:33 -0800 2011


文件 hr_demo/jruby_hash_cohextend.rb 将数据从部门缓存复制到 Ruby 哈希数据结构 并重复执行,以验证复制是否已成功执行。根据系统的实际情况更改 Coherence jar 的位置并在需 要的情况下更新 proxy.host:


# jruby_hash_cohextend.rb

require 'java'
require File.dirname(__FILE__) + '/oraclehrdemo.jar'
require '/home/cjones/coherence/lib/coherence.jar'  # Update for your environment

import com.tangosol.net.CacheFactory
import com.tangosol.net.NamedCache
import java.lang.System

puts "*********************************************************"
puts "Coherence 3.6 Oracle HR Extend Client Example from JRuby"
puts "*********************************************************"

print "Started at ", Time.now, "\n"

begin

  # setup required properties to connect to proxy server as extend client
  System.setProperty("tangosol.coherence.cacheconfig", 
                     "client-cache-config.xml")
  System.setProperty("tangosol.pof.enabled", "true")
  System.setProperty("tangosol.pof.config", "hr-pof-config.xml")
  # Update for your environment  
  System.setProperty("proxy.host", "localhost")  

  # get named cache dep-cache
  depscache = CacheFactory.getCache("dep-cache")

  #retrieve size of caches
  print "\nCache [depscache] size  = " , depscache.size() , "\n\n"

  deptiterator = depscache.entrySet().iterator

  depthash = Hash.new

  #copy all department cache data into ruby hash data structure
  while deptiterator.hasNext()
    entry = deptiterator.next()
    depthash[entry.getKey()] = entry.getValue()
  end

  #display hash
  print "Displaing hash data structure of department cache \n"
  print "Is Hash structure depthash empty : ", depthash.empty?, 

"\n"
  print "Hash structure depthash size: ", depthash.length, "\n"

  keys = depthash.keys
  for key in 0...depthash.length
    print "key  : ", keys[key], " "
    print "value : ", depthash[keys[key]], "\n"
  end

rescue
  print "\n** Error occured **\n"
	print "Failed to display HR data from cache ", $!, "\n\n"

end

print "\nEnded at ", Time.now, "\n"


运行 jruby_hash_cohextend.rb 并验证输出如下所示:

$ jruby jruby_hash_cohextend.rb
*********************************************************
Coherence 3.6 Oracle HR Extend Client Example from JRUBY
*********************************************************
Started at Mon Mar 07 17:36:12 -0800 2011
2011-03-07 17:36:12.529/3.240 Oracle Coherence 3.6.1.0  
(thread=main, member=n/a): Loaded operational configuration from
"jar:file:/home/cjones/coherence/lib/coherence.jar!/tangosol- coherence.xml"
2011-03-07 17:36:12.565/3.275 Oracle Coherence 3.6.1.0
(thread=main, member=n/a): Loaded operational overrides from
"jar:file:/home/cjones/coherence/lib/coherence.jar!/
tangosol-coherence- override-dev.xml"
2011-03-07 17:36:12.567/3.277 Oracle Coherence 3.6.1.0
(thread=main, member=n/a): Optional configuration override
"/tangosol -coherence-override.xml" is not specified
2011-03-07 17:36:12.611/3.321 Oracle Coherence 3.6.1.0
(thread=main, member=n/a):
Optional configuration override "/custom-mbeans.xml" is not specified

Oracle Coherence Version 3.6.1.0 Build 19636
Grid Edition: Development mode
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

2011-03-07 17:36:13.070/3.780 Oracle Coherence GE 3.6.1.0
(thread=main, member=n/a): Loaded cache configuration from
"jar:file:/home/cjones/hr_demo/./oraclehrdemo.jar!/client-cache- config.xml"
2011-03-07 17:36:13.577/4.287 Oracle Coherence GE 3.6.1.0
(thread=RemoteCache:TcpInitiator, member=n/a):
Loaded POF configuration from
"jar:file:/home/cjones/hr_demo/./oraclehrdemo.jar!/hr-pof- config.xml"
2011-03-07 17:36:13.620/4.330 Oracle Coherence GE 3.6.1.0
(thread=RemoteCache:TcpInitiator, member=n/a):
Loaded included POF configuration from
"jar:file:/home/cjones/coherence/lib/coherence.jar!/coherence-pof- config.xml"
2011-03-07 17:36:14.249/4.959 Oracle Coherence GE 3.6.1.0
(thread=RemoteCache:TcpInitiator, member=n/a):
Started: TcpInitiator {Name=RemoteCache:TcpInitiator, State=(SERVICE_STARTED),
ThreadCount=0, Codec=Codec(Format=POF),
Serializer=com.tangosol.io.pof.ConfigurablePofContext, PingInterval=0,
PingTimeout=0, RequestTimeout=0, ConnectTimeout=0,
SocketProvider=SystemSocketProvider,
RemoteAddresses=[/10.0.2.15:9099], SocketOptions{LingerTimeout=0,
KeepAliveEnabled=true,
TcpDelayEnabled=false}}
2011-03-07 17:36:14.275/4.985 Oracle Coherence GE 3.6.1.0
(thread=main, member=n/a): Connecting Socket to 10.0.2.15:9099
2011-03-07 17:36:14.291/5.001 Oracle Coherence GE 3.6.1.0
(thread=main, member=n/a): Connected Socket to 10.0.2.15:9099

Cache [depscache] size = 27

Displaing hash data structure of department cache
Is Hash structure depthash empty : false
Hash structure depthash size: 27
key : 100 value : Department [departmentId=100 ,departmentName=Finance ,
managerId=108 ,locationId=1700]
key : 20 value : Department [departmentId=20 ,departmentName=Marketing ,
managerId=201 ,locationId=1800]
key : 270 value : Department [departmentId=270 ,departmentName=Payroll ,
managerId=0 ,locationId=1700]
key : 90 value : Department [departmentId=90 ,departmentName=Executive ,
managerId=100 ,locationId=1700]
key : 150 value : Department [departmentId=150 ,departmentName=Shareholder Services ,
managerId=0 ,locationId=1700]
key : 250 value : Department [departmentId=250 ,
departmentName=Retail Sales ,managerId=0 ,locationId=1700]
key : 80 value : Department [departmentId=80 ,
departmentName=Sales ,managerId=145 ,locationId=2500]
key : 110 value : Department [departmentId=110 ,
departmentName=Accounting ,managerId=205 ,locationId=1700]
key : 50 value : Department [departmentId=50 ,
departmentName=Shipping ,managerId=121 ,locationId=1500]
key : 140 value : Department [departmentId=140 ,
departmentName=Control And Credit ,managerId=0 ,locationId=1700]
key : 60 value : Department [departmentId=60 ,
departmentName=IT ,managerId=103 ,locationId=1400]
key : 260 value : Department [departmentId=260 ,
departmentName=Recruiting ,managerId=0 ,locationId=1700]
key : 40 value : Department [departmentId=40 ,
departmentName=Human Resources ,managerId=203 ,locationId=2400]
key : 240 value : Department [departmentId=240 ,
departmentName=Government Sales ,managerId=0 ,locationId=1700]
key : 130 value : Department [departmentId=130 ,
departmentName=Corporate Tax ,managerId=0 ,locationId=1700]
key : 180 value : Department [departmentId=180 ,
departmentName=Construction ,managerId=0 ,locationId=1700]
key : 120 value : Department [departmentId=120 ,
departmentName=Treasury ,managerId=0 ,locationId=1700]
key : 70 value : Department [departmentId=70 ,
departmentName=Public Relations ,managerId=204 ,locationId=2700]
key : 200 value : Department [departmentId=200 ,
departmentName=Operations ,managerId=0 ,locationId=1700]
key : 230 value : Department [departmentId=230 ,
departmentName=IT Helpdesk ,managerId=0 ,locationId=1700]
key : 170 value : Department [departmentId=170 ,
departmentName=Manufacturing ,managerId=0 ,locationId=1700]
key : 220 value : Department [departmentId=220 ,
departmentName=NOC ,managerId=0 ,locationId=1700]
key : 190 value : Department [departmentId=190 ,
departmentName=Contracting ,managerId=0 ,locationId=1700]
key : 10 value : Department [departmentId=10 ,
departmentName=Administration ,managerId=200 ,locationId=1700]
key : 210 value : Department [departmentId=210 ,
departmentName=IT Support ,managerId=0 ,locationId=1700]
key : 160 value : Department [departmentId=160 ,
departmentName=Benefits ,managerId=0 ,locationId=1700]
key : 30 value : Department [departmentId=30 ,
departmentName=Purchasing ,managerId=114 ,locationId=1700]

Ended at Mon Mar 07 17:36:15 -0800 2011


最后,将在 Coherence 缓存中插入一个部门。这样做不会将更改持久保存到数据库,因 为该主题不在本文的范围之内。有关利用 Coherence 对直读、直写、提前刷新和后写入式缓存的支 持的更多信息,请访问此处链接。数据库用于为 缓存提供数据源(填充缓存),不过更新数据库的主题不在本文讨论范围之内。

查看 hr_demo/jruby_insert_cohextend.rb。根据系统的实际情况更改 Coherence jar 的位置 并在需要的情况下更新 proxy.host:在这个 JRuby 脚本中,我们创建了一个新的 Department Java 对象,并将其插入名为“dep-cache”的缓存,然后验证它确实成为了缓存的一部 分。

# jruby_insert_cohextend.rb

require 'java'
require File.dirname(__FILE__) + '/oraclehrdemo.jar'
require '/home/cjones/coherence/lib/coherence.jar'  # Update for your environment

import com.tangosol.net.CacheFactory
import com.tangosol.net.NamedCache
import java.lang.System
import java.lang.Integer
import "pas.au.coherence.hr.server.Department"

puts "*********************************************************"
puts "Coherence 3.6 Oracle HR Extend Client Example from JRuby"
puts "*********************************************************"

print "Started at ", Time.now, "\n"

begin

  # setup required properties to connect to proxy server as extend client
  System.setProperty("tangosol.coherence.cacheconfig", "client-cache-

config.xml")
  System.setProperty("tangosol.pof.enabled", "true")
  System.setProperty("tangosol.pof.config", "hr-pof-config.xml")
  System.setProperty("proxy.host", "localhost")  # Update for your 

environment

  # get named cache dep-cache
  depscache = CacheFactory.getCache("dep-cache")

  # retrieve size of cache
  print "\nCache [depscache] size  = " , depscache.size() , "\n\n"

  # insert department 280 into cache
  deptid = Integer.new(280)
  newdept = Department.new
  newdept.setDepartmentId(280)
  newdept.setDepartmentName("JRuby Department")

  depscache.put(deptid, newdept)

  puts "Department 280 added to cache"

  # retrieve record 280 ensuring it make it's way into the cache
  deptrecord = depscache.get(deptid)
  print "\n** DEPARTMENT 280 **\n"
  print deptrecord
  puts

  # retrieve size of cache to verify inserted record exists
  print "\nCache [depscache] size  = " , depscache.size() , "\n"

rescue
  print "\n** Error occured **\n"
	print "Failed to display HR data from cache ", $!, "\n\n"

end

print "\nEnded at ", Time.now, "\n"


运行 jruby_insert_cohextend.rb,如下所示:

$ jruby jruby_insert_cohextend.rb
/home/cjones/jruby-1.5.6/lib/ruby/site_ruby/shared/builtin/
javasupport/core_ext/object.rb:99 warning: already initialized constant Integer
*********************************************************
Coherence 3.6 Oracle HR Extend Client Example from JRUBY
*********************************************************
Started at Mon Mar 07 17:42:50 -0800 2011
2011-03-07 17:42:50.803/3.705 Oracle Coherence 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded operational configuration from 
"jar:file:/home/cjones/coherence/lib/coherence.jar!/tangosol-coherence.xml"
2011-03-07 17:42:50.832/3.734 Oracle Coherence 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded operational overrides from 
"jar:file:/home/cjones/coherence/lib/coherence.jar!/tangosol-coherence-override-

dev.xml"
2011-03-07 17:42:50.835/3.737 Oracle Coherence 3.6.1.0 <D5> 
(thread=main, member=n/a): Optional configuration override 
"/tangosol-coherence-override.xml" is not specified
2011-03-07 17:42:50.890/3.792 Oracle Coherence 3.6.1.0 <D5> 
(thread=main, member=n/a): Optional configuration override "/custom-

mbeans.xml" 
is not specified

Oracle Coherence Version 3.6.1.0 Build 19636
 Grid Edition: Development mode
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

2011-03-07 17:42:51.388/4.290 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=main, member=n/a): Loaded cache configuration from 
"jar:file:/home/cjones/hr_demo/./oraclehrdemo.jar!/client-cache-config.xml"
2011-03-07 17:42:51.797/4.699 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=RemoteCache:TcpInitiator, member=n/a): Loaded POF configuration from 
"jar:file:/home/cjones/hr_demo/./oraclehrdemo.jar!/hr-pof-config.xml"
2011-03-07 17:42:51.835/4.737 Oracle Coherence GE 3.6.1.0 <Info> 
(thread=RemoteCache:TcpInitiator, member=n/a): Loaded included POF configuration 
from "jar:file:/home/cjones/coherence/lib/coherence.jar!/coherence-pof-

config.xml"
2011-03-07 17:42:52.362/5.264 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=RemoteCache:TcpInitiator, member=n/a): Started: 
TcpInitiator{Name=RemoteCache:TcpInitiator, State=(SERVICE_STARTED), ThreadCount=0, 
Codec=Codec(Format=POF), Serializer=com.tangosol.io.pof.ConfigurablePofContext, 
PingInterval=0, PingTimeout=0, RequestTimeout=0, ConnectTimeout=0, 
SocketProvider=SystemSocketProvider, RemoteAddresses=[/10.0.2.15:9099], 
SocketOptions{LingerTimeout=0, KeepAliveEnabled=true, TcpDelayEnabled=false}}
2011-03-07 17:42:52.389/5.291 Oracle Coherence GE 3.6.1.0 <D5> 
(thread=main, member=n/a): Connecting Socket to 10.0.2.15:9099
2011-03-07 17:42:52.402/5.304 Oracle Coherence GE 3.6.1.0 
<Info> (thread=main, member=n/a): Connected Socket to 10.0.2.15:9099

Cache [depscache] size  = 27

Department 280 added to cache

** DEPARTMENT 280 **
Department [departmentId=280 ,departmentName=JRuby Department ,
managerId=0 ,locationId=0]

Cache [depscache] size  = 28

Ended at Mon Mar 07 17:42:52 -0800 2011


总结

本文向您介绍了如何从 JRuby 脚本作为 Coherence Extend 客户端访问 Coherence 网格。通过 JRuby,我们能够使用 Oracle Coherence 内存中数据网格来查询缓存、用键值搜索特定记录、插入 新记录以及将缓存数据复制到 Ruby 哈希结构。




Pas Apicella
[oracle.com 的 pas.apicella] 是 Oracle 的首席技 术支持工程师。