Oracle Coherence 内存网格
第 5 章 — 在 Coherence 中使用 POF 对象

 

作者:金辉 (Oracle)

2016 年 6 月 20 日发布


右箭头 第 1 章 — 漫说内存网格
右箭头 第 2&3 章 — 安装和配置开发环境
右箭头 第 4 章 —
开始第一个Coherence程序
右箭头 第 5 章 — 在 Coherence 中使用 POF 对象
右箭头 第 6 章 — 分布式内存集群的数据灌注、查询和统计
右箭头 第 7 章 — 监听器处理内存集群中变化的对象
右箭头 第 8 章 — 使用 ZFS 加密
右箭头 第 9 章 — 内存集群与数据库的互操作
右箭头 第 10 章 — Coherence 内存集群的安全访问
右箭头 第 11 章 — 基于内存集群的事件处理

在这一章,学习在 Cache 环境中使用 POF 复杂对象。使用 POF 对象的目的是在分布式环境中压缩对象占用空间的大小,提高网络传输效率。

操作重点是 Coherence 的 PofReader、PofWriter 和 PortableObject API。内容如下:

  • 简介
  • 使用复杂对象

5.1 简介

 

目前为止,还只是将简单的字符串类型防止到缓存集群当中。现实当中,许多键值对都是用 Coherence Java API 来操作的对象:

public java.lang.Object get(java.lang.Object oKey)
public void put(java.lang.Object oKey, java.lang.Object oValue)

 

一个对象能够作为键,或者值,意味着程序开发人员可以存取复杂对象。

由于 Coherence 需要在网络间复制对象,所以对象必须是能够被序列化的 (serializable)。对象序列化通常需要将对象的状态写入到顺序的字节流当中,在需要是再从字节流当中读出,这被称之为反序列化 (deserializing)。通常而言,对象需要实现 Java 的 java.io.Serializable 接口开进行序列化。

作为 Java java.io.Serializable 序列化的另一种替代解决方案,可以使用 Coherence 的高性能序列化解决方案 com.tangosol.io.pof.PortableObject  来提高性能。 PortableObject 格式提供了 6 倍于标准序列化方案的速度,并且序列化的结果集更小。

PortableObject 接口提供了两种简单的方法,readExternal 和 writeExternal,提供了分别 PofReader 和 PofWriter 流中显式的读和写序列化对象属性。通过控制序列化对象格式,Coherence 提供了提高性能的方法。使用 POF 格式减少了二进制文件的大小 5-10 倍,提供了 5-20 倍的序列化性能。

5.2 缓存集群中使用复杂对象

 

在本章中,创建一个包含 names、addresses、生日和员工电话号码的 Contact 对象。通过实现 PortableObject 接口,使用 POF 序列化将对象在内存缓存中存取里。

  1. 创建数据对象
  2. 创建复杂对象
  3. 创建驱动类
  4. 创建 POF 和缓存配置文件
  5. 运行和测试工程

5.2.1 创建数据对象

 

这一部分介绍如何创建两个数据对象,这两个对象将被其他对象所引用。Address 对象提供了员工住址信息,PhoneNumber 对象提供了联系人的联系方式。

1. 为员工信息创建 Address 对象

1) 在 com.oracle.handson.chapter05 包里创建一个 Address 类,继承 PortableObject 接口。

05-figure-01

如果自动产生的代码没有构造函数,则自己需要为这个 POF 对象写个默认的构造函数:

05-figure-02

2) 添加如下私有的成员变量

- String Street1

- String Street2

- String City

- String State

- String Country

05-figure-03

3) 使用 Eclipse 为这些属性,自动产生 get 和 set 方法。右键点击 Address-> Source->Generate Getters and Setters。

05-figure-04

05-figure-05

点击 Select All ,点 OK。

4) 再产生一个带 set 的构造函数。Source->Generate Constructor using Fields。

05-figure-06

05-figure-07

点 Select All, 然后 OK。

添加"this"到构造函数中。结果如下:

05-figure-08

5) 为 PortableObject 实现 readExternal和writeExternal 方法。下面的例子,演示如何将各属性值读到 POF 对象里:

05-figure-09

6) 实现 equals()、hashCode() 和 toString() 对象方法。

注释:
缓存的键值必须被序列化,缓存的键 (Key) 必须实现 hashCode 和 equals 方法,这些方法在集群节点中必须返回一致的结果。这意味着实现 hashCode 和 equals 方法必须基于单独的对象序列化状态(即,对象的非暂时性属性);大部分预制的 Java 类型,如 String、Integer 和 Date,符合这个要求。Some cache implementations (specifically the partitioned cache) use the serialized form of the key objects for equality testing, which means that keys for which the equals() method returns true must serialize identically; most built-in Java types meet this requirement.

 

为实现这些方法,需要 import the com.tangosol.util.Base 和 com.tangosol.util.HashHelper 类。Base 类提供了 equals 方法, HashHelper 包含了为计算 hash 值提供的 helper 函数。

05-figure-10

这些方法,需要 import the com.tangosol.util.Base 和 com.tangosol.util.HashHelper 类。Base 类提供了 equals 方法,HashHelper 包含了为计算 hash 值提供的 helper 函数。

完整代码见工程。

2. 创建 PhoneNumber 类存放电话联系信息

创建过程如 Address 类。同样是需要:

1) 实现 com.tangosol.io.pof PortableObject 接口
2) 定义成员变量

- short AccessCode
- short CountryCode
- short AreaCode
- int LocalNumber

 

3) 产生默认的 get 和 set 方法
4) 产生带构造器的默认构造函数
5) 实现 readExternal 和 writeExternal 方法
6) 实现 equals、hashCode 和 toString 方法
7) 结果类似如下

05-figure-11

5.2.2 创建复杂对象

 

Contact 对象通过引入 Address 和 PhoneNumber 对象,定义了员工的 name、address 和 telephone 信息。

1. 创建一个 Java 类:Contact。具体步骤参见 3.5.1。

2. 这个类同样要实现 PortableObject 接口。

3. 确认默认构造函数

05-figure-12

4. 注意新产生的类代码已经 import PofReader/PofWriter和IOException

05-figure-13

5. 使用以下属性作为成员变量:

  • String FirstName
  • String LastName
  • Address HomeAddress
  • Address WorkAddress
  • java.util.Map TelephoneNumbers
  • java.sql.Date BirthDate

6. 通过 eclipse 的源代码帮助产生上述成员变量的 set 和 get 方法

7. 新建一个获取器 getAge() 用来计算员工年龄

05-figure-14

其中增加一个用来计算 1 年毫秒时间的成员变量。

8. 通过代码生成器自动产生默认的构造函数。

Source-> Generate Constructor using Fields,点击选择全部,然后 OK。产生的代码基本与下面相同:

05-figure-15

9. 由于集成了 PortableObject 接口,所以必须实现 readExternal 和 writeExternal 两个方法。

05-figure-16

10. 实现 equals()、hashCode() 和 toString() 三个方法,方法同 5.2.1 中的内容。

11. 代码参见工程文件 chapter03_07/src/com.oracle.handson.chapter05/Contac.java

5.2.3 创建一个驱动程序类

 

创建一个叫 ContactDriver 的类,用于向内存集群存取 Contact 对象。

1. 在工程中新产生一个叫 ContactDriver 的 Java 类,确保有 main 函数。

05-figure-17

2. 在这个 ContactDriver 类中,创建一个 NamedCache 叫 contact 并且存放一个 Contact 对象到其中,从内存集群中取得对象,确定这两个对象是完全一致的。示例代码如下

05-figure-18

5.2.4 创建一个 POF 配置文件和一个 Cache 配置文件

 

为了使用 POF 序列化,必须在 POF 文件中注册自己定义的对象。 配置文件中需要将用户定义对象指定一个数值用来做标识。同时要在 cache 配置文件中指定使用的 POF 序列化配置文件。

1. 为 Contact、Address 和 PhoneNumber 三个对象类型创建 POF 配置文件。

a) 在工程文件中,已经有了一个 pof-config.xml 用于 POF。

05-figure-19

b) 为 Contact、Address 和 PhoneNumber 对象定义 元素,分别赋予 ID 为 1001、1002 和 1003,并提供完整的类名称。这个文件必须包含 coherence-pof-config.xml 文件 — 该文件提供了 Coherence 前 1000 个 ID 的数据类型。

05-figure-20

c) 把这个文件改名,存为 contacts-pof-config.xml,样式如下

05-figure-21

2. 创建一个 cache 配置文件。在项目浏览器里,已经有了一个 coherence-cache-config.xml 文件可以作为模板进行修改。在 coherence.jar 中也有一个 coherence-cache-config.Xml。

05-figure-22

a) 使用 ExamplesPartitionedPocScheme 作为 scheme-name,并且建 PartitionedPofCache 作为 service-name。

05-figure-23

05-figure-24

在序列化配置中需要指定合适的序列化收到,在本例中使用 com.tangosol.io.pof.ConfigurablePofContext。在初始化参数中,指定 POF 配置文件为 contacts-pof-config.xml

05-figure-25

05-figure-26

05-figure-27

05-figure-28

<?xml version="1.0"?> 

<!-- Note: This XML document is an example Coherence Cache Configuration 

deployment descriptor that should be customized (or replaced) for your particular 

caching requirements. The cache mappings and schemes declared in this descriptor 

are strictly for demonstration purposes and are not required. For detailed 

information on each of the elements that can be used in this descriptor please 

see the Coherence Cache Configuration deployment descriptor guide included 

in the Coherence distribution or the "Cache Configuration Elements" page 

on the Coherence Wiki (http://wiki.tangosol.com). -->

cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config" 

xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config http://xmlns.oracle.com      /coherence/coherence-cache-config/1.2/coherence-cache-config.xsd"> 

<!-- The defaults element defines factory-wide default settings. -->

<defaults>

<!-- Note: This element defines the default serializer for all services 

defined within this cache configuration descriptor. Valid values include 

full serializer definitions, as well as named references to serializers defined 

within the "serializers" element of the operational configuration. Example 

values include: java, pof. Default value is java. -->

<serializer system-property="tangosol.coherence.serializer" /> 
            
<!-- Note: This element defines the default socket-provider for all Coherence 

Extend services defined within this cache configuration descriptor. Valid 

values include full socket-provider definitions, as well as named references 

to providers defined within the "socket-providers" element of the operational 

configuration. This setting only specifies the default socket-provider for 

Coherence Extend services; TCMP's socket-provider is specified within the 

"unicast-listener" of the operational configuration. Example values include: 

system, ssl. Default value is system. -->

<socket-provider system-property="tangosol.coherence.socketprovider" /> 

</defaults>

<caching-scheme-mapping>

<cache-mapping>

<cache-name>*</cache-name>

<scheme-name>ExamplesPartitionedPofScheme</scheme-name>

</cache-mapping>

</caching-scheme-mapping>

<caching-schemes>

<distributed-scheme>

<scheme-name>ExamplesPartitionedPofScheme</scheme-name>

<service-name>PartitionedPofCache</service-name>

<serializer>

<instance>

<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>

<init-params>

<init-param>

<param-type>String</param-type>

<param-value>contacts-pof-config.xml</param-value>

</init-param>

</init-params>

</instance>

</serializer>

<backing-map-scheme>

<local-scheme>

<!-- each node will be limited to 250MB -->

<high-units>250M</high-units>

<unit-calculator>binary</unit-calculator>

</local-scheme>

</backing-map-scheme>

<autostart>true</autostart>

</distributed-scheme>

</caching-schemes>

</cache-config>
 

b) 将这个文件改名为 contacts-cache-config.xml

05-figure-29

5.2.5 运行该项目

 

本节需要有 cache 的运行,cache 服务器和应用必须使用同样的 POF 和 cache 配置文件。下面的内容介绍如何创建 cache 服务器和应用的配置文件。

1. 创建和运行 Cache 运行配置。

停止之前运行的 cache 服务器。复制先前的 chapter03CacheServer,改名为 chapter05CacheServer

05-figure-30

1) 在 General 里,指定 cache 配置文件

05-figure-31

2) 在 Other 选卡中,下拉滑动条找 tangosol.pof.config 项:

05-figure-32

3) 在 Arguments 选卡,在 VM 参数中输入 -showversion。

4) 在 Classpath 选卡中,确保本项目出现在 User Entries 下。如果没有,点 Add Projects 按键增加本工程。

5) 在 Common 选卡,选择 Shared file,如下

05-figure-33

6) 点 Run,启动 cache 服务器。输出如下:

05-figure-34

2. 为 ContactDriver 执行程序创建一个运行配置

1) 复制先前的 chapter05CacheServer,更名为 chapter05CacheClientContactDriver

2) Main 选卡,选择 Enter ContactsDriver 作为运行类。

05-figure-35

3) 在 General 选卡,确保 contacts-cache-config.xml 文件作为缓存配置文件,与 Cache 服务相同。选择 Disable (cache client) 选项。

05-figure-36

4) 在 Other 选卡中,下拉滑动条找 tangosol.pof.config 项:

05-figure-37

5) 在 Arguments 选卡,在 VM 参数中输入 -showversion。

6) 在 Classpath 选卡中,确保本项目出现在 User Entries 下。如果没有,点 Add Projects 按键增加本工程。

7) 点 RUN。如下是运行结果

05-figure-38

关于作者

 niehao

金辉,在 Oracle 负责云和中间件产品的资深售前顾问和团队经理,有十多年的中间件和项目管理经验,专注在企业云构建,企业集成解决方案领域,熟悉业内主要的 SOA 集成产品。参加过北京马拉松和 TNF50 越野比赛。你可以通过邮件 arthur.jin@oracle.com 与他联系。