Oracle® Fusion Middleware Oracle Coherenceリモート・クライアントの開発

12c (12.1.2)

B70742-01(原本部品番号:E26037-01)

目次

例一覧

図一覧

表一覧

タイトルおよび著作権情報

はじめに

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

このガイドで説明する新機能

- 12c (12.1.2)での新機能および変更された機能

- 12c (12.1.2)に関するこのドキュメントにおけるその他の大きな変更

第I部 スタート・ガイド

1 Coherence*Extendの概要

- 1.1 Coherence*Extendの概要

- 1.2 クライアントの種類

- 1.2.1 データ・クライアント

- 1.2.2 リアルタイム・クライアント

- 1.3 クライアントAPI

- 1.4 POFシリアライズ

- 1.5 クライアント構成ファイルの理解

2 クライアント・ディストリビューションのインストール

- 2.1 Coherence for Javaのインストール

- 2.2 C++クライアント・ディストリビューションのインストール

- 2.2.1 サポートされている環境

- 2.2.2 Microsoft固有の要件

- 2.2.3 Coherence for C++ディストリビューションの抽出

- 2.3 .NETクライアント・ディストリビューションのインストール

- 2.3.1 前提条件

- 2.3.2 インストーラの実行

- 2.3.3 Coherence .NETバージョン番号マッピング

- 2.3.4 Coherence for .NETのデプロイ

- 2.4 Coherence*Extendのバージョン間の互換性

3 最初のExtendクライアントの構築

- 3.1 Extendサンプルの概要

- 3.2 ステップ1: クラスタ側の構成

- 3.3 ステップ2: クライアント側の構成

- 3.4 ステップ3: サンプル・クライアントの作成

- 3.5 ステップ4: キャッシュ・サーバー・プロセスの開始

- 3.6 ステップ5: アプリケーションの実行

4 Coherence*Extendの設定

- 4.1 概要

- 4.2 クラスタ側の構成

- 4.2.1 拡張プロキシ・サービスの設定

- 4.2.1.1 単一のプロキシ・サービスの定義

- 4.2.1.2 複数のプロキシ・サービス・インスタンスの定義

- 4.2.1.3 複数のプロキシ・サービスの定義

- 4.2.1.4 クラスタ・サービス・プロキシの無効化

- 4.2.1.5 NamedCache読取り専用アクセスの指定

- 4.2.1.6 NamedCacheロックの指定

- 4.2.2 Extendクライアントで使用するキャッシュの定義

- 4.2.3 プロキシ・サーバーでのストレージの無効化

- 4.3 クライアント側の構成

- 4.3.1 リモート・キャッシュの定義

- 4.3.2 バック・キャッシュとしてのリモート・キャッシュの使用方法

- 4.3.3 リモート起動スキームの定義

- 4.3.4 複数のリモート・アドレスの定義

- 4.3.5 接続エラーの検出

- 4.3.6 TCMP通信の無効化

- 4.4 TCPアドレス用のアドレス・プロバイダ参照の使用方法

- 4.5 ネーム・サービス・アクセプタを使用したプロキシへの接続

- 4.6 TCPアドレス用のカスタム・アドレス・プロバイダの使用方法

- 4.7 ロード・バランシング接続

- 4.7.1 プロキシベースのロード・バランシングの使用方法

- 4.7.1.1 プロキシベースのロード・バランシングのデフォルト・アルゴリズムの理解

- 4.7.1.2 カスタムのプロキシベース・ロード・バランシングの戦略の実装

- 4.7.2 クライアントベースのロード・バランシングの使用方法

- 4.8 Extendクライアントでのネットワーク・フィルタの使用方法

5 Coherence*Extendのベスト・プラクティス

- 5.1 ローカル記憶域を無効にしてプロキシ・サーバーを実行する

- 5.2 プロキシ・サーバーでニア・キャッシュを実行しない

- 5.3 ヒープNIO領域を最大ヒープ・サイズと同じ値に構成する

- 5.4 Proxyサービスのスレッド・プールの構成

- 5.4.1 Proxyサービスのスレッドの理解

- 5.4.2 Proxyサービスのスレッド・プールのしきい値の設定

- 5.4.3 正確なスレッド数の設定

- 5.5 InvocationServiceをコールするときの注意事項

- 5.6 キャッシュにコレクション・クラスを書き込むときの注意事項

- 5.7 キャッシュ・サーバーに対してPOFシリアライザを構成する

- 5.8 スレッドのロックでなくノードのロックを使用する

第II部 Java Extendクライアントの作成

第III部 C++ Extendクライアントの作成

6 C++アプリケーション・ビルドの設定

- 6.1 Coherenceベースのアプリケーション向けのコンパイラの設定

- 6.2 Coherenceのヘッダー・ファイルの組込み

- 6.3 >Coherenceライブラリのリンク

- 6.4 ランタイム・ライブラリと検索パスの設定

- 6.5 Coherence for C++のデプロイメント

7 C++クライアントの構成と使用

- 7.1 一般的な手順

- 7.2 C++アプリケーションの実装

- 7.3 アプリケーションのコンパイルとリンク

- 7.4 パスの構成

- 7.5 Coherence*Extendの構成

- 7.5.1 クラスタでのCoherence*Extendの構成

- 7.5.2 クライアントでのCoherence*Extendの構成

- 7.5.2.1 C++クライアント用ローカル・キャッシュの定義

- 7.5.2.2 C++クライアント用ニア・キャッシュの定義

- 7.5.3 接続エラーの検出とフェイルオーバー

- 7.6 C++によるキャッシュ参照の取得

- 7.7 キャッシュに関連付けられたリソースのクリーンアップ

- 7.8 Coherence for C++クライアント・ライブラリの構成と使用

- 7.8.1 環境変数による構成ファイルの場所の設定

- 7.8.2 プログラム処理による構成ファイルの場所の設定

- 7.9 オペレーション構成ファイル(tangosol-coherence-override.xml)

- 7.10 Loggerの構成

- 7.11 CoherenceのDefaultCacheServerプロキシの起動

8 CoherenceのC++オブジェクト・モデルの使用

- 8.1 オブジェクト・モデルの使用

- 8.1.1 Coherenceのネームスペース

- 8.1.2 ベース・オブジェクトの理解

- 8.1.3 自動管理メモリー

- 8.1.3.1 管理オブジェクトの参照

- 8.1.3.2 ハンドルの使用

- 8.1.3.3 管理オブジェクトのインスタンス化

- 8.1.4 管理文字列

- 8.1.4.1 文字列のインスタンス化

- 8.1.4.2 自動ボックス付き文字列

- 8.1.5 型保証キャスト

- 8.1.5.1 ダウン・キャスト

- 8.1.6 マネージ配列

- 8.1.7 コレクション・クラス

- 8.1.8 マネージ例外

- 8.1.9 オブジェクトの不変性

- 8.1.10 オブジェクト・モデルへの既存のクラスの統合

- 8.2 新規管理クラスの作成

- 8.2.1 仕様に基づく管理クラスの定義

- 8.2.2 等価性、ハッシング、クローニング、不変性およびシリアライズ

- 8.2.3 スレッド処理

- 8.2.4 弱参照

- 8.2.5 仮想コンストラクタ

- 8.2.6 高度なハンドル・タイプ

- 8.2.7 スレッド・セーフティ

- 8.2.7.1 同期および通知

- 8.2.7.2 スレッド・セーフなハンドル

- 8.2.7.3 エスケープ分析

- 8.2.7.4 スレッドローカル・アロケータ

- 8.3 診断およびトラブルシューティング

- 8.3.1 スレッド・ダンプ

- 8.3.2 メモリー・リーク検出

- 8.3.3 メモリー破損の検出

- 8.4 アプリケーション・ランチャ - Sanka

- 8.4.1 コマンドラインの構文

- 8.4.2 組込み実行可能ファイル

- 8.4.3 カスタム実行可能ファイル・クラスのサンプル

9 Coherence for C++クライアントAPIの使用

- 9.1 CacheFactory

- 9.2 NamedCache

- 9.3 QueryMap

- 9.4 ObservableMap

- 9.5 InvocableMap

- 9.6 Filter

- 9.7 値エクストラクタ

- 9.8 入力プロセッサ

- 9.9 エントリ・アグリゲータ

10 統合オブジェクトの構築(C++)

- 10.1 統合オブジェクトの構築(C++)の概要

- 10.2 POFの組込み型

- 10.3 シリアライズの各オプション

- 10.3.1 Managed<T>(自由関数シリアライズ)

- 10.3.2 PortableObject(自己シリアライズ)

- 10.3.3 PofSerializer(外部シリアライズ)

- 10.4 POFオブジェクト参照の使用方法

- 10.4.1 POFオブジェクト参照の有効化

- 10.4.2 循環構造のオブジェクトやネストされたオブジェクトへのPOFオブジェクトIDの登録

- 10.5 カスタムのC++型の登録

- 10.6 JavaバージョンのC++オブジェクトの実装

- 10.7 シリアライズのパフォーマンスの理解

- 10.8 POF注釈を使用したオブジェクトのシリアライズ

- 10.8.1 POFシリアライズでのオブジェクトへの注釈付け

- 10.8.2 POF注釈付きオブジェクトの登録

- 10.8.3 自動索引付けの有効化

- 10.8.4 カスタム・コーデックの提供

11 キャッシュの問合せ(C++)

- 11.1 問合せの機能の概要

- 11.2 単純な問合せの実行

- 11.2.1 パーティション・キャッシュの問合せ

- 11.2.2 ニア・キャッシュの問合せ

- 11.3 問合せの概念の理解

- 11.4 複数値属性が関係する問合せの実行

- 11.5 問合せでの連鎖エクストラクタの使用

- 11.6 問合せレコーダの使用

12 連続問合せの実行(C++)

- 12.1 連続問合せの実行の概要(C++)

- 12.1.1 連続問合せキャッシュのユース・ケースの理解

- 12.2 連続問合せキャッシュの実装の理解

- 12.3 連続問合せキャッシュの定義

- 12.4 連続問合せキャッシュ・リソースのクリーンアップ

- 12.5 キーのみのキャッシングと、キーおよび値のキャッシング

- 12.5.1 CacheValuesプロパティとイベント・リスナー

- 12.5.2 連続問合せキャッシュでのReflectionExtractorの使用

- 12.6 連続問合せキャッシュのリスニング

- 12.6.1 予期しない結果の回避

- 12.6.2 安定したマテリアライズド・ビューの実現

- 12.6.3 同期および非同期リスナーのサポート

- 12.7 連続問合せキャッシュを読取り専用にする

13 リモート起動の実行(C++)

- 13.1 リモート起動の実行の概要(C++)

- 13.2 リモート起動サービスの構成と使用

- 13.3 Invocable実装クラスの登録

14 キャッシュ・イベントの使用方法(C++)

- 14.1 マップ・イベントの概要(C++)

- 14.1.1 イベントをサポートするキャッシュとクラス

- 14.2 すべてのイベントのサインアップ

- 14.3 多重化マップ・リスナーの使用

- 14.4 キャッシュ用のMapListenerの構成

- 14.5 特定のIDのイベントのサインアップ

- 14.6 イベントのフィルタリング

- 14.7 Liteイベントの使用

- 14.8 問合せのリスニング

- 14.9 統合イベントの使用

- 14.10 バッキング・マップ・イベントの使用

- 14.11 同期イベント・リスナーの使用

15 トランザクションの実行(C++)

- 15.1 入力プロセッサ内でのトランザクションAPIの使用方法

- 15.2 トランザクション入力プロセッサ用のスタブ・クラスの作成

- 15.3 トランザクション入力プロセッサのユーザー・タイプの登録

- 15.4 クラスタ側のトランザクション・キャッシュの構成

- 15.5 クライアント側のリモート・キャッシュの構成

- 15.6 C++クライアントからのトランザクション入力プロセッサの使用方法

第IV部 .NET Extendクライアントの作成

16 .NETクライアントの構成と使用

- 16.1 一般的な手順

- 16.2 Coherence*Extendの構成

- 16.2.1 クラスタでのCoherence*Extendの構成

- 16.2.2 クライアントでのCoherence*Extendの構成

- 16.2.2.1 .NETクライアント用ローカル・キャッシュの定義

- 16.2.2.2 .NETクライアント用ニア・キャッシュの定義

- 16.2.3 接続エラーの検出とフェイルオーバー

- 16.3 CoherenceのDefaultCacheServerプロセスの起動

- 16.4 .NETによるキャッシュ参照の取得

- 16.5 キャッシュに関連付けられたリソースのクリーンアップ

- 16.6 ネットワーク・フィルタの使用方法

- 16.6.1 カスタム・フィルタ

- 16.6.2 フィルタの構成

17 統合オブジェクトの構築(.NET)

- 17.1 統合オブジェクトの構築(.NET)の概要

- 17.2 IPortableObject実装の作成

- 17.3 Javaバージョンの.NETオブジェクトの実装

- 17.3.1 PortableObject実装の作成(Java)

- 17.4 .NETクライアントでのカスタム型の登録

- 17.5 クラスタでのカスタム型の登録

- 17.6 進化可能な移植性のあるユーザー定義型

- 17.7 変更なしで型を移植可能にする

- 17.8 POFオブジェクト参照の使用方法

- 17.8.1 POFオブジェクト参照の有効化

- 17.8.2 循環構造のオブジェクトやネストされたオブジェクトへのPOFオブジェクトIDの登録

- 17.9 POF注釈を使用したオブジェクトのシリアライズ

- 17.9.1 POFシリアライズでのオブジェクトへの注釈付け

- 17.9.2 POF注釈付きオブジェクトの登録

- 17.9.3 自動索引付けの有効化

- 17.9.4 カスタム・コーデックの提供

18 Coherence .NETクライアント・ライブラリの使用

- 18.1 Coherence .NETクライアント・ライブラリの設定

- 18.2 Coherence .NET APIの使用

- 18.2.1 CacheFactory

- 18.2.2 IConfigurableCacheFactory

- 18.2.3 DefaultConfigurableCacheFactory

- 18.2.4 Logger

- 18.2.5 Common.Loggingライブラリの使用

- 18.2.6 INamedCache

- 18.2.7 IQueryCache

- 18.2.8 QueryRecorder

- 18.2.9 IObservableCache

- 18.2.9.1 キャッシュ・イベントへの応答

- 18.2.10 IInvocableCache

- 18.2.11 フィルタ

- 18.2.12 値エクストラクタ

- 18.2.13 入力プロセッサ

- 18.2.14 エントリ・アグリゲータ

19 連続問合せの実行(.NET)

- 19.1 連続問合せの実行の概要(.NET)

- 19.1.1 連続問合せキャッシュのユース・ケースの理解

- 19.2 連続問合せキャッシュの実装の理解

- 19.3 連続問合せキャッシュの構成

- 19.4 連続問合せキャッシュ・リソースのクリーンアップ

- 19.5 キーのみのキャッシングと、キーおよび値のキャッシング

- 19.6 連続問合せキャッシュのリスニング

- 19.6.1 安定したマテリアライズド・ビューの実現

- 19.6.2 同期および非同期リスナーのサポート

- 19.7 連続問合せキャッシュを読取り専用にする

20 リモート起動の実行(.NET)

- 20.1 リモート起動の実行の概要

- 20.2 リモート起動サービスの構成と使用

21 トランザクションの実行(.NET)

- 21.1 入力プロセッサ内でのトランザクションAPIの使用方法

- 21.2 トランザクション入力プロセッサ用のスタブ・クラスの作成

- 21.3 トランザクション入力プロセッサのユーザー・タイプの登録

- 21.4 クラスタ側のトランザクション・キャッシュの構成

- 21.5 クライアント側のリモート・キャッシュの構成

- 21.6 .NETクライアントからのトランザクション入力プロセッサの使用方法

22 ASP.NETセッション状態の管理

- 22.1 概要

- 22.2 Coherenceセッション管理の設定

- 22.2.1 Coherenceセッション・プロバイダの有効化

- 22.2.2 クラスタ側のASPセッション・キャッシュの構成

- 22.2.3 クライアント側のASPセッション・リモート・キャッシュの構成

- 22.2.4 デフォルトのセッション・キャッシュ名のオーバーライド

- 22.3 セッション・モデルの選択

- 22.3.1 セッション・モデルの指定

- 22.3.1.1 バッキング・マップ・リスナーの登録

- 22.4 シリアライザの指定

- 22.4.1 POFを使用したセッションのシリアライズ

- 22.5 アプリケーション間でのセッション状態の共有

第V部 Coherence RESTの使用方法

23 Coherence RESTについて

- 23.1 Coherence RESTの概要

- 23.2 Coherence RESTの依存性

- 23.3 Coherence RESTの構成の概要

- 23.4 データ・フォーマットのサポートの理解

- 23.4.1 データ・フォーマットとしてのXMLの使用方法

- 23.4.2 データ・フォーマットとしてのJSONの使用方法

- 23.5 Coherence RESTクライアントの認証と認可

24 最初のCoherence RESTアプリケーションの作成

- 24.1 Coherence RESTの例の概要

- 24.2 ステップ1: クラスタ側の構成

- 24.3 ステップ2: ユーザー・タイプの作成

- 24.4 ステップ3: RESTサービスの構成

- 24.5 ステップ4: キャッシュ・サーバー・プロセスの開始

- 24.6 ステップ5: クライアントからRESTサービスへのアクセス

25 RESTによるグリッド操作の実行

- 25.1 キーおよび値のタイプの指定

- 25.2 単一オブジェクトのREST操作の実行

- 25.3 複数オブジェクトのREST操作の実行

- 25.4 部分オブジェクトのREST操作の実行

- 25.5 RESTによる問合せの実行

- 25.5.1 直接問合せの使用

- 25.5.2 名前付き問合せの使用

- 25.5.3 問合せのソート順の指定

- 25.5.4 問合せのサイズの制限

- 25.5.5 キーのみの取出し

- 25.5.6 カスタム問合せエンジンの使用

- 25.5.6.1 カスタム問合せエンジンの実装

- 25.5.6.2 カスタム問合せエンジンの有効化

- 25.6 RESTによる集計の実行

- 25.6.1 RESTの集計の構文

- 25.6.2 事前定義のアグリゲータのリスト

- 25.6.3 カスタム・アグリゲータの作成

- 25.7 RESTによるエントリ処理の実行

- 25.7.1 RESTのエントリ・プロセッサの構文

- 25.7.2 事前定義のエントリ・プロセッサのリスト

- 25.7.3 カスタム・エントリ・プロセッサの作成

- 25.8 並列処理制御の理解

- 25.9 キャッシュの別名の指定

26 Coherence RESTのデプロイ

- 26.1 埋込みHTTPサーバーによるデプロイ

- 26.2 WebLogicサーバーへのデプロイ

- 26.2.1 タスク1: Coherence RESTのWebLogicサーバー・ドメインの構成

- 26.2.2 タスク2: Coherence REST Webアプリケーションのパッケージ化

- 26.2.3 タスク3: Coherenceアプリケーションのパッケージ化

- 26.2.4 タスク4: エンタープライズ・アプリケーションのパッケージ化

- 26.2.5 タスク5: エンタープライズ・アプリケーションのデプロイ

- 26.3 Java EEサーバー(一般)へのデプロイ

- 26.3.1 デプロイメント用のCoherence RESTのパッケージ化

- 26.3.2 GlassFishへのデプロイ

- 26.3.3 サーブレット・コンテナへのデプロイ

27 デフォルトのREST実装の変更

- 27.1 カスタム・プロバイダおよびリソースの使用方法

- 27.2 埋込みHTTPサーバーの変更

- 27.2.1 Grizzly HTTPサーバーの使用方法

- 27.2.2 Simple HTTPサーバーの使用方法

A RESTの構成要素

- A.1 REST構成ファイル

- 要素リファレンス

- aggregator

- aggregators

- engine

- marshaller

- processor

- processors

- query

- query-engines

- resource

- resources

- rest

B F5 BIG-IP LTMとの統合

- B.1 基本概念

- B.2 ノードの作成

- B.3 ロード・バランシング・プールの構成

- B.3.1 ロード・バランシング・プールの作成

- B.3.2 ロード・バランシング・プールのメンバーの追加

- B.4 仮想サーバーの構成

- B.5 BIG-IP LTMを使用するようにCoherence*Extendを構成する方法

- B.6 高度なヘルス・モニタリングの使用方法

- B.6.1 カスタム・ヘルス・モニターを作成してCoherenceにpingを送信する方法

- B.6.2 カスタム・ヘルス・モニターをロード・バランシング・プールと関連付ける方法

- B.7 SSLオフロードの有効化

- B.7.1 サーバーのSSL証明書とキーのインポート

- B.7.2 クライアントSSLプロファイルの作成

- B.7.3 クライアントSSLプロファイルの関連付け

例一覧

- 3-1 Coherence*Extendアプリケーションのサンプル

- 4-1 拡張プロキシ・サービスの構成

- 4-2 リモート・キャッシュの定義

- 4-3 リモート起動スキームの定義

- 5-1 記憶域の無効化

- 5-2 ArrayListオブジェクトのキャスト

- 5-3 分散キャッシュに対するPOFシリアライザの構成

- 7-1 build.cmdファイルの実行例

- 7-2 2つのクラスタ・サービスのキャッシュ構成

- 7-3 リモートCoherenceクラスタに接続するキャッシング・スキーム

- 7-4 ローカル・キャッシュ構成

- 7-5 ニア・キャッシュの構成

- 7-6 構成ファイルの場所の設定

- 7-7 Coherenceキャッシュ・ファクトリの作成

- 7-8 CacheFactoryとローカル・メンバーの構成

- 7-9 サーバー/クラスタのキャッシュ構成ファイルの場所の設定

- 7-10 オペレーション構成のサンプル

- 7-11 ログ出力を扱うオペレーション構成ファイル

- 7-12 DefaultCacheServerを起動するコマンドのサンプル

- 8-1 Stringオブジェクトの構成例

- 8-2 <<演算子を使用したStringオブジェクトの構成

- 8-3 自動ボックス付け処理の例

- 8-4 型保証キャストの例

- 8-5 ダウン・キャストの例

- 8-6 instanceof<H>関数によるオブジェクト型のチェック

- 8-7 配列の索引付け

- 8-8 管理オブジェクトのインスタンスの格納

- 8-9 マネージ例外を使用したtry/catchブロック

- 8-10 interface_specで定義するインタフェース

- 8-11 interface_specで定義する派生インタフェース

- 8-12 cloneable_specで定義する実装

- 8-13 specを使用しないクラスの定義

- 8-14 specを使用したクラスの定義

- 8-15 Runnableインスタンスの作成とスレッドの生成

- 8-16 COH_SYNCHRONIZEDマクロ・コード・ブロックのサンプル

- 8-17 スレッド・セーフ・ハンドル

- 8-18 非管理クラスとしてのスレッド・セーフ・ハンドル

- 8-19 スレッドのダンプのサンプル

- 8-20 ヒープ・アナライザから返されたデータ

- 8-21 メモリー破損検出の実行結果

- 9-1 EqualsFilterメソッドの使用方法

- 9-2 GreaterEqualsFilterメソッドの使用方法

- 9-3 LikeFilterメソッドの使用方法

- 9-4 AndFilterメソッドの使用方法

- 9-5 OrFilterメソッドの使用方法

- 10-1 非管理クラス

- 10-2 シリアライズを使用した管理クラス

- 10-3 Managed<T>でラップしたクラスのインスタンス

- 10-4 PortableObjectを実装する管理クラス

- 10-5 Managed<T>を使用しない管理クラス

- 10-6 非PortableObjectバージョンの管理クラス

- 10-7 シリアライズを担当する外部クラス

- 11-1 キャッシュの内容の問合せ

- 11-2 LimitFilterメソッドの使用方法

- 11-3 問合せ可能な属性に対する索引付け

- 11-4 特定のフィルタに適合するキャッシュ・エントリの選択

- 11-5 エントリの選択およびソート

- 11-6 keySet形式の問合せの使用

- 11-7 複数値属性に対する索引付けおよび問合せ

- 11-8 ChainedExtractor実装の使用

- 12-1 フィルタを使用した問合せ

- 12-2 連続問合せキャッシュへのリスナーの配置

- 12-3 フィルタとリスナーを使用する連続問合せキャッシュの作成

- 12-4 データを処理してからリスナーを追加する場合

- 12-5 リスナーを追加してからデータを処理する場合

- 13-1 リモート起動スキーム構成のサンプル

- 13-2 リモート起動サービスへの参照

- 14-1 ObservableMapのメソッド

- 14-2 MapListener実装のサンプル

- 14-3 イベントの出力

- 14-4 リスナーへの参照の保持

- 14-5 リスナーへの参照の削除

- 14-6 MultiplexingMapListenerを使用したイベントのルーティング

- 14-7 指定したIntegerキーに対して発生したイベントの出力

- 14-8 指定したIntegerキーの値に対するイベントのトリガー

- 14-9 削除されたイベントのみを許可するフィルタを指定したリスナーの追加

- 14-10 キャッシュに対するデータの挿入および削除

- 14-11 値の挿入、更新、削除

- 14-12 Liteイベントのみのリクエスト

- 14-13 キャッシュ・イベントのフィルタリング

- 14-14 特化されたイベントのフィルタリング

- 14-15 ネットワークを介した、特化されたイベントのみの伝達

- 14-16 クライアントに起因するイベントと統合イベントの区別

- 15-1 拡張クライアント・トランザクション用の入力プロセッサ

- 15-2 トランザクション入力プロセッサのC++スタブ・クラス

- 15-3 トランザクション入力プロセッサのC++スタブ・クラス・ヘッダー・ファイル

- 16-1 Coherence*Extendに対応したデフォルト・キャッシュ・サーバーの構成

- 16-2 リモートCoherenceクラスタに接続するための構成

- 16-3 ローカル・キャッシュの構成

- 16-4 ニア・キャッシュの構成

- 16-5 Coherenceのデフォルト・キャッシュ・サーバーを起動するコマンド

- 16-6 キャッシュへの参照の取得

- 16-7 キャッシュへの参照の取得と解放

- 16-8 IWrapperStreamFactoryインタフェースのメソッド

- 17-1 移植可能なユーザー定義クラス

- 17-2 Javaでのユーザー定義クラス

- 17-3 POFユーザー定義型構成ファイルへのマッピング情報の格納

- 17-4 キャッシュ構成ファイルでのserializerの使用

- 17-5 POF構成ファイルの指定

- 17-6 クラスタ側のPOF構成ファイル

- 17-7 POF構成ファイルを使用するためのサーバーの構成

- 17-8 クラスの進化をサポートするようにクラスを変更する

- 17-9 クラスの進化をサポートするようにJava型のクラスを変更する

- 17-10 .NET型のIPofSerializerの実装

- 17-11 Java型クラスのPofSerializerの実装

- 17-12 .NET型のIPofSerializer実装の登録

- 17-13 Java型のPofSerializer実装の登録

- 18-1 アプリケーション構成ファイルのサンプル

- 18-2 INamedCacheインスタンスのファクトリの構成

- 18-3 ConfigurableCacheFactory実装の構成

- 18-4 別のキャッシュ構成ディスクリプタ・ファイルの指定

- 18-5 Loggerの構成

- 18-6 特定の値に関するキーの問合せ

- 18-7 挿入されたオブジェクトに対するフィルタリング

- 18-8 削除されたオブジェクトに対するフィルタリング

- 18-9 変更されたオブジェクトに対するフィルタリング

- 18-10 UIスレッドでのコールのマーシャリングと実行

- 18-11 キャッシュ・イベントに応じたメソッドのコール

- 18-12 ある数値と等しいキーの取得

- 18-13 ある数値より大きいか、それと等しいキーの取得

- 18-14 ある文字列値に基づいたキーの取得

- 18-15 大文字と小文字を区別する文字列値に基づいたキーの取得

- 18-16 ある数値より大きいキャッシュ・エントリの取得

- 18-17 ある文字列値に基づいたキャッシュ・エントリの取得

- 18-18 ある数値に基づいたキー値の条件付き設定

- 18-19 ある数値に基づいたキー値の設定

- 18-20 キャッシュのサイズを返す

- 18-21 IDictionaryを返す

- 19-1 連続問合せキャッシュへの参照の取得と解放

- 19-2 連続問合せキャッシュへのキーのみのキャッシュ

- 19-3 連続問合せキャッシュでのリスナーの配置

- 19-4 データを処理してからリスナーを配置する場合

- 19-5 リスナーを配置してからデータを処理する場合

- 19-6 連続問合せキャッシュの構成時にリスナーを提供する場合

- 19-7 連続問合せキャッシュを読取り専用にする

- 20-1 リモート起動サービスの構成

- 20-2 リモート起動サービスへの参照の取得

- 20-3 グリッド・ノードでのエージェントの実行

- 21-1 拡張クライアント・トランザクション用の入力プロセッサ

- 21-2 トランザクション入力プロセッサの.NETスタブ・クラス

図一覧

- 1-1 Coherence*Extendのコンポーネントの概念図

- 8-1 双方向の関係

- 8-2 弱参照の確立

- 8-3 ツリーに対する弱参照と強参照

- 8-4 弱参照の削除によって発生した状態

- 18-1 「参照の追加」ウィンドウ

- 18-2 構成ファイルを表示しているファイル・システム

- B-1 F5 BIG-IP LTMの概念図

- B-2 ノード構成例

- B-3 プール構成例

- B-4 プールのメンバー例

- B-5 仮想サーバー例

- B-6 構成プールを使用する仮想サーバー例

- B-7 Coherence*Extend pingヘルス・モニター例

- B-8 シェル・スクリプトで実装されたCoherence*Extendヘルス・モニター例

- B-9 Coherence*Extendプールをカスタム・ヘルス・モニターと関連付ける方法

- B-10 BIG-IPシステムにおけるSSL証明書構成例

- B-11 SSLプロファイル構成例

- B-12 クライアントSSLプロファイルのある仮想サーバー構成例

表一覧

- 2-1 Coherence for C++がサポートされているプラットフォームとオペレーティング・システム

- 6-1 MSVC (Visual Studio)向けのコンパイラの設定

- 6-2 g++向けのコンパイラの設定

- 6-3 リリース・バージョン向けおよびデバッグ・バージョン向けのリンク・ライブラリの名前

- 6-4 Coherence for C++のライブラリ名と環境変数

- 6-5 様々なオペレーティング・システム向けのキャッシュ構成のシステム・プロパティの値

- 8-1 Coherence for C++でサポートされている高度なハンドルのタイプ

- 10-1 シリアライズの各オプションの要件と制限

- 23-1 Coherence RESTの依存性

- 25-1 パラメータ型のヒント

- A-1 RESTの構成要素

- A-2 aggregatorの下位要素

- A-3 aggregatorsの下位要素

- A-4 engineの下位要素

- A-5 marshallerの下位要素

- A-6 processorの下位要素

- A-7 processorsの下位要素

- A-8 queryの下位要素

- A-9 query-enginesのサブ要素

- A-10 resourceの下位要素

- A-11 resourcesの下位要素

- A-12 restの下位要素

Oracle® Fusion Middleware

Oracle Coherenceリモート・クライアントの開発

12c (12.1.2)

B70742-01(原本部品番号:E26037-01)

2013年6月

ドキュメントは開発者やアーキテクトを対象にしており、Coherence*Extendを構成する方法や、リモート・クライアントをJava、C++および.NETで開発する方法について説明しています。Coherence RESTを使用してリモート・クライアントを開発する方法の指示についても記載されています。

Oracle Fusion Middleware Oracle Coherenceリモート・クライアントの開発, 12c (12.1.2)

B70742-01

Copyright © 2008, 2013, Oracle and/or its affiliates.All rights reserved.

原本著者:  Joseph Ruzzi

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

このソフトウェアまたは関連ドキュメントが、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供される場合は、次のNoticeが適用されます。

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007).Oracle USA, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

このソフトウェアまたはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアまたはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用する際、このソフトウェアまたはハードウェアを安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

OracleはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

このソフトウェアおよびドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。

はじめに

『Oracle Coherenceリモート・クライアントの開発』にようこそ。このドキュメントでは、Coherence*Extendの構成方法と、クライアントをJava、C++および.NETで開発する方法について説明します。また、Coherence RESTを使用してリモート・クライアントを開発する手順を説明します。

対象読者

このドキュメントは、ソフトウェア開発者およびアーキテクトを対象としています。Coherenceクラスタに存在するリモート・キャッシュと相互作用するC++および.NETアプリケーションを記述してデプロイするための詳細な技術的情報を提供します。このドキュメントは、これらの各技術に精通したユーザーを対象としています。また、クラスタに対してデータをシリアライズする場合は、Javaにも精通している必要があります。

ドキュメントのアクセシビリティについて

オラクル社のアクセシビリティへの取組みの詳細は、Oracle Accessibility ProgramのWebサイトhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=docaccを参照してください。

Oracleサポートへのアクセス

Oracleのお客様は、My Oracle Supportを使用して電子サポートにアクセスできます。詳細は、http://www.oracle.com/pls/topic/lookup?ctx=acc&id=infoまたはhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs (聴覚障害者向け)を参照してください。

関連ドキュメント

詳細は、Oracle Coherenceドキュメント・セットに付属の次のドキュメントを参照してください。

- Oracle Coherence*WebでのHTTPセッション・マネージメントの管理

- Oracle Coherenceの管理

- Oracle Coherenceでのアプリケーションの開発

- Oracle Coherenceの統合

- Oracle Coherenceの管理

- Oracle Coherenceの保護

- Oracle Coherenceチュートリアル

- Oracle Coherence Java APIリファレンス

- Oracle Coherence C++ APIリファレンス

- Oracle Coherence .NET APIリファレンス

- リリース・ノート

表記規則

このドキュメントでは次の表記規則を使用します。

規則

意味

太字

太字は、操作に関連するGraphical User Interface要素、または本文中で定義されている用語および用語集に記載されている用語を示します。

イタリック体

イタリックは、ユーザーが特定の値を指定するプレースホルダ変数を示します。

固定幅フォント

固定幅フォントは、段落内のコマンド、URL、サンプル内のコード、画面に表示されるテキスト、または入力するテキストを示します。

このガイドで説明する新機能

次のトピックでは、Oracle Coherenceの新機能や変更された機能について、およびこのガイドに記載されるその他の重要な変更について紹介し、詳細情報へのリンクを提供します。このドキュメントは、旧名『Oracle Coherenceクライアント・ガイド』の新版です。

12c (12.1.2)での新機能および変更された機能

Oracle Coherence 12c (12.1.2)のこのドキュメントには次の新機能と拡張機能があります。

- アドレス・プロバイダ参照では、オペレーション構成オーバーライド・ファイルにプロキシ・サービス、リモート・キャッシュおよびリモート起動アドレスを定義でき、キャッシュ構成ファイルから参照できます。「TCPアドレス用のアドレス・プロバイダ参照の使用方法」を参照してください。

- ネーム・サービスはExtendクライアントでは、プロキシ・サービス・アドレスではなく、プロキシ・サービス名を指定することでプロキシに接続できます。「ネーム・サービス・アクセプタを使用したプロキシへの接続」を参照してください。

- 動的スレッド・プールは、クライアント・リクエストの数、リクエストのバックログの合計数およびアイドル・スレッドの合計数を基に、プロキシ・サービスで使用可能なワーカー・スレッドの数を管理します。「Proxyサービスのスレッド・プールの構成」を参照してください。

- RESTの条件付きのGETリクエストは、クライアントのオブジェクトが最新バージョンかどうか判定できます。「GET操作」を参照してください。

- REST問合せ

- 名前付け問合せは、REST構成ファイルで定義することにより、リクエストURLに名前で使用できます。「名前付き問合せの使用方法」を参照してください。

- 問合せのサイズの制限は、問合せ結果セットのサイズを制御します。「問合せのサイズの制限」を参照してください。

- カスタム問合せエンジンは、デフォルトのCohQLセマンティクスではなく、別の問合せセマンティクスを使用できます。「カスタム問合せエンジンの使用」を参照してください。

- コンテキスト・パス構成は、複数のCoherence RESTアプリケーションを埋込みHTTPサーバーにデプロイできます。「埋込みHTTPサーバーのデプロイ」を参照してください。

12c(12.1.2)に関するこのドキュメントにおけるその他の大きな変更

このガイドは12c (12.1.2)でいくつかの点が更新されました。次に、追加または変更された項を示します。

- プロキシ・ロード・バランシングの手順を改定しました。「ロード・バランシング接続」を参照してください。

- Coherence RESTの依存性の項を改定しました。「Coherence RESTの依存性」を参照してください。

- WebLogicサーバーのCoherence RESTをデプロイする手順を改定し、WebLogicサーバー・ドメインの新しいパッケージ要件を含めました。「WebLogicサーバーへのデプロイ」を参照してください。

第I部

スタート・ガイド

第I部は、次の章で構成されています。

- 第1章「Coherence*Extendの概要」

- 第2章「クライアント・ディストリビューションのインストール」

- 第3章「最初のExtendクライアントの構築」

- 第4章「Coherence*Extendの設定」

- 第5章「Coherence*Extendのベスト・プラクティス」

1 Coherence*Extendの概要

この章では、Coherence*Extendについて説明し、サポートされているCoherenceクライアント(Java、C++および.NET)に関する情報を提供します。

この章には次の項が含まれます:

- Coherence*Extendの概要

- クライアントの種類

- クライアントAPI

- POFシリアライズ

- クライアント構成ファイルの理解

1.1 Coherence*Extendの概要

Coherence*Extendは、コアとなるCoherence TCMPクラスタの作用範囲を、デスクトップ、リモート・サーバー、WANに接続されたコンピュータなどのより広範な顧客環境に拡張します。Coherence*Extendの一般的な用途は、Coherenceキャッシュ(ニア・キャッシュや連続問合せのサポートを含む)にアクセスできるデスクトップ・アプリケーションを提供したり、待機時間の長い不安定なWANを介して接続された複数のCoherenceクラスタをリンクしたりすることです。

Coherence*Extendは、2つの基本コンポーネントで構成されます。それらは、クラスタの外部で実行されるExtendクライアントと、ストレージが無効な1台以上のキャッシュ・サーバー(DefaultCacheServer)に配置されたクラスタで実行される拡張プロキシ・サービスです。クライアントAPIにはCacheServiceインタフェースとInvocationServiceインタフェースの両方の実装が含まれており、これらによって、すべてのリクエストはプロキシにルーティングされます。プロキシは、実際のCoherenceクラスタ・サービス(パーティション化またはレプリケートされたキャッシュ・サービス、起動サービスなど)に委任することによってクライアント・リクエストに応答します。

Coherence*Extendでは、Extend-TCP転送バインディング(低レベルのメッセージ・プロトコル)を使用して、クライアントとクラスタの間の通信を行います。このプロトコルは、高性能でスケーラブルなTCP/IPベースの通信レイヤーです。転送バインディングは、構成により、Coherence*Extendを使用するクライアント・アプリケーションに対して完全に透過的に行われます。

図1-1は、Coherence*Extendのコンポーネントの概念図であり、Extend-TCPを使用してExtendクライアントを拡張プロキシ・サービスに接続している状態を示しています。

図1-1 Coherence*Extendのコンポーネントの概念図

「図1-1 Coherence*Extendのコンポーネントの概念図」の説明

キャッシュ・クライアントと同様に、Extendクライアントでは、キャッシュ・ファクトリを使用してCoherenceクラスタ・サービスを取得します。サービスを取得すると、クライアントでは、Coherenceクラスタの一部であるかのようにそのサービスを使用します。リモート・クラスタ・ノードに送信される操作は、クライアント・アプリケーションに対して透過的になります。

1.2 クライアントの種類

Extendクライアントは、Java、.NETおよびC++の各プラットフォーム用に作成でき、クラスタの完全なメンバーでなくとも、標準のCoherence APIと同等の充実したAPIにアクセスできます。通常、クライアント・アプリケーションでは、直接読取り/書込みアクセスを有効化できますが、クラスタ・データに対しては読取りアクセスのみが付与されます。クライアントには、データ・クライアントとリアルタイムExtendクライアントの2つのカテゴリがあります。

1.2.1 データ・クライアント

データ・クライアントは、クラスタ内のデータへのアクセス(入力、取得、問合せ)や、標準のCoherence APIを使用した起動サービス・リクエストが可能な、Extendクライアントです。特に、データ・クライアントには次の機能があります。

- NamedCacheインタフェースを使用したキーベースのキャッシュ・アクセス

- フィルタを使用した属性ベースのキャッシュ・アクセス

- InvocableMapインタフェースを使用したクラスタ側エントリのカスタム処理と集計

- LocalCacheを使用したインプロセス・キャッシング

- 起動サービスを使用したクラスタ内のカスタム・タスクのリモート起動

データ・クライアントの機能の詳細は、『Oracle Fusion Middlewareライセンス情報』を参照してください。

注意:

データ・クライアントには、クラスタ内のデータの変更は通知できません。さらに、データ・クライアントには、ニア・キャッシュや連続問合せキャッシュの機能はありません。これらの機能も、クラスタからのデータ変更通知を受信する機能に依存しているためです。これらの機能に関しては、リアルタイム・クライアントを使用する必要があります。

1.2.2 リアルタイム・クライアント

リアルタイム・クライアント(Extend-TCP)には、データ・クライアントと同じ機能が備わっています。ただし、データ・クライアントとは異なり、リアルタイム・クライアントでは次の機能もサポートされています。

- イベント通知 – 標準のCoherenceイベント・モデルを使用すると、クラスタ内で発生したデータの変更をクライアント・アプリケーションで確認できます。クライアント・アプリケーションで登録されたイベントのみが、ネットワークに配信されます。このモデルでは、ネットワーク帯域幅とクライアント処理が効率的に使用されます。

- ローカル・キャッシュ – クラスタで管理されるキャッシュにクライアント・アプリケーションが直接アクセスできても、ネットワーク・インフラストラクチャによっては効果がない場合があります。効率を高めるために、リアルタイム・クライアントでは、ニア・キャッシュと連続問合せの両方を使用して、キャッシュ・データをローカルに維持できます。クライアント・アプリケーションが接続されているサーバーで障害が発生した場合は、接続が別のサーバーとの間で自動的に再確立され、ローカルにキャッシュされているデータはクラスタとの間で再び同期化されます。

リアルタイム・クライアントの機能の詳細は、『Oracle Fusion Middlewareライセンス情報』を参照してください。

1.3 クライアントAPI

Java、C++および.NET (C#)の各ネイティブ・ライブラリを使用して、Extendクライアントを構築できます。APIはそれぞれ独自の方法で配布されており、別個にインストールする必要があります。Extendクライアントでは、それぞれのAPIを使用して、クラスタ内のデータに対して、アクセス、変更、問合せなどのキャッシュ操作を行います。C++ APIとC# APIは、プラットフォーム間の動作を一貫させるために、できるかぎりJava APIに従っています。

たとえば、JavaクライアントでCacheFactory.getCacheメソッドを使用してNamedCacheインスタンスを取得する場合は次のようになります。

NamedCache cache = CacheFactory.getCache("dist-extend");

C++の場合は、APIは次のようになります。

NamedCache::Handle hCache = CacheFactory::getCache("dist-extend");

C#の場合は、APIは次のようになります。

INamedCache cache = CacheFactory.GetCache("dist-extend");

この機能およびその他の多くのAPIの機能については、このガイドの次の各項でも説明します。

- Java: APIの使用方法の詳細は、第II部「Java Extendクライアントの作成」を、APIドキュメントの詳細は、Oracle Coherence Java APIリファレンスを参照してください。

- C++: APIの使用方法の詳細は、第III部「C++ Extendクライアントの作成」を、APIドキュメントの詳細は、Oracle Coherence C++ APIリファレンスを参照してください。

- .NET: APIの使用方法の詳細は、第IV部「.NET Extendクライアントの作成」を、APIドキュメントの詳細は、Oracle Coherence .NET APIリファレンスを参照してください。

1.4 POFシリアライズ

キャッシュ・クライアントと同様に、Extendクライアントでは、クラスタに格納するオブジェクトをシリアライズする必要があります。C++クライアントおよびC#クライアントでは、言語に依存しないバイナリ形式であるCoherenceのPortable Object Format (POF)を使用します。Java Extendクライアントでも、通常はPOFを使用してシリアライズを行います。ただし、Javaオブジェクトのシリアライズには、Javaネイティブ・シリアライズやカスタム・シリアライズ・ルーチンなど、他のオプションもいくつかあります。詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

オブジェクトをクラスタにシリアライズするクライアントでは、オブジェクトに対してgetベースとputベースの操作を実行できます。ただし、問合せや入力プロセッサなどの機能では、データ・オブジェクトのシリアライズ表現を保持するだけでなく、Javaベースのキャッシュ・サーバーを使用してデータ・オブジェクトと相互作用する必要があります。データ・オブジェクトと相互作用してそのプロパティにアクセスするには、キャッシュ・サーバーでJavaバージョンのオブジェクトを利用できようにする必要があります。

JavaでPOFの使用する際の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。C++およびC#でのPOFの使用方法の詳細は、それぞれ、第10章「統合オブジェクトの構築(C++)」および第17章「統合オブジェクトの構築(.NET)」を参照してください。

1.5 クライアント構成ファイルの理解

Extendクライアントは、複数の構成ファイルを使用して構成します。この構成ファイルは、クラスタ構成ファイルと同じです。ただし、クライアント構成ファイルはクライアントでデプロイされています。該当するファイルは次のとおりです。

- キャッシュ構成デプロイメント・ディスクリプタ – このファイルは、クライアント側のキャッシュ・サービスおよび起動サービスを定義するために使用します。クライアントの接続先であるクラスタ側の拡張プロキシ・サービスのアドレスとポートを指定する必要があります。このファイルのスキーマは、JavaおよびC++クライアント用がcoherence-cache-config.xsdで、.NETクライアント用がcache-config.xsdです。このファイルの要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。
実行時には、クラスパスで最初に検出されたキャッシュ構成ファイルが使用されます。tangosol.coherence.cacheconfigシステム・プロパティを使用して、キャッシュ構成ファイルを明示的に指定することもできます。このファイルは、プログラムによっても設定できます。キャッシュ構成デプロイメント・ディスクリプタの一般的な情報は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

- POF構成デプロイメント・ディスクリプタ – このファイルは、POFを使用してオブジェクトをシリアライズする際に、カスタム・データ型を指定するために使用します。このファイルのスキーマは、JavaおよびC++クライアント用がcoherence-pof-config.xsdで、.NETクライアント用がpof-config.xsdです。このファイルの要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。
実行時には、クラスパスで最初に検出されたPOF構成ファイルが使用されます。tangosol.pof.configシステム・プロパティを使用して、POF構成ファイルを明示的に指定することもできます。POFを使用すると、クライアント・アプリケーションでは、Coherence固有のPOF構成ファイルと、クライアントで使用されているユーザー定義型固有のPOF構成ファイルが使用されます。POF構成デプロイメント・ディスクリプタの一般的な情報は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

- オペレーション・オーバーライド・ファイル: このファイルは、オペレーション・デプロイメント・ディスクリプタをオーバーライドするために使用します。クラスタ・サービス、通信サービス、データ管理サービスを作成、構成および維持するために使用する、操作設定およびランタイム設定を指定します。Extendクライアントの場合、このファイルは通常、メンバーのID、ロギング、セキュリティおよびライセンスをオーバーライドするために使用します。このファイルのスキーマは、JavaおよびC++クライアント用がcoherence-operational-config.xsdで、.NETクライアント用がcoherence.xsdです。このファイルの要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。
実行時には、クラスパスで最初に検出されたオペレーション・オーバーライド・ファイル(tangosol-coherence-override.xml)が使用されます。tangosol.coherence.overrideシステム・プロパティを使用して、オペレーション・オーバーライド・ファイルを明示的に指定することもできます。このファイルは、プログラムによっても設定できます。オペレーション・オーバーライド・ファイルの一般的な情報は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

2 クライアント・ディストリビューションのインストール

この章では、Coherence C++および.NETのクライアント・ディストリビューションのインストール手順について説明します。Javaクライアント用の別個のディストリビューションはありません。Java Extendクライアントは、Coherence for Javaを使用して作成されます。

この章には次の項が含まれます:

- Coherence for Javaのインストール

- C++クライアント・ディストリビューションのインストール

- .NETクライアント・ディストリビューションのインストール

- Coherence*Extendのバージョン間の互換性

2.1 Coherence for Javaのインストール

Coherence for Javaディストリビューションは、JavaベースのExtendクライアントの構築および使用の際に使用します。Coherence for Javaをインストールするには、『Oracle Coherenceでのアプリケーションの開発』のOracle Coherence for Javaのインストールに関する項を参照してください。

2.1 C++クライアント・ディストリビューションのインストール

Oracle Coherence for C++ディストリビューションは、C++ Extendクライアントの開発および実行の際に使用します。ディストリビューションの最新バージョンは、Oracle Technology NetworkのCoherence製品に関するページからダウンロードできます。

http://www.oracle.com/technology/software/products/ias/htdocs/coherence.html

この項は次のトピックで構成されています。

- サポートされている環境

- Microsoft固有の要件

- Coherence for C++ディストリビューションの抽出

2.2.1 サポートされている環境

表2-1は、Coherence for C++がサポートされているプラットフォームおよびオペレーティング・システムのリストです。

表2-1 Coherence for C++がサポートされているプラットフォームとオペレーティング・システム

オペレーティング・システム

コンパイラ

アーキテクチャ

Microsoft Windows Server 2003以降

MSVC 2010、MSVC 2012

x86、x64

Sun Solaris 10+

SunPro 5.9以降脚注 2

SPARC、x86、x64

Linux

GCC 4.1.2以降、GNU libc 2.5以降

x86、x64

Apple OS X 10.7以降脚注 3

GCC 3.4以降

x64

脚注 1 具体的には、Sun C++ 5.9 SPARCパッチ124863-14以降がサポートされています。

脚注 2 具体的には、Sun C++ 5.9 x86/x64パッチ124864-14以降がサポートされています。

脚注 3 OS X Lion (10.7)とMountain Lion (10.8)が含まれます。

2.2.2 Microsoft固有の要件

Microsoft Windowsにデプロイする場合は、MSVCベースのアプリケーションの場合と同様に、対応するMSVCランタイム・ライブラリをデプロイメント・コンピュータにインストールする必要があります。

- Visual Studio 2012: x86またはx64向けの再配布可能なランタイム・ライブラリ。
http://www.microsoft.com/en-us/download/details.aspx?id=30679

- Visual Studio 2010: x86またはx64向けの再配布可能なランタイム・ライブラリ。
x86:

http://www.microsoft.com/en-us/download/details.aspx?id=5555

x64:

http://www.microsoft.com/en-us/download/details.aspx?id=14632

2.2.3 Coherence for C++ディストリビューションの抽出

Coherence for C++はZIPファイルとして配布されます。ZIPユーティリティまたはunzipコマンドライン・ユーティリティを使用して、ターゲット・コンピュータの任意の場所にZIPファイルを解凍します。抽出されたファイルは、coherence-cppという単一のディレクトリ内にまとめられています。

次の例では、unzipユーティリティを使用して、/optディレクトリ(UNIXベースのオペレーティング・システムで推奨されるインストール・ディレクトリ)にディストリビューションを抽出します。unzipユーティリティが使用できない場合は、ターゲットのオペレーティング・システムで提供されているZIPユーティリティを使用します。

unzip /path_to_zip/coherence-cpp-version_number-platform-architecture-compiler.zip -d /opt

次の例では、unzipユーティリティを使用して、Windowsオペレーティング・システムのC:\ディレクトリにディストリビューションを抽出します。

unzip C:\path_to_zip\coherence-cpp-version_number-platform-architecture-compiler.zip -d C:\

インストール・ディレクトリに含まれているディレクトリの説明は、次のとおりです。

- bin – このディレクトリに含まれるsanka.exeは、共有ライブラリ内に埋め込まれている実行可能クラスを起動するアプリケーション・ランチャです。

- doc – このディレクトリには、Coherence for C++に関するドキュメント(APIドキュメントを含む)が含まれています。

- include - このディレクトリには、Coherence APIを使用し、アプリケーションとともにコンパイルする必要があるヘッダー・ファイルが含まれています。

- lib – このディレクトリにはCoherence for C++ライブラリが含まれています。coherence.dllファイルは、開発およびランタイム用のメイン・ライブラリです。これについては、このドキュメント全体で詳細に説明します。

2.3 .NETクライアント・ディストリビューションのインストール

Oracle Coherence for .NETディストリビューションは、.NET Extendクライアントの開発および使用の際に使用します。ディストリビューションの最新バージョンは、Oracle Technology NetworkのCoherence製品に関するページからダウンロードできます。

http://www.oracle.com/technology/software/products/ias/htdocs/coherence.html

この項は次のトピックで構成されています。

- 前提条件

- インストーラの実行

- Coherence .NETバージョン番号マッピング

- Coherence for .NETのデプロイ

2.3.1 前提条件

Coherence for .NETを使用するには、次のものが必要です。

- Microsoft .NET 2.0以上のランタイムとSDK:
http://www.microsoft.com/download/en/default.aspx

- サポートされているMicrosoft Windowsオペレーティング・システム(前述の該当する.NETランタイムのシステム要件を参照)

- MSHelp 2.xランタイム。これは、Visual Studio 200x、および次のリストにあるMicrosoft製品に含まれています。
http://www.helpware.net/mshelp2/h20.htm#MS_H2_Runtime

- Coherence for Javaディストリビューションの一部として提供されているexample.zipファイル内の例を構築および実行するには、Microsoft Visual Studio 2008以上が必要です。

2.3.2 インストーラの実行

Coherence for .NETは、インストーラを含むZIPファイルとして配布されています。ZIPユーティリティまたはunzipコマンドライン・ユーティリティを使用して、ターゲット・コンピュータの任意の場所にインストーラを抽出します。次の例では、unzipユーティリティを使用して、C:\ディレクトリにインストーラを抽出します。

unzip C:\path_to_zip\coherence-net-version_number.zip -d C:\

インストーラを実行する手順は、次のとおりです。

1. ZIPファイルの抽出先のディレクトリで、coherence-net-version.msiファイルをダブルクリックします。

2. インストーラの指示に従ってインストールを完了します。

注意:

インストーラの実行中に、インストールをロールバックすると表示された場合は、実行モードのレベルを上げてインストーラを実行します。たとえば、管理者の権限でコマンド・プロンプトからMSIファイルを実行すれば、インストール・プロセスを完了できます。Windows 7の場合は、コマンド・プロンプトを右クリックして「管理者として実行」を選択します。

インストール・ディレクトリに含まれているディレクトリの説明は、次のとおりです。

- bin – このディレクトリにはCoherence for .NETライブラリが含まれています。Coherence.dllファイルは、開発およびランタイム用のメイン・ライブラリです。これについては、このドキュメント全体で詳細に説明します。

- config – このディレクトリには、Coherenceクライアント構成ファイル用のXMLスキーマと、Coherenceで定義したユーザー定義型に対するPOF構成ファイルが含まれています。

- doc – このディレクトリには、Coherence for .NETに関するAPIドキュメントが含まれています。APIドキュメントは、HTMLヘルプ(Coherence.chm)、MSHelp 2.0およびMS Help Viewerです。

2.3.3 Coherence .NETバージョン番号マッピング

Coherenceアセンブリは、カスタム・バージョン番号マッピングを使用します。Oracleバージョン番号は5桁 (N.N.N.N.N)を使用しますが、.NETバージョン番号は4桁(N.N.N.N)までしか使用できません。.NETのバージョン規則をサポートするために、.NETのバージョンの4桁目にOracleの4桁目および5桁目を組み合せます。

.NETのバージョンの4桁目の作成には次の計算が使用されます:

.NET4桁目= Oracle4桁目 * 1000 + Oracle5桁目

.NETのバージョンの4桁目をOracleのバージョンの5桁目に変換するには次の計算が使用されます:

Oracle4桁目= int(.NET4桁目 / 1000)

Oracle5桁目= .NET4桁目 - (Oracle4桁目 * 1000)

例:

.NETバージョン番号

Oracleバージョン番号

12.1.2.0

12.1.2.0.0

12.1.2.1

12.1.2.0.1

12.1.2.1000

12.1.2.1.0

12.1.2.1001

12.1.2.1.1

12.1.2.2010

12.1.2.2.10

12.1.2.10010

12.1.2.10.10

注意:

ロギングでは.NETの4桁目がOracleの4桁目および5桁目に変換されるため、JavaおよびC++のログ・メッセージと同じようにロギング・メッセージが表示されます。

2.3.4 Coherence for .NETのデプロイ

Coherence for .NETには、専用のデプロイメント構成は必要ありません。bin\フォルダにあるCoherence.dllへの参照を、Microsoft.NETアプリケーションに追加するのみです。

2.4 Coherence*Extendのバージョン間の互換性

ExtendプロトコルとPOFの互換性はポイント・リリース間では維持されますが(3.5、3.6など)、メジャー・リリース間では維持されません(2.0、3.0など)。さらに、ポイント・リリース間でもExtendクライアントからクラスタ・プロキシへの前方互換のみが維持されます。つまり、Extendクライアントは、同じバージョン番号以上のクラスタ・プロキシと接続可能です。Extendクライアントから、以前のバージョンのクラスタ・プロキシに接続を試行しないでください。

注意:

POFでは、下位互換のシリアライズ変更がサポート可能なため、POFを使用する場合は互換性が要求されます。

Coherence 12.1.2の後方互換性の例外

Coherence 12.1.2.*クラスタ・プロキシは、Extendクライアント・バージョン3.*と後方互換性があります。つまり、3.*クライアントは、12.1.2.*のクラスタ・プロキシと接続可能です。12.1.2.*の後方互換性は、前述のCoherence*Extendのバージョン互換性原則における例外の1つです。クラスタ・プロキシの12.1.2より後のバージョンには、現在の例外が含まれず、後方互換性が維持されません。

3 最初のExtendクライアントの構築

この章では、Coherence*Extendクライアントを構築および実行するために必要な、基本的なタスクについて説明します。この章で使用するクライアントの例はJavaベースのExtendクライアントですが、説明する概念はC++および.NET Extendクライアントにも共通しています。C++および.NETの完全な例は、Coherence for Javaディストリビューションの一部として配布されているCoherenceの例を参照してください。

この章には次の項が含まれます:

- Extendサンプルの概要

- ステップ1: クラスタ側の構成

- ステップ2: クライアント側の構成

- ステップ3: サンプル・クライアントの作成

- ステップ4: キャッシュ・サーバー・プロセスの開始

- ステップ5: アプリケーションの実行

3.1 Extendサンプルの概要

この章では、一連の手順を使用して、基本的なCoherence*Extendクライアントを作成、構成および実行します。各手順では、拡張プロキシの構成、リモート・キャッシュの構成、リモート起動サービスの構成、Coherence APIの使用など、Coherence*Extendの多数の基本的な概念について説明します。

手順を完了するには、Coherence for Javaをインストールする必要があります。わかりやすくするため、またデプロイしやすくするために、この例では、クライアントとキャッシュ・サーバーを同じコンピュータで実行します。通常は、Extendクライアントとキャッシュ・サーバーは、別々のシステムに配置されます。

3.2 ステップ1: クラスタ側の構成

この例のExtendクライアントでは、クラスタのキャッシュ構成デプロイメント・ディスクリプタで、拡張プロキシとキャッシュを構成する必要があります。拡張プロキシは、localhostおよびポート9099でクライアントのTCP/IP通信を受け入れるように構成します。dist-extendという名前の分散キャッシュを定義し、これを使用してクライアント・データをクラスタに格納します。

クラスタ側を構成する手順は、次のとおりです。

1. example-config.xmlという名前のXMLファイルを作成します。

2. このファイルに次のXMLをコピーします。

<?xml version="1.0"?>

<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend</cache-name>
<scheme-name>extend</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<distributed-scheme>
<scheme-name>extend</scheme-name>
<lease-granularity>member</lease-granularity>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>

3. ファイルを保存して閉じます。

3.3 ステップ2: クライアント側の構成

この例のExtendクライアントには、リモート・キャッシュ・スキームとリモート起動スキームが必要です。リモート・キャッシュ・スキームでは、データのキャッシュに使用するキャッシュをクラスタ上で定義する必要があり、クライアントの接続先となる拡張プロキシのアドレスとポートを指定する必要があります。この例では(ステップ1に基づく)、リモート・キャッシュ・スキームはdist-extendキャッシュを使用するように構成され、localhostおよび9099に配置されている拡張プロキシに接続します。

この例のExtendクライアントはリモート・キャッシュに問い合せるため、リモート起動スキームが必要です。リモート起動スキームでは、クライアントの接続先となる拡張プロキシのホストとポートも定義する必要があります。

クライアント側を構成する手順は、次のとおりです。

1. example-client-config.xmlという名前のXMLファイルを作成します。

2. このファイルに次のXMLをコピーします。

<?xml version="1.0"?>

<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend</cache-name>
<scheme-name>remote</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<remote-cache-scheme>
<scheme-name>remote</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>

<remote-invocation-scheme>
<scheme-name>extend-invocation</scheme-name>
<service-name>ExtendTcpInvocationService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-invocation-scheme>
</caching-schemes>
</cache-config>

3. ファイルを保存して閉じます。

3.4 ステップ3: サンプル・クライアントの作成

例3-1は、CacheServiceを使用してリモート・キャッシュ内のInteger値を増分してから、InvocationServiceを使用してキャッシュから値を取得する、単純なクライアントです。最後に、クライアントはシステム出力に値を書き込んでから終了します。

注意:

この例は、Coherenceノード(つまりクラスタ内)でもそのまま実行できます。TCP/IPを介してリモート・クラスタ・ノードに送信される操作は、クライアント・アプリケーションに対して完全に透過的になります。

サンプル・アプリケーションを作成する手順は、次のとおりです。

1. テキスト・ファイルを作成します。

2. このファイルに次のJavaコードをコピーします。

例3-1 Coherence*Extendアプリケーションのサンプル

import com.tangosol.net.AbstractInvocable;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.InvocationService;
import com.tangosol.net.NamedCache;
import java.util.Map;

public class TestClient {
public static void main(String[] asArgs)
throws Throwable
{
NamedCache cache  = CacheFactory.getCache("dist-extend");
Integer IValue = (Integer) cache.get("key");
if (IValue == null)
{
IValue = new Integer(1);
}
else
{
IValue = new Integer(IValue.intValue() + 1);
}
cache.put("key", IValue);

InvocationService service = (InvocationService)
CacheFactory.getConfigurableCacheFactory()
.ensureService("ExtendTcpInvocationService");

Map map = service.query(new AbstractInvocable()
{
public void run()
{
setResult(CacheFactory.getCache("dist-extend").get("key"));
}
}, null);

Integer IValue1 = (Integer) map.get(service.getCluster().
getLocalMember());
System.out.print("The value of the key is " + IValue1);
}
}

3. TestClient.javaという名前でファイルを保存して閉じます。

4. 次のようにTestClient.javaをコンパイルします。

javac -cp .;COHERENCE_HOME\lib\coherence.jar TestClient.java

Coherence*Extend InvocationService

当然、Coherence*Extendクライアントはクラスタやクラスタ内で実行されているメンバーを直接認識しないため、Coherence*Extend InvocationServiceのInvocableタスクを実行できるのは、クライアントが接続されているJVMに対してのみです。したがって、必ずnullメンバーをquery()メソッドに設定して渡す必要があります。結果として、実行による単一の結果がローカルのMemberを使用してキー設定されます(クライアントがクラスタの一部でない場合はnullに設定されます)。このMemberは、service.getCluster().getLocalMember()をコールすることで取得できます。またCoherence*Extend InvocationServiceは、同期タスクの実行のみをサポートします(つまりexecute()メソッドはサポートされません)。

3.5 ステップ4: キャッシュ・サーバー・プロセスの開始

拡張プロキシは、キャッシュ・サーバーのプロセス(DefaultCacheServer)の一環として開始されます。キャッシュ・サーバーは、ステップ1で作成したキャッシュ構成を使用するように構成する必要があります。また、キャッシュ・サーバー・プロセスは、実行時にクラスパス上でTestClientアプリケーションを検出できる必要があります。

次のコマンドラインでは、キャッシュ・サーバー・プロセスが開始され、tangosol.coherence.cacheconfigシステム・プロパティを使用して、ステップ1で作成したキャッシュ構成ファイルに明示的に名前が付けられます。

java -cp COHERENCE_HOME\lib\coherence.jar;PATH_TO_CLIENT -Dtangosol.coherence.cacheconfig=PATH\example-config.xml com.tangosol.net.DefaultCacheServer

コンソール出力をチェックして、プロキシ・サービスが開始されていることを確認します。出力メッセージは次のようになります。

(thread=Proxy:ExtendTcpProxyService:TcpAcceptor, member=1): TcpAcceptor now
listening for connections on 192.168.1.5:9099

3.6 ステップ5: アプリケーションの実行

javaコマンドを使用してTestClientアプリケーションを起動し、ステップ2で作成したキャッシュ構成ファイルを使用するように構成する必要があります。

次のコマンドラインでアプリケーションを実行します。ここでは、TestClientクラスが現在のディレクトリに配置されていると想定しています。キャッシュ構成ファイルは、tangosol.coherence.cacheconfigシステム・プロパティを使用して明示的に名前が付けられます。

java -cp .;COHERENCE_HOME\lib\coherence.jar -Dtangosol.coherence.cacheconfig=PATH\example-client-config.xml TestClient

出力には、クライアントが拡張プロキシのTCPアドレスに正常に接続したことやキャッシュ内のキーの現在の値などが表示されます。クライアントを再度実行すると、キーの値が増分します。

4 Coherence*Extendの設定

この章では、Coherence*Extendを構成する手順について説明します。この手順は、基本設定を行うためのものであり、完全な構成方法を示すものではありません。また、追加の構成手順については、このガイドのプラットフォーム固有の項を参照してください。

構成および設定も含むJavaの完全な例については、第3章「最初のExtendクライアントの構築」を参照してください。

この章には次の項が含まれます:

- 概要

- クラスタ側の構成

- クライアント側の構成

- TCPアドレス用のアドレス・プロバイダ参照の使用方法

- ネーム・サービス・アクセプタを使用したプロキシへの接続

- TCPアドレス用のカスタム・アドレス・プロバイダの使用方法

- ロード・バランシング接続

- Extendクライアントでのネットワーク・フィルタの使用方法

4.1 概要

Coherence*Extendでは、クライアント側とクラスタ側の両方の構成が必要です。クラスタ側では、クライアント・リクエストを受け入れるために拡張プロキシ・サービスが設定されます。プロキシ・サービスを使用することにより、クラスタ上で実行されるキャッシュ・サービス・インスタンスおよび起動サービス・インスタンスにアクセスできます。クライアント側では、リモート・キャッシュ・サービスおよびリモート起動サービスを構成し、それを使用して拡張プロキシ・サービス経由でクラスタにアクセスします。Extendクライアントと拡張プロキシ・サービスの間の通信にはTCP/IPが使用されます。

拡張プロキシ・サービスは、キャッシュ構成デプロイメント・ディスクリプタで構成されます。このデプロイメント・ディスクリプタは、多くの場合、クラスタ側のキャッシュ構成ファイルと呼ばれます。これは、クラスタでキャッシュを設定する際に使用するキャッシュ構成ファイルと同じです。Extendクライアントも、キャッシュ構成デプロイメント・ディスクリプタを使用して構成されます。このデプロイメント・ディスクリプタは、クライアントでデプロイされ、多くの場合、クライアント側のキャッシュ構成ファイルと呼ばれます。キャッシュ構成デプロイメント・ディスクリプタの詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

4.2 クラスタ側の構成

Coherenceクラスタには、Extendクライアントの接続を受け入れるための拡張プロキシ・サービスと、クライアントでデータを取得して格納する際に使用するキャッシュが組み込まれている必要があります。拡張プロキシ・サービスもキャッシュも、クラスタのキャッシュ構成デプロイメント・ディスクリプタで構成されます。拡張プロキシ・サービスおよびキャッシュは、キャッシュ・サーバー(DefaultCacheServer)のプロセスの一環として開始されます。

この項は、次のトピックで構成されています。

- 拡張プロキシ・サービスの設定

- Extendクライアントで使用するキャッシュの定義

- プロキシ・サーバーでのストレージの無効化

4.2.1 拡張プロキシ・サービスの設定

拡張プロキシ・サービス(ProxyService)は、ExtendクライアントからTCP/IPを使用してCoherenceクラスタにアクセスできるクラスタ・サービスです。プロキシ・サービスには、CacheServiceクラスタ・サービス(クライアントからキャッシュへのアクセスに使用)、およびInvocationServiceクラスタ・サービス(クライアントがクラスタ上でInvocableオブジェクトを実行する際に使用)の2種類のクラスタ・サービス用のプロキシが組み込まれています。

この項には、次のトピックが含まれます:

- 単一のプロキシ・サービスの定義

- 複数のプロキシ・サービス・インスタンスの定義

- 複数のプロキシ・サービスの定義

- クラスタ・サービス・プロキシの無効化

- NamedCache読取り専用アクセスの指定

- NamedCacheロックの指定

4.2.1.1 単一のプロキシ・サービスの定義

拡張プロキシ・サービスは、<caching-schemes>ノード内で、<proxy-scheme>要素を使用して構成します。子要素の<tcp-acceptor>には、TCP/IPクライアント通信のために拡張プロキシ・サービスがリスニングするアドレス(IPまたはDNS名と、ポート)が含まれます。アドレスは、<local-address>要素を使用して明示的に定義するか、オペレーション構成オーバーライド・ファイル内で定義できます。さらに、<address-provider>要素を使用して参照できます。後者の方法は、アドレス構成をプロキシ・スキーム定義から分離し、プロキシ定義を変更することなくランタイムでのアドレスの変更を可能にします。アドレス定義の参照の詳細は、「TCPアドレス用のアドレス・プロバイダ参照の使用方法」を参照してください。

例4-1では、198.168.1.5およびポート9099にバインドされているTCP/IPソケットでクライアント・リクエストをリスニングするように設定されている、ExtendTcpProxyServiceという名前のプロキシ・サービスを定義します。キャッシュと起動の両方のクラスタ・サービス・プロキシが、クライアント・リクエストに対して有効になっています。さらに、クラスタ・ノードでサービスが自動的に開始されるように、<autostart要素がtrueに設定されています。<proxy-schemeのすべてのサブ要素の一覧と説明は、『Oracle Coherenceでのアプリケーションの開発』の<proxy-scheme要素参照を参照してください。

例4-1 拡張プロキシ・サービスの構成

...
<caching-schemes>
<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.5</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<proxy-config>
<cache-service-proxy>
<enabled>true</enabled>
</cache-service-proxy>
<invocation-service-proxy>
<enabled>true</enabled>
</invocation-service-proxy>
</proxy-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
...

注意:

- わかりやすいように、前述の例では、キャッシュおよび起動のクラスタ・サービス・プロキシを明示的に有効にしています。ただし、いずれのプロキシもデフォルトで有効なため、<cache-service-proxy>要素と<invocation-service-proxy>要素をプロキシ・スキーム定義に含める必要はありません。

- <address>要素でも、サブネットおよびマスクとしてのCIDR記述の使用をサポートしています(例、192.168.1.0/24)。CIDRは、単一のアドレス構成によって、同一サブネット内のコンピュータ間での情報共有を可能にすることで、構成を単純化しています。各クラスタ・メンバーで同じCIDRアドレス・ブロックを指定すると、各コンピュータのローカルNICでは、自動的にアドレス・パターンの一致が検出されます。/24の接頭辞のサイズは、192.168.1.0から192.168.1.255までの256の使用可能アドレスと一致します。

4.2.1.2 複数のプロキシ・サービス・インスタンスの定義

予想されるクライアント接続数をサポートするため、およびフォルト・トレランスとロード・バランシングをサポートするために、複数の拡張プロキシ・サービス・インスタンスを定義できます。クライアント接続は、プロキシ・サービス・インスタンス間で自動的に調整されます。接続の調整に使用されているアルゴリズムは、構成されているロード・バランシングの戦略によって変わります。ロード・バランシングの詳細は、「ロード・バランシング接続」を参照してください。

複数のプロキシ・サービス・インスタンスを定義するには、単一のプロキシ・サービス定義を複数のキャッシュ・サーバーで読み込んで、各プロキシ・サービスに同じサービス名を使用します。同じサービス名のプロキシ・サービスはピアと見なすことができます。

次の例では、ExtendTcpProxyServiceプロキシ・サービスの2つのインスタンスを定義し、ポート9099にバインドされているTCP/IP ServerSocketでクライアント・リクエストをリスニングするように設定しています。プロキシ・サービス定義は、各キャッシュ・サーバーのそれぞれのキャッシュ設定ファイルで <proxy-scheme>要素内に含まれています。

キャッシュ・サーバー1:

...
<caching-schemes>
<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.5</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
...

キャッシュ・サーバー2:

...
<caching-schemes>
<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.6</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
...

4.2.1.3 複数のプロキシ・サービスの定義

複数の拡張プロキシ・サービスを定義することにより、それぞれのプロキシで異なるアプリケーションを提供できます。より予測性の高い環境を構築するために、特定のアプリケーションのExtendクライアントを特定のプロキシに誘導できます。

次の例では、2つの拡張プロキシ・サービスを定義します。ExtendTcpProxyService1は、198.168.1.5およびポート9099にバインドされているTCP/IP ServerSocketでクライアント・リクエストをリスニングするように設定します。ExtendTcpProxyService2は、198.168.1.5およびポート9098にバインドされているTCP/IP ServerSocketでクライアント・リクエストをリスニングするように設定します。

...
<caching-schemes>
<proxy-scheme>
<service-name>ExtendTcpProxyService1</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.5</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
<proxy-scheme>
<service-name>ExtendTcpProxyService2</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.5</address>
<port>9098</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
...

4.2.1.4 クラスタ・サービス・プロキシの無効化

キャッシュ・サービス・プロキシと起動サービス・プロキシは、拡張プロキシ・サービス定義内で無効化できます。これらのプロキシはいずれもデフォルトで有効になっており、クライアントにサービスが不要な場合は明示的に無効化できます。

クラスタ・サービス・プロキシは、それぞれ<cache-service-proxy>内および<invocation-service-proxy>内で<enabled>要素をfalseに設定することによって無効にします。

次の例では、Extendクライアントがクラスタ内でInvocableオブジェクトを実行できないように、起動サービス・プロキシを無効にします。

<proxy-scheme>
...
<proxy-config>
<invocation-service-proxy>
<enabled>false</enabled>
</invocation-service-proxy>
</proxy-config>
...
</proxy-scheme>

同様に、次の例では、Extendクライアントがクラスタ内のキャッシュへアクセスしないようにキャッシュ・サービス・プロキシを無効にします。

<proxy-scheme>
...
<proxy-config>
<cache-service-proxy>
<enabled>false</enabled>
</cache-service-proxy>
</proxy-config>
...
</proxy-scheme>

4.2.1.5 NamedCache読取り専用アクセスの指定

デフォルトでは、Extendクライアントは、プロキシ設定されたNamedCacheインスタンスに対するデータの読取りおよび書込みがいずれも許可されています。<cache-service-proxy>要素内で<read-only>要素を指定すると、Extendクライアントでは、クラスタ上でキャッシュされているコンテンツを変更できなくなります。例:

<proxy-scheme>
...
<proxy-config>
<cache-service-proxy>
<read-only>true</read-only>
</cache-service-proxy>
</proxy-config>
...
</proxy-scheme>

4.2.1.6 NamedCacheロックの指定

注意:

NamedCacheロックAPIは非推奨です。入力プロセッサAPI (JavaおよびC++用のEntryProcessor、および.NET用のIEntryProcessor)で提供されるロック・サポートをかわりに使用してください。

デフォルトでは、ExtendクライアントはNamedCacheロックを取得できません。<cache-service-proxy>要素内で<lock-enabled>要素を指定すると、Extendクライアントでロックを実行できます。例:

<proxy-scheme>
...
<proxy-config>
<cache-service-proxy>
<lock-enabled>true</lock-enabled>
</cache-service-proxy>
</proxy-config>
...
</proxy-scheme>

クライアント側のロックを有効にして、クライアント・アプリケーションでNamedCache.lock()メソッドおよびunlock()メソッドを使用する場合は、パーティション化またはレプリケートされたキャッシュを使用するときに、(スレッドベースではなく)メンバーベースのロック戦略を構成することが重要です。ロック戦略は、クラスタ側のキャッシュを定義するときに、<lease-granularity>要素を使用して構成します。粒度の値がthread(デフォルト設定)の場合、ロックはそのロックを取得したスレッドによって保持され、そのスレッドによってのみ解放されます。粒度の値がmemberの場合、ロックはクラスタ・ノードによって保持され、ロックを取得したクラスタ・ノード上で実行される任意のスレッドによって解放できます。拡張プロキシ・クラスタ・サービスではクライアント・リクエストを同時実行するスレッド・プールが使用されるため、同じExtendクライアントからの後続のリクエストが同じスレッドで実行される保証はありません。

次の例では、パーティション化されたキャッシュに関してリース粒度をmemberに設定する場合を示します。

...
<distributed-scheme>
<scheme-name>dist-default</scheme-name>
<lease-granularity>member</lease-granularity>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
...

4.2.2 Extendクライアントで使用するキャッシュの定義

Extendクライアントは、クラスタ上のキャッシュに対してデータの読取りおよび書込みを行います。クライアント・データは、どのようなキャッシュ・タイプでも格納できます。Extendクライアントの場合、クラスタ上のキャッシュは、クライアント側で使用されているキャッシュと同じ名前である必要があります。「リモート・キャッシュの定義」を参照してください。キャッシュの定義の詳細は、『Oracle Coherenceでのアプリケーションの開発』のキャッシュの使用に関する項を参照してください。

次の例では、dist-extendという名前のパーティション化されたキャッシュを定義します。

...
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend</cache-name>
<scheme-name>dist-default</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<distributed-scheme>
<scheme-name>dist-default</scheme-name>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
</caching-schemes>
...

4.2.3 プロキシ・サーバーでのストレージの無効化

プロキシ・サービスは通常、クラスタ内でデータの保存を担当していないクラスタ・メンバーで実行されます。ストレージに対応するクラスタ・メンバーは、逆にプロキシ・サービスの影響を受ける場合があり、クライアントの負荷を処理するには、追加のリソースが必要です。ストレージ対応メンバーへのプロキシ・サービスの配置は、単純化された開発では通常は可能ですが、テストや実務環境では使用しないでください。

分散キャッシュで、プロキシ・サーバーとして構成されたクラスタ・メンバーにデータを保存しないようにするには、クラスタ・メンバーの起動時にtangosol.coherence.distributed.localstorage Javaプロパティをfalseに設定します。例:

-Dtangosol.coherence.distributed.localstorage=false

ストレージは、分散キャッシュの定義の際に、キャッシュ構成ファイルで無効にすることもできます。これには、<local-storage要素をfalseに設定します。詳細は、『Oracle Coherenceでのアプリケーションの開発』の<distributed-scheme要素のリファレンスを参照してください。

...
<distributed-scheme>
<scheme-name>dist-default</scheme-name>
<local-storage>false</local-storage>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
...

4.3 クライアント側の構成

Extendクライアントは、リモート・キャッシュ・サービスおよびリモート起動サービスを使用して、Coherenceクラスタと相互作用します。これらのサービスは、クラスタ上で実行されている拡張プロキシ・サービスに接続するように構成する必要があります。リモート・キャッシュ・サービスとリモート起動サービスはいずれも、拡張ベースのクライアント・アプリケーションが起動するときにクラスパス上で検出されるキャッシュ構成・デプロイメント・ディスクリプタで構成されます。

この項には、次のトピックが含まれます:

- リモート・キャッシュの定義

- バック・キャッシュとしてのリモート・キャッシュの使用方法

- リモート起動スキームの定義

- 複数のリモート・アドレスの定義

- 接続エラーの検出

- TCMP通信の無効化

4.3.1 リモート・キャッシュの定義

リモート・キャッシュとは、キャッシュ操作をクラスタ上のキャッシュにルーティングする、専用のキャッシュ・サービスです。リモート・キャッシュとクラスタ上のキャッシュは、同じ名前である必要があります。Extendクライアントでは、NamedCacheインタフェースを通常どおりに使用して、キャッシュのインスタンスを取得します。実行時、キャッシュ操作は、ローカルでは実行されず、TCP/IPを使用してクラスタ上の拡張プロキシ・サービスに送信されます。キャッシュ操作をクラスタ上のキャッシュに委任する処理は、Extendクライアントに対して透過的に行われます。

リモート・キャッシュは、<caching-schemesノード内で、<remote-cache-scheme要素を使用して定義されます。クライアントの接続先のクラスタ上にある拡張プロキシ・サービスのアドレス(IPまたはDNS名と、ポート)を定義するには、<tcp-initiator要素を使用します。<remote-cache-schemeサブ要素の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

例4-2では、dist-extendという名前のリモート・キャッシュを定義し、<socket-address>要素を使用して、拡張プロキシ・サービスがリスニングするアドレス(198.168.1.5およびポート9099)を明示的に構成しています。アドレスは、オペレーション構成オーバーライド・ファイル内で定義でき、<address-provider>要素を使用して参照できます。後者の方法は、アドレス構成をリモート・キャッシュ定義から分離し、リモート・キャッシュ定義を変更することなくランタイムでのアドレスの変更を可能にします。アドレス定義の参照の詳細は、「TCPアドレス用のアドレス・プロバイダ参照の使用方法」を参照してください。

注意:

このリモート・キャッシュを使用するには、同じくdist-extendという名前の、クラスタ上で定義されたキャッシュが存在する必要があります。クラスタ上でのキャッシュ定義の詳細は、「Extendクライアントで使用するキャッシュの定義」を参照してください。

例4-2 リモート・キャッシュの定義

...
<caching-scheme-mapping>
<cache-mapping>
che-name>dist-extend</cache-name>
<scheme-name>extend-dist</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>198.168.1.5</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
...

4.3.2 バック・キャッシュとしてのリモート・キャッシュの使用方法

Extendクライアントでは通常、リモート・キャッシュをニア・キャッシュの一部として使用します。この場合、ローカル・キャッシュをフロント・キャッシュとして使用し、リモート・キャッシュをバック・キャッシュとして使用します。詳細は、「C++クライアント用ニア・キャッシュの定義」および「.NETクライアント用ニア・キャッシュの定義」をそれぞれ参照してください。

次の例では、ローカル・キャッシュとリモート・キャッシュを同時に使用するニア・キャッシュを作成します。

...
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend-near</cache-name>
<scheme-name>extend-near</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<near-scheme>
<scheme-name>extend-near</scheme-name>
<front-scheme>
<local-scheme>
<high-units>1000</high-units>
</local-scheme>
</front-scheme>
<back-scheme>
<remote-cache-scheme>
<scheme-ref>extend-dist</scheme-ref>
</remote-cache-scheme>
</back-scheme>
<invalidation-strategy>all</invalidation-strategy>
</near-scheme>

<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
...

4.3.3 リモート起動スキームの定義

リモート起動スキームでは、クライアントがリモートのCoherenceクラスタでタスクを実行する際に使用する起動サービスを定義します。Extendクライアントでは、InvocationServiceインタフェースを通常どおりに使用します。実行時に、拡張プロキシ・サービスに対してTCP/IP接続が行われ、InvocationServiceの実装が返されます。これによって、クライアントの接続先のリモート・クラスタJVM内で同期Invocableタスクが実行されます。

リモート起動スキームは、<caching-schemesノード内で、<remote-invocation-scheme要素を使用して定義されます。クライアントの接続先のクラスタ上にある拡張プロキシ・サービスのアドレス(IPまたはDNS名と、ポート)を定義するには、<tcp-initiator要素を使用します。<remote-invocation-schemeサブ要素の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

例4-3では、ExtendTcpInvocationServiceという名前のリモート起動スキームを定義し、<socket-address>要素を使用して、拡張プロキシ・サービスがリスニングするアドレス(198.168.1.5およびポート9099)を明示的に構成しています。アドレスは、オペレーション構成オーバーライド・ファイル内で定義でき、<address-provider>要素を使用して参照できます。後者の方法は、アドレス構成をリモート起動キャッシュ定義から分離し、リモート起動キャッシュ定義を変更することなく実行時でのアドレスの変更を可能にします。アドレス定義の参照の詳細は、「TCPアドレス用のアドレス・プロバイダ参照の使用方法」を参照してください。

例4-3 リモート起動スキームの定義

...
<caching-schemes>
<remote-invocation-scheme>
<scheme-name>extend-invocation</scheme-name>
<service-name>ExtendTcpInvocationService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>198.168.1.5</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-invocation-scheme>
</caching-schemes>
...

4.3.4 複数のリモート・アドレスの定義

リモート・キャッシュ・スキームとリモート起動スキームには、クライアントがいつでも必ずクラスタに接続できるように、拡張プロキシ・サービスのアドレスを複数含めることができます。接続の調整に使用されているアルゴリズムは、構成されているロード・バランシングの戦略によって変わります。ロード・バランシングの詳細は、「ロード・バランシング接続」を参照してください。

複数のアドレスを構成するには、必要に応じて、<remote-cache-scheme>ノードおよび<remote-invocation-scheme>ノードの<tcp-initiator>要素内に、子要素<socket-address>を追加します。次の例では、リモート・キャッシュ・スキームの拡張プロキシ・アドレスを2つ定義します。複数のプロキシ・アドレスを設定する手順の詳細は、「複数のプロキシ・サービス・インスタンスの定義」を参照してください。

...
<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>192.168.1.5</address>
<port>9099</port>
</socket-address>
<socket-address>
<address>192.168.1.6</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
...

4.3.5 接続エラーの検出

Coherence*Extendサービスで(ネットワーク、ソフトウェアまたはハードウェア障害などに起因する)クライアントとクラスタ間の接続の切断が検出されると、Coherence*Extendクライアント・サービスの実装(CacheServiceまたはInvocationService)により、登録されているすべてのMemberListenersにMemberEvent.MEMBER_LEFTイベントがディスパッチされ、サービスが停止します。アプリケーションがCacheFactory.shutdown()をコールする場合は、サービスの実装により、MemberEvent.MEMBER_LEAVINGイベントと、続いてMemberEvent.MEMBER_LEFTイベントがディスパッチされます。いずれの場合も、その後クライアント・アプリケーションでサービスを使用しようとすると、サービスが自動的に再起動され、クラスタとの再接続が試行されます。このサービスが接続に成功するとMemberEvent.MEMBER_JOINEDイベントがディスパッチされ、接続に失敗するとクライアント・アプリケーションに修復できないエラーの例外がスローされます。

Coherence*Extendサービスには、接続の切断を検出するためのメカニズムがいくつか用意されています。その中には、(Extend-TCPのTCP/IPのように)基底プロトコルに固有のものもあれば、サービス自体に実装されるものもあります。後者のメカニズムは、<outgoing-message-handler要素を使用して構成されます。この要素の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。特に、<request-timeout値は、リクエストを中止するまでの応答を待機する時間を制御します。<heartbeat-intervalおよび<heartbeat-timeout値は、接続を閉じるまでのpingリクエストへの応答を待機する時間を制御します。

次の例は、例4-2から抜粋したもので、リクエスト・タイムアウトを5秒に設定する場合を示しています。

...
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>198.168.1.5</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
...

次の例では、ハートビート間隔を500ミリ秒に、ハートビート・タイムアウトを10秒に設定します。

...
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>198.168.1.5</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<heartbeat-interval>500ms</heartbeat-interval>
<heartbeat-timeout>10s</heartbeat-timeout>
</outgoing-message-handler>
</initiator-config>
...

4.3.6 TCMP通信の無効化

ネットワーク内に配置されたJavaベースのExtendクライアントでは、拡張プロキシを使用して排他的にクラスタ・サービスに接続するために、TCMP通信を無効にする必要があります。TCMPが無効でない場合、JavaベースのExtendクライアントが互いにクラスタ化される可能性があり、既存のクラスタに追加される可能性もあります。TCMPはクラスタ側のtangosol-coherence-override.xmlファイルで無効にします。

TCMP通信を無効にするには、<packet-publisher>内の<enabled>要素をfalseに設定します。例:

...
<cluster-config>
<packet-publisher>
<enabled system-property="tangosol.coherence.tcmp.enabled">false
</enabled>
</packet-publisher>
</cluster-config>
...

オペレーション・オーバーライド・ファイルを使用するかわりに、tangosol.coherence.tcmp.enabledシステム・プロパティを使用して、TCMPを有効にするかどうかを指定します。例:

-Dtangosol.coherence.tcmp.enabled=false

4.4 TCPアドレス用のアドレス・プロバイダ参照の使用方法

プロキシ・サービス、リモート・キャッシュおよびリモート起動定義では、キャッシュ構成ファイルで明示的にアドレスを定義するかわりに、<address-provider>を使用して、オペレーション構成オーバーライド・ファイルに定義されたTCPソケット・アドレスを参照できます。ソケット・アドレス定義を参照することで、キャッシュ構成ファイルを更新することなく、ネットワーク・アドレスを変更できます。

TCPアドレス用のアドレス・プロバイダ参照を使用する手順は次のとおりです。

1. ソケットのアドレスとポートを含んでいる<address-provider要素内で、tangosol-coherence-override.xmlファイル(クライアント上とクラスタ側の両方)を編集し、<socket-address定義を追加します。<address-provider要素のid属性を使用して、ソケット・アドレスの固有IDを定義します。オペレーション構成オーバーライド・ファイルの<address-provider要素の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。次の例は、proxy1のIDでアドレスを定義しています。

...
<cluster-config>
<address-providers>
<address-provider id="proxy1">
<socket-address>
<address>198.168.1.5</address>
<port>9099</port>
</socket-address>
</address-provider>
</address-providers>
</cluster-config>
...

2. クラスタ側のcoherence-cache-config.xmlを編集して、プロキシ・サービス定義を作成または更新し、<tcp-acceptor>要素内の<address-provider>要素の値としてソケット・アドレス定義のIDを指定することで、ソケット・アドレス定義を参照します。次の例は、手順1で定義したアドレスを参照するプロキシ・サービスを定義しています。

...
<caching-schemes>
<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<address-provider>proxy1</address-provider>
</tcp-acceptor>
</acceptor-config>
<proxy-config>
<cache-service-proxy>
<enabled>true</enabled>
</cache-service-proxy>
<invocation-service-proxy>
<enabled>true</enabled>
</invocation-service-proxy>
</proxy-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
...

3. クライアント側のcoherence-cache-config.xmlを編集して、リモート・キャッシュまたはリモート起動定義を作成または更新し、<tcp-initiator>要素内の<address-provider>要素の値としてソケット・アドレス定義のIDを指定することで、ソケット・アドレス定義を参照します。次の例は、手順1で定義したアドレスを参照するリモート・キャッシュを定義しています。

<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<address-provider>proxy1</address-provider>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>

4.5 ネーム・サービス・アクセプタを使用したプロキシへの接続

ネーム・サービスは特殊化されたTCPアクセプタで、Extendクライアントでは、プロキシ・サービス・アドレスではなく、プロキシ・サービス名を指定することでプロキシに接続できます。クライアントは、要求されたプロキシの実際のアドレスを提供するネーム・サービス・アクセプタへ接続します。ネーム・サービス・アクセプタを使用することで、キャッシュ構成ファイルを更新することなく、実際のプロキシ・アドレスを変更できます。

ネーム・サービス・アクセプタは、プロキシ・サービスがクラスタ・メンバー上に構成されている場合、TCMPソケットと同じポート(デフォルトで8088)で自動的に起動します。さらに、クラスタでTCMPソケットが使用するリスニング・ポートを複数のプロキシ・サービスが使用するように構成することもできます。TCMP、ネーム・サービスおよびプロキシ・サービスと同じポートを使用することは、Coherenceで使用されるポートの数を最小限にして、ファイアウォールの構成を単純化できます。

注意:

ネーム・サービス・アクセプタを使用するように構成されたクライアントは、ネーム・サービス・アクセプタをサポートするクラスタにしか接続できません。

ネーム・サービス・アクセプタを使用してプロキシへ接続する手順は次のとおりです。

1. クラスタ側のcoherence-cache-config.xmlを編集して、プロキシ・サービス定義を作成または更新します。<tcp-acceptor>要素内で明示的にソケット・アドレスを定義しないでください。次の例は、TCMPが使用するポートにバインドするTcpExtendという名前のプロキシ・サービスを定義しています。

...
<caching-schemes>
<proxy-scheme>
<service-name>TcpExtend/service-name>
<acceptor-config/>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
...

2. クライアント側のcoherence-cache-config.xmlを編集して、リモート・キャッシュまたはリモート起動定義を作成または更新し、<tcp-initiator>要素内に<name-service-addresses>要素を追加します。この要素は、クラスタ上のネーム・サービス・アクセプタのソケット・アドレスを含みます。次の例は、手順1で構成したTcpExtendプロキシ・サービスへの接続を確立するネーム・サービスへ接続するためのリモート・キャッシュ定義を指定しています。この例では、ポート8088をTCMPクラスタ・ポート、ネーム・サービス・ポートおよびプロキシ・サービス・ポートとして使用しています。

注意:

- リモート・キャッシュまたはリモート起動スキームの<service-name>の値がクラスタ上のプロキシ・スキームの<service-name>の値と異なる場合、プロキシ・スキームで構成された<service-name>要素の値を含むリモート・キャッシュおよびリモート起動スキームに<proxy-service-name>も指定する必要があります。

- <name-services-addresses>要素では、オペレーション構成オーバーライド・ファイルで構成されたソケット・アドレスの参照に<address-provider>を使用できます。詳細は、「TCPアドレス用のアドレス・プロバイダ参照の使用方法」を参照してください。

<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>TcpExtend</service-name>
<initiator-config>
<tcp-initiator>
<name-service-addresses>
<socket-address>
<address>198.168.1.5</address>
<port>8088</port>
</socket-address>
</name-service-addresses>
<connect-timeout>5s</connect-timeout>
</tcp-initiator>
</initiator-config>
</remote-cache-scheme>

4.6 TCPアドレス用のカスタム・アドレス・プロバイダの使用方法

カスタム・アドレス・プロバイダは、サーバー・ソケットにバインドするとき、TCPアドレスおよびポートの設定を動的に割り当てます。アドレス・プロバイダは、com.tangosol.net.AddressProviderインタフェースの実装である必要があります。アドレスの動的割当ては通常、カスタムのロード・バランシング・アルゴリズムを実装するために使用します。

アドレス・プロバイダは、拡張プロキシ・スキームの場合は<tcp-acceptor>要素内、リモート・キャッシュ・スキームおよびリモート起動スキームの場合は<tcp-initiator>要素内で使用できる、<address-provider>要素を使用して定義します。

次の例は、拡張プロキシ・スキームを構成するときに、MyAddressProviderという名前のAddressProviderの実装をTCPアクセプタ用に構成する方法を示しています。

...
<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<address-provider>
<class-name>com.MyAddressProvider</class-name>
</address-provider>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
...

次の例は、リモート・キャッシュ・スキームを構成するときに、MyClientAddressProviderという名前のAddressProviderの実装をTCPイニシエータ用に構成する方法を示しています。

...
<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<address-provider>
<class-name>com.MyClientAddressProvider</class-name>
</address-provider>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
...

さらに、<address-provider>要素では、AddressProviderインスタンスを作成するためのファクトリ・クラスを使用するために<class-factory-name>要素、およびオブジェクトのインスタンス化を実行するファクトリ・クラス上で静的なファクトリ・メソッドを指定する<method-name>要素の使用もサポートされています。

4.7 ロード・バランシング接続

Extendクライアント接続は、プロキシ・サービスのメンバー間で自動的にロード・バランシングされます。デフォルトでは、クライアント接続を利用率の低いプロキシ・サービス・メンバーに分散するプロキシベースの戦略が使用されます。必要に応じてカスタムのプロキシベースの戦略の作成や、デフォルトの戦略の変更が可能です。また別の戦略として、クライアント側アドレス・プロバイダを作成するか、プロキシ・サービス・メンバーへのクライアント接続のランダム化によってクライアントベースのロード・バランシングの戦略を実装できます。ランダム化の方法は、プロキシベースのロード・バランシングと比べて調整の効果が大きく劣ります。

Coherence*Extendは、ハードウェアベースのロード・バランシングを提供するF5 BIG-IP Local Traffic Manager (LTM)と併用できます。詳細は、付録B「F5 BIG-IP LTMとの統合」を参照してください。

この項には、次のトピックが含まれます:

- プロキシベースのロード・バランシングの使用方法

- クライアントベースのロード・バランシングの使用方法

4.7.1 プロキシベースのロード・バランシングの使用方法

プロキシベースのロード・バランシングは、クライアント接続を複数の同じプロキシ・サービスのメンバーで調整するデフォルトの戦略です。この戦略は、プロキシの既存接続数、プロキシのデーモン・プールの利用率、プロキシのメッセージ・バックログの順番に重み付けされています。

プロキシベースのロード・バランシングの戦略は、<proxy-scheme>定義内で <load-balancer>要素を使用し、proxyに設定することで構成します。わかりやすいように、次の例ではこの戦略を明示的に指定しています。ただし、戦略が指定されていない場合もこの戦略が使用されるため、プロキシ・スキーム定義では必須ではありません。

...
<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.5</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<load-balancer>proxy</load-balancer>
<autostart>true</autostart>
</proxy-scheme>
...

注意:

プロキシベースのロード・バランシングを使用するとき、クライアントでは、キャッシュ構成に全プロキシ・サービス・メンバーのリストを必要としません。ただし、冗長化の目的で、常に最低2つのプロキシ・サービス・メンバーを構成する必要があります。クライアントによって使用する複数のリモート・アドレスの定義方法の詳細は、「複数のリモート・アドレスの定義」を参照してください。

4.7.1.1 ロキシベースのロード・バランシングのデフォルト・アルゴリズムの理解

プロキシベースのロード・バランシング・アルゴリズムは、プロキシ・サービスのメンバーに均等にクライアント接続を分配します。このアルゴリズムは、利用率の低いプロキシ・サービス・メンバーにクライアントをリダイレクトします。プロキシの使用率の決定には次の係数が使用されています。

- 接続の使用率 - この使用率は、現在の接続数と保留接続の数を合計して計算されます。プロキシに設定済の接続制限があり、現在の接続数と保留接続の数の合計が接続制限と同じ場合、使用率は無限大と見なされます。

- デーモン・プールの使用率 - この使用率は、アクティブなデーモン・スレッドの現在の数と同じになります。すべてのデーモン・スレッドが現在アクティブな場合、使用率は無限大と見なされます。

- メッセージ・バックログの使用率 - この使用率は、現在の受信バックログと現在の送信メッセージ・バックログを合計して計算されます。

各プロキシ・サービスでは、使用率順に並べられた全プロキシ・サービスのメンバーのリストが維持されます。この順序付けは、接続の使用率、デーモン・プールの使用率、メッセージ・バックログの順番で重み付けされます。このリストでは、プロキシ・サービス・メンバーの使用率が変わるたびに、並替えが行われます。プロキシ・サービス・メンバーは互いに、接続数が変わるごとまたは10秒ごと(いずれかが先に発生したとき)に現在の使用率を送信します。

プロキシで新しい接続が試行されたとき、リストは次のように更新されます。

- 現在のプロキシの接続使用率が低い場合は接続が許可され、そうでない場合は、低い接続使用率のプロキシ・サービス・メンバーの順番に並べられたリストがある接続の試行に返信することでその新規接続がリダイレクトされます。次に、クライアントは戻されたリストの順にプロキシ・サービス・メンバーへ接続を試行します。

- プロキシの接続使用率が同じ場合は、プロキシのデーモン・プールの使用率で優先順位が決定されます。現在のプロキシのデーモン・プール使用率が低い場合は接続が許可され、そうでない場合は、低いデーモン・プール使用率のプロキシ・サービス・メンバーが順番に並べられたリストがある接続の試行に返信することでその新規接続がリダイレクトされます。次に、クライアントは戻されたリストの順にプロキシ・サービス・メンバーへ接続を試行します。

- プロキシのデーモン・プール使用率が同じ場合は、プロキシのメッセージ・バックログで優先順位が決定されます。現在のプロキシのメッセージ・バックログ使用率が低い場合は接続が許可され、そうでない場合は、低いメッセージ・バックログ使用率のプロキシ・サービス・メンバーが順番に並べられたリストがある接続の試行に返信することでその新規接続がリダイレクトされます。次に、クライアントは戻されたリストの順にプロキシ・サービス・メンバーへ接続を試行します。

- すべてのプロキシが同じ使用率の場合、クライアントは現在のプロキシに接続します。

4.7.1.2 カスタムのプロキシベース・ロード・バランシングの戦略の実装

com.tangosol.coherence.net.proxyパッケージには、プロキシ・サービスのメンバー間でクライアントの負荷を調節するために使用するAPIが含まれています。プロキシベースのロード・バランシングAPIの使用方法の詳細は、Oracle Coherence Java APIリファレンスを参照してください

カスタムの戦略では、ProxyServiceLoadBalancerインタフェースを実装する必要があります。必要に応じて新規の戦略を作成するか、デフォルトの戦略(DefaultProxyServiceLoadBalancer)を拡張または変更できます。たとえば、プロキシ・サービスのリストで優先する使用率係数を変更するには、目的の順番を強制するコンストラクタでDefaultProxyServerLoadBalancerを拡張し、カスタムComparatorオブジェクトを渡します。最後に、クライアントのMemberオブジェクト(各クライアントを一意に定義)を戦略に渡します。Memberオブジェクトは、クライアントに重み付けをした戦略を実装する手段となります。クライアントのメンバー識別情報を構成する方法の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

カスタムのロード・バランシング戦略を有効にするには、<load-balancer>要素内に<instance>のサブ要素を追加し、ProxyServiceLoadBalancerインタフェースを実装する完全修飾クラス名を指定します。次の例は、MyProxyServiceLoadBalancerクラスに実装されているカスタムのプロキシベース・ロード・バランシングの戦略を有効化します。

...
<load-balancer>
<instance>
<class-name>package.MyProxyServiceLoadBalancer</class-name>
</instance>
</load-balancer>
...

さらに、<instance要素では、ProxyServiceLoadBalancerインスタンスを作成するためのファクトリ・クラスを使用するために<class-factory-name要素、およびオブジェクトのインスタンス化を実行するファクトリ・クラス上で静的なファクトリ・メソッドを指定する<method-name要素の使用もサポートされています。<instance要素の詳細な手順は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

4.7.2 クライアントベースのロード・バランシングの使用方法

クライアントベースのロード・バランシングの戦略は、プロキシ・サービス・メンバー間でのクライアントの分配を処理するクライアント・アドレス・プロバイダ実装に依存しています。クライアント・アドレス・プロバイダ実装が提供されていない場合、Extendクライアントは、接続が成功するまで構成済の各プロキシ・サービスへランダムな順序で接続を試行します。アドレス・プロバイダ実装の提供方法の詳細は、「TCPアドレス用のアドレス・プロバイダの使用方法」を参照してください。

クライアントベースのロード・バランシングの戦略は、<proxy-scheme>定義内で <load-balancer>要素を使用し、clientに設定することで構成します。例:

...
<proxy-scheme>
<service-name>ExtendTcpProxyService1</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.5</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<load-balancer>client</load-balancer>
<autostart>true</autostart>
</proxy-scheme>
...

前述の構成は、クライアントの戦略を1つのプロキシ・サービスに設定するため、クライアントの戦略を使用するすべてのプロキシ・サービスで繰り返し設定する必要があります。戦略が指定されていない場合に、クライアントの戦略をすべてのプロキシ・サービスのデフォルトの戦略として設定するには、オペレーション・オーバーライド・ファイルでプロキシ・サービス・タイプにload-balancerパラメータをオーバーライドします。例:

...
<cluster-config>
<services>
<service id="7">
<init-params>
<init-param id="12">
<param-name>load-balancer</param-name>
<param-value>client</param-value>
</init-param>
</init-params>
</service>
</services>
</cluster-config>
...

4.8 Extendクライアントでのネットワーク・フィルタの使用方法

Coherenceクラスタ・サービス同様、Coherence*Extendサービスはプラガブルなネットワーク・フィルタをサポートします。フィルタは、送信前のネットワーク・トラフィックのコンテンツを変更します。フィルタの構成方法の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

Coherence*Extendでネットワーク・フィルタを使用するには、<use-filters>要素を、クライアント側のキャッシュ構成ディスクリプタの<initiator-config>要素とクラスタ側のキャッシュ構成ディスクリプタの<acceptor-config>要素に追加する必要があります。

注意:

<use-filters>要素の内容は、クライアント側およびクラスタ側のキャッシュ構成ディスクリプタで同じにする必要があります。

たとえば、Extendクライアントとクラスタ・サービスとの間で事前定義のgzipフィルタを使用して交換されるネットワーク・トラフィックを圧縮するには、次に示すように、クライアント側の<remote-cache-scheme>要素および<remote-invocation-scheme>要素を構成します。

<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
<use-filters>
<filter-name>gzip</filter-name>
</use-filters>
</initiator-config>
</remote-cache-scheme>

<remote-invocation-scheme>
<scheme-name>extend-invocation</scheme-name>
<service-name>ExtendTcpInvocationService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
<use-filters>
<filter-name>gzip</filter-name>
</use-filters>
</initiator-config>
</remote-invocation-scheme>

クラスタ側では、クライアント側の構成と同じ名前のフィルタを指定する<use-filters>要素を<proxy-scheme>要素内に追加します。

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
<use-filters>
<filter-name>gzip</filter-name>
</use-filters>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>

5 Coherence*Extendのベスト・プラクティス

この章では、Coherence*Extendの構成および実行のベスト・プラクティスとガイドラインについて説明します。

この章には次の項が含まれます:

- ローカル記憶域を無効にしてプロキシ・サーバーを実行する

- プロキシ・サーバーでニア・キャッシュを実行しない

- ヒープNIO領域を最大ヒープ・サイズと同じ値に構成する

- Proxyサービスのスレッド・プールの構成

- InvocationServiceをコールするときの注意事項

- キャッシュにコレクション・クラスを書き込むときの注意事項

- キャッシュ・サーバーに対してPOFシリアライザを構成する

- スレッドのロックでなくノードのロックを使用する

5.1 ローカル記憶域を無効にしてプロキシ・サーバーを実行する

プロキシ・サーバーも含めて、パーティション・キャッシュ内の各サーバーには、データの一部を格納できます。ただし、プロキシ・サーバーには予測できない潜在的クライアントの処理負荷を管理するための負荷が加わり、その負荷はCPUやメモリーの使用率を大きく消費する可能性があります。プロキシ・サーバーではリソースを維持するためにローカル記憶域を無効にする必要があります。

記憶域を無効にするには、次のような方法が使用されます。

Javaプロパティtangosol.coherence.distributed.localstorageを使用して、プロキシ・サーバーのローカル記憶域を有効または無効に設定できます。例:

-Dtangosol.coherence.distributed.localstorage=false

<local-storage要素を使用してキャッシュ構成ファイルの記憶域を無効にすることもできます。詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

すべてのプロキシ・サービス・インスタンスの記憶域を無効にするには、tangosol-coherence-override.xmlファイルにある<local-storage>設定を変更してください。例5-1は、<local-storage>をfalseに設定する方法を示しています。

例5-1 記憶域の無効化

<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/
coherence-operational-config coherence-operational-config.xsd">
<cluster-config>
<services>
<service id="3">
<init-params>
<init-param id="4">
<param-name>local-storage</param-name>
<param-value system-property="tangosol.coherence.distributed.
localstorage">false</param-value>
</init-param>
</init-params>
</service>
</services>
</cluster-config>
</coherence>

5.2 プロキシ・サーバーでニア・キャッシュを実行しない

定義上、ニア・キャッシュでは、最近使用されたデータと頻繁に使用されるデータの両方のローカル・キャッシュへのアクセスが提供されます。プロキシ・サーバーでニア・キャッシュが構成されている場合、リモート・クライアントがアクセスするデータがローカル・キャッシュに保存されます。これらのクライアントが同じデータ・サブセットに継続的にアクセスする可能性は低いため、ニア・キャッシュでのヒット率は高くありません。プロキシ・サーバーでニア・キャッシュを実行した場合、プロキシ・ノードのヒープ使用率とネットワーク・トラフィックが増加するばかりで、利点はまったくないかほとんどありません。このような理由から、プロキシ・サーバーではニア・キャッシュを使用しないことをお薦めします。プロキシ・サーバーでニア・キャッシュが実行されないようにするには、プロキシに使用するキャッシュ構成からすべてのニア・スキームを削除します。

5.3 ヒープNIO領域を最大ヒープ・サイズと同じ値に構成する

NIOメモリーは、プロキシへのTCP接続とPOFのシリアライズおよびデシリアライズに使用されます。以前のJavaインストールでは、ヒープ・メモリーが少なく構成されていたため不足しがちでした。新しいJava JDKでは、ヒープNIO領域が最大ヒープ領域と同じサイズに構成されます。Sun JVMでは、これを手動で設定することもできます。

-XX:MaxDirectMemorySize=MAX_HEAP_SIZE

5.4 Proxyサービスのスレッド・プールの構成

プロキシ・サービスは、デーモン(ワーカー)スレッドの動的なスレッド・プールを使用します。スレッド・プールは、クライアント・リクエストの数、リクエストのバックログの合計数およびアイドル・スレッドの合計数を基に自動的にスレッドの追加や削除を実行します。スレッド・プールは、Extendクライアントのリクエストを満たす十分なスレッドを確保し、リソースがアイドル・スレッドによって無駄に使用されないようにするために役立ちます。スレッド・プールのデフォルト設定を変更することで、クライアントのパフォーマンスを最適化できます。

この項の内容は次のとおりです。

- Proxyサービスのスレッドの理解

- Proxyサービスのスレッド・プールのしきい値の設定

- 正確なスレッド数の設定

5.4.1 Proxyサービスのスレッドの理解

それぞれのアプリケーションのスレッドの要件は、クライアント数と実行中の処理の量に応じて異なります。パフォーマンスを綿密に監視して、クライアント・リクエストに十分対応するスレッドを確保し、さらにクライアントがスレッドで飽和しないようにします。さらに、スレッド・プールで最大数のスレッドが使用されているときにはログ・メッセージが発行されます。このメッセージによって、追加のスレッドが必要であることを認識できます。

クライアント・アプリケーションは、アクティブ・アプリケーションとパッシブ・アプリケーションの2つの一般カテゴリに分類できます。アクティブなアプリケーションでは、Extendクライアントが多数のリクエスト(PUT、GETなど)を送信し、それらがProxyサービスによって処理されます。Proxyサービスが、これらの多数のタスクを十分に処理するためには大量のスレッドを必要とします。

パッシブ・アプリケーションでは、クライアントは、特定の基準に基づいてイベント(マップ・リスナーなど)を待ちます。イベントは、分散キャッシュ・サービスによって処理されます。このサービスはワーカー・スレッドを使用してイベントをクライアントにプッシュします。このタスクに対応するため、分散キャッシュ・サービスのスレッド・プール構成には、十分なワーカー・スレッドを確保するようにします。分散サービスのスレッド件数の構成方法は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

注意:

Extendクライアントのニア・キャッシュでは、ALL、PRESENTおよびAUTOの無効化戦略を実行する場合にマップ・リスナーが使用されます。書込み量が多く、ニア・キャッシュを使用するアプリケーションでは、多数のマップ・イベントが生成されます。

5.4.2 Proxyサービスのスレッド・プールのしきい値の設定

デフォルトのスレッド・プールの動作では、コア数の2倍と等しいスレッドの量から始まり、コア数の8倍の最大スレッド量まで増やされます。構成済の最大値に達するとログ・メッセージが発行されます。

スレッド・プールは、スレッドの減少量を上回るスレッドを積極的に作成します。クライアントのリクエストやサービスのブロックが増加すると、追加のスレッドが0.5秒ごとに作成されます。アイドル状態になったスレッドが多すぎる場合は、60秒ごとにスレッドがスレッド・プールから削除されます。

プロキシ・サービスにスレッド・プールのしきい値を設定するには、<proxy-scheme要素内に<thread-count-maxおよび<thread-count-min要素を追加します。これらの要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。次の例は、新しいデフォルト・プール設定を変更します。

注意:

- 動的なスレッド・プールのサイズ設定を有効にするには、プロキシ・サービスに<thread-count>要素を設定しないでください。スレッド件数の値を設定すると、動的なスレッド・プールのサイズ設定が無効になります。

- 最大スレッド件数をゼロに設定すると、プロキシ・サービスのスレッドがすべてのリクエストを処理するように強制され、ワーカー・スレッドは使用されません。プロキシ・サービス・スレッドを使用してクライアントのリクエストを処理することはお薦めできません。

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<thread-count-max>75</thread-count-max>
<thread-count-min>10</thread-count-min>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>

tangosol.coherence.proxy.threads.maxおよびtangosol.coherence.proxy.threads.minシステム・プロパティは、キャッシュ構成ファイルを使用するかわりに、動的なスレッド・プールのしきい値を指定します。例:

-Dtangosol.coherence.proxy.threads.max=75
tangosol.coherence.proxy.threads.min=10

5.4.3 正確なスレッド数の設定

ほとんどの用途で、プロキシ・サービスがリクエストを処理するための十分なスレッドを確保にするには、動的なスレッド・プール設定が最も適しています。クライアントの用途が明確な適切に制御されたアプリケーションでは、<thread-count>要素を使用してスレッド数を明示的に指定することで動的なスレッド・プールを無効にすることもできます。次の例では、プロキシ・サービス用に10スレッドを設定します。追加のスレッドは自動的には作成されません。

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<thread-count>10</thread-count>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>

5.5 InvocationServiceをコールするときの注意事項

InvocationServiceを使用すると、サービスのメンバーがクラスタ内の任意のノードで任意のコードを起動できます。ただし、Coherence*Extendでは、InvocationServiceコールは、クライアントがデフォルトで接続されるプロキシによって処理されます。プロキシ経由でコールを送信する場合、コードの実行先とする特定のノードを選択できません。

5.6 キャッシュにコレクション・クラスを書き込むときの注意事項

Coherence*Extendクライアントがコレクション・オブジェクト(ArrayList、HashSet、HashMapなど)をキャッシュに直接書き込む場合、オブジェクトは不変の配列としてデシリアライズされます。次にこのオブジェクトを抽出して元の型にキャストすると、ClassCastExceptionsが返されます。代替策としては、Javaインタフェース・オブジェクト(List、Set、Mapなど)を使用するか、またはコレクション・オブジェクトを別のオブジェクトにカプセル化します。次の例では、この両方のテクニックを示しています。

例5-2 ArrayListオブジェクトのキャスト

public class ExtendExample
{
@SuppressWarnings({ "unchecked" })
public static void main(String asArgs[])
{
System.setProperty("tangosol.coherence.cacheconfig", "client-config.xml");
NamedCache cache = CacheFactory.getCache("test");

// Create a sample collection
List list  = new ArrayList();
for (int i = 0; i < 5; i++)
{
list.add(String.valueOf(i));
}
cache.put("list", list);

List listFromCache = (List) cache.get("list");

System.out.println("Type of list put in cache: " + list.getClass());
System.out.println("Type of list in cache: " + listFromCache.getClass());

Map map = new TreeMap();
for (Iterator i = list.iterator(); i.hasNext();)
{
Object o = i.next();
map.put(o, o);
}
cache.put("map", map);

Map mapFromCache = (Map) cache.get("map");

System.out.println("Type of map put in cache: " + map.getClass());
System.out.println("Type of map in cache: " + mapFromCache.getClass());
}
}

5.7 キャッシュ・サーバーに対してPOFシリアライザを構成する

プロキシ・サーバーは、POFデータをJavaオブジェクトにデシリアライズする処理を担当します。C++または.NETのアプリケーションを実行してデータをキャッシュに格納する場合、Javaオブジェクトへの変換が不要な手順に思えることがあります。現在のリリースのCoherenceでは、キャッシュ・サーバーに対してPOFシリアライザを構成するオプションがあります。

これによって、アプリケーションに次の影響が及ぶ可能性があります。

- putまたはgetの操作のみを実行する.NETまたはC++のクライアントでは、Javaバージョンのオブジェクトは不要です。(入力プロセッサやキャッシュ・ストアなどのために)サーバー側でデシリアライズが実行される場合、Javaバージョンは必要です。

- POFシリアライザを使用することで、プロキシでシリアライズ/デシリアライズを実行する必要がなくなるため、メモリーとCPUの要件が小さくなります。

例5-3は、オペレーション・デプロイメント・ディスクリプタで定義されるデフォルトのPOFシリアライザを構成する、キャッシュ構成ファイルの抜粋を示しています。

例5-3 分散キャッシュに対するPOFシリアライザの構成

...
<distributed-scheme>
<scheme-name>dist-default</scheme-name>
<serializer>pof</serializer>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
...

5.8 スレッドのロックでなくノードのロックを使用する

注意:

NamedCacheロックAPIは非推奨です。入力プロセッサAPI (JavaおよびC++用のEntryProcessor、および.NET用のIEntryProcessor)で提供されるロック・サポートをかわりに使用してください。

Coherence*Extendクライアントは、lock、putおよびunlockのリクエストをクラスタに送信できます。ロックはクライアントにかわってプロキシが保持します。ロックおよびロック解除のリクエストは、スレッド・レベルまたはノード・レベルで発行できます。スレッド・レベルのロックでは、プロキシに属する特定のスレッド・インスタンス(スレッド1など)が、lockリクエストを発行します。他のスレッド(スレッド3など)がunlockリクエストを発行しても、無視されます。unlockリクエストが正常に処理されるのは、最初のlockリクエストを発行したスレッドによって発行された場合のみです。この場合、unlockリクエストは、そのロック解除リクエストを受け取るスレッドと元のロックを発行したスレッドが同じでないかぎり正常に処理されないため、アプリケーション・エラーが発生する可能性があります。

ノード・レベルのロックでは、プロキシに属する特定のスレッド(スレッド1など)がlockリクエストを発行した場合、他のスレッド(スレッド3など)もunlockリクエストを正常に発行できます。

第II部

Java Extendクライアントの作成

Coherence for Javaを使用すると、データ、データ・イベント、データ処理などのCoherenceクラスタ・サービスに、Coherenceクラスタ外部からJavaアプリケーションを使用してアクセスできます。Java Extendクライアントは通常、Coherenceキャッシュへのアクセスを必要とするデスクトップ・アプリケーションやWebアプリケーションで使用されます。

Coherence for Javaライブラリは、Coherenceクラスタ内で稼働する Coherence*Extend のクラスタ・サービス・インスタンスに、高性能なTCP/IPベースの通信レイヤーを使用して接続します。このライブラリからCoherence*Extendクラスタ・サービスにすべてのクライアント・リクエストが送信され、このサービスは実際のCoherenceクラスタ・サービス(パーティション・キャッシュ・サービス、レプリケーション・キャッシュ・サービスなど)に委任することで、クライアント・リクエストに応答します。

クラスタのメンバーであるキャッシュ・クライアントと同様に、Java Extendクライアントでは、CacheFactory.getCache() APIコールを使用してNamedCacheインスタンスを取得します。これが取得されると、クライアントはCoherenceクラスタに組み込まれている場合と同じようにNamedCacheにアクセスします。NamedCacheの操作はリモートのクラスタ・ノードに(TCP/IPを介して)送信されますが、この処理はクライアント・アプリケーションに対して完全に透過的に行われます。

C++や.NETのディストリビューションとは異なり、Javaには個別のクライアント・ディストリビューションはありません。Coherence for Javaで提供されるAPIは、Extendクライアントの作成に使用するAPIと同じです。APIは、『Oracle Coherenceでのアプリケーションの開発』で詳しく説明されているため、このガイドでは同様の説明は行いません。Java Extendクライアントを構築する場合は、このガイドの「第I部 スタート・ガイド」(基本的な設定用)と、『Oracle Coherenceでのアプリケーションの開発』の第IV部のプログラミングAPIの使用に関する項を参照してください。

第III部

C++ Extendクライアントの作成

Coherence for C++を使用すると、データ、データ・イベント、データ処理などのCoherenceクラスタ・サービスに、Coherenceクラスタ外部からC++アプリケーションを使用してアクセスできます。Coherence for C++は通常、Coherenceキャッシュへのアクセスを必要とするデスクトップ・アプリケーションやWebアプリケーションで使用されます。

Coherence for C++は、Coherenceクラスタ内で稼働する Coherence*Extend クラスタ・サービス・インスタンスに、高性能なTCP/IPベースの通信レイヤーを使用して接続するネイティブC++ライブラリで構成されます。このライブラリからCoherence*Extendクラスタ・サービスにすべてのクライアント・リクエストが送信され、このサービスは実際のCoherenceクラスタ・サービス(パーティション・キャッシュ・サービス、レプリケーション・キャッシュ・サービスなど)に委任することで、クライアント・リクエストに応答します。

NamedCacheインスタンスは、CacheFactory::getCache(...) APIコールを使用して取得されます。これが取得されると、クライアントはCoherenceクラスタに組み込まれている場合と同じようにNamedCacheにアクセスします。NamedCacheの操作はリモートのクラスタ・ノードに(TCP/IPを介して)送信されますが、この処理はクライアント・アプリケーションに対して完全に透過的に行われます。

注意:

C++クライアントは、Javaクライアントのインタフェースと概念に従います。Coherence for Javaに精通していると、Coherence C++への移行が容易であることがわかります。

「Coherence for C++」は次の章で構成されています。

- 第6章「C++アプリケーション・ビルドの設定」

- 第7章「C++クライアントの構成と使用」

- 第8章「CoherenceのC++オブジェクト・モデルの使用」

- 第9章「Coherence for C++クライアントAPIの使用」

- 第10章「統合オブジェクトの構築(C++)」

- 第11章「キャッシュの問合せ(C++)」

- 第12章「連続問合せの実行(C++)」

- 第13章「リモート起動の実行(C++)」

- 第14章「キャッシュ・イベントの使用方法(C++)」

- 第15章「トランザクションの実行」

6 C++アプリケーション・ビルドの設定

この章では、Coherence for C++を使用するためのC++アプリケーション・ビルドの設定手順を説明します。

この章の内容は次のとおりです。

- Coherenceベースのアプリケーション向けのコンパイラの設定

- Coherenceのヘッダー・ファイルの組込み

- Coherenceライブラリのリンク

- ランタイム・ライブラリと検索パスの設定

- Coherence for C++のデプロイメント

6.1 Coherenceベースのアプリケーション向けのコンパイラの設定

アプリケーションのビルド・プロセスにCoherence for C++を統合する場合は、コンパイラとリンカーのいくつかの設定を有効にすることが重要です。これらの設定の中にはオプションのものもありますが、それらも含め、有効にすることを強くお薦めします。

*MSVC (Visual Studio)*

表6-1 MSVC (Visual Studio)向けのコンパイラの設定

設定

ビルド・タイプ

必須?

説明

/EHsc

すべて

はい

C++の例外のサポートを有効化

/GR

すべて

はい

C++のRTTIを有効化

/O2

リリース

いいえ

スピードの最適化を有効化

/MD

リリース

はい

マルチスレッド化したDLLに対してリンク

/MDd

デバッグ

はい

マルチスレッド化したデバッグDLLに対してリンク

g++ / SunPro

表6-2 g++向けのコンパイラの設定

設定

ビルド・タイプ

必須

説明

-O3

リリース

いいえ

スピードの最適化を有効化

-m32 / -m64

すべて

いいえ

コンパイラを明示的に32ビット・モードまたは64ビット・モードに設定

6.2 Coherenceのヘッダー・ファイルの組込み

Coherenceには、Coherence APIを使用し、アプリケーションとともにコンパイルする必要のある一連のヘッダー・ファイルが付属しています。このヘッダー・ファイルは、インストール先のincludeディレクトリにあります。使用しているコンパイラのinclude検索パスで、このincludeディレクトリを指定する必要があります。

6.3 Coherenceライブラリのリンク

Coherence for C++には、Coherenceライブラリのリリース・バージョンが付属しています。アプリケーション・コードのデバッグ・バージョンとのリンクでも、このライブラリが適しています。このライブラリは、インストール先のlibディレクトリにあります。リンクの際、リンカーのライブラリ・パスでこのディレクトリを指定する必要があります。

表6-3 リリース・バージョン向けおよびデバッグ・バージョン向けのリンク・ライブラリの名前

オペレーティング・システム

ライブラリ

Windows

coherence.lib

Solaris

libcoherence.so

Linux

libcoherence.so

Apple OS X

libcoherence.dylib

6.4 ランタイム・ライブラリと検索パスの設定

Coherence対応アプリケーションを実行しているときは、そのアプリケーションのライブラリ検索パスからCoherence for C++の共有ライブラリを利用できる必要があります。そのためには、この共有ライブラリが含まれているディレクトリを、オペレーティング・システム固有の環境変数に追加します。各ライブラリは、インストール先のlibサブディレクトリに格納されます。

表6-4 Coherence for C++のライブラリ名と環境変数

オペレーティング・システム

環境変数

Windows

PATH

Solaris

LD_LIBRARY_PATH

Linux

LD_LIBRARY_PATH

Apple (Mac) OS X

DYLD_LIBRARY_PATH

たとえば、WindowsでPATH環境変数を設定するには、次を実行します。

c:\coherence\coherence-cpp\examples> set PATH=%PATH%;c:\coherence\coherence-cpp\lib

JavaバージョンのCoherence同様、C++バージョンでも、構成のデフォルト設定より優先するシステム・プロパティの概念がサポートされています。C++で使用するシステム・プロパティは、オペレーティング・システムの標準的な環境変数を使用して設定します。使用するプロパティの名前は、Javaバージョンと同じです。tangosol.coherence.cacheconfigシステム・プロパティは、キャッシュ構成ファイルの場所を指定します。この構成ファイルの場所は、アプリケーション・コードでのプログラム処理(>CacheFactory::configure())でも設定できますが、この例ではその方法は採用していません。

表6-5 様々なオペレーティング・システム向けのキャッシュ構成のシステム・プロパティの値

オペレーティング・システム

システム・プロパティ

Windows

tangosol.coherence.cacheconfig

Linux

TangosolCoherenceCacheConfig

Solaris

TangosolCoherenceCacheConfig

Apple (Mac) OS X

TangosolCoherenceCacheConfig

注意:

UNIXのbashシェルなど、一部のオペレーティング・システム・シェルでは、.記号を含んだ環境変数をサポートしていません。この場合はキャメル・ケースを使用して、先頭の文字と各ピリオド文字(.)の後の1文字を大文字で記述します。つまり、tangosol.coherence.cacheconfigはTangosolCoherenceCacheConfigとします。

たとえば、Windowsでこの構成ファイルの場所を設定するには、次のコマンドを実行します。

c:\coherence\coherence-cpp\examples> set tangosol.coherence.cacheconfig=config\extend-cache-config.xml

6.5 Coherence for C++のデプロイメント

Coherence for C++には、専用のデプロイメント構成は必要ありません。アプリケーションをCoherenceライブラリとリンクするのみです。サンプル・ビルド・スクリプトおよび構成の例に関しては、Coherence例に含まれているC++の例を参照してください。例はCoherence for Javaディストリビューションの一部として含まれています。

注意:

Microsoft Windowsにデプロイする場合は、 Visual Studio 2005 SP1 C++ランタイム・ライブラリが必要です。このサンプルをビルドするには、Visual Studio 2005 SP1以降が必要です。

7 C++クライアントの構成と使用

この章では、Coherence for C++クライアントの設定手順を説明します。

この章には次の項が含まれます:

- 一般的な手順

- C++アプリケーションの実装

- アプリケーションのコンパイルとリンク

- パスの構成

- Coherence*Extendの構成

- C++によるキャッシュ参照の取得

- キャッシュに関連付けられたリソースのクリーンアップ

- Coherence for C++クライアント・ライブラリの構成と使用

- オペレーション構成ファイル(tangosol-coherence-override.xml)

- Loggerの構成

- CoherenceのDefaultCacheServerプロキシの起動

7.1 一般的な手順

Coherence for C++を構成して使用するには、次の7つの基本的な手順が必要です。

1. Coherence for C++ APIを使用してC++アプリケーションを実装します。APIの詳細は、第9章 「Coherence for C++クライアントAPIの使用」を参照してください。

2. アプリケーションをコンパイルおよびリンクします。

3. パスを構成します。

4. クライアント、およびクラスタにある1つ以上のJVMの両方にCoherence*Extendを構成します。

5. クライアント、およびクラスタの中でCoherence*Extendのクラスタ・サービスを実行しているすべてのJVMにPOFコンテキストを構成します。

6. Coherenceクラスタが稼動中であることを確認します。

7. C++クライアント・アプリケーションを起動します。

これらの手順の詳細は、次の各項で説明します。

7.2 C++アプリケーションの実装

Coherence for C++に用意されているAPIを使用すると、データ、データ・イベント、データ処理などのCoherenceクラスタ・サービスに、Coherenceクラスタ外部からC++アプリケーションを使用してアクセスできます。

Coherence for C++ APIは、次のもので構成されています。

- 一連のC++パブリック・ヘッダー・ファイル

- サポートされているすべてのC++コンパイラでビルドした、各バージョンの静的ライブラリ

- いくつかのサンプル

このライブラリを使用したC++アプリケーションは、Coherenceクラスタ内で稼働するCoherence*Extendのクラスタ・サービス・インスタンスに、高性能なTCP/IPベースの通信レイヤーを使用して接続できます。このライブラリからCoherence*Extendクラスタ・サービスにすべてのクライアント・リクエストが送信され、このサービスは実際のCoherenceクラスタ・サービス(パーティション・キャッシュ・サービス、レプリケーション・キャッシュ・サービスなど)に委任することで、クライアント・リクエストに応答します。

第9章 「Coherence for C++クライアントAPIの使用」では、APIのキー・クラスの概要を説明します。これらのクラスの詳細は、Coherence for C++のdocディレクトリにあるAPIそのものを参照してください。

7.3 アプリケーションのコンパイルとリンク

Coherence for C++を採用したアプリケーションをコンパイルできるプラットフォームのリストは、サポートされているプラットフォームとオペレーティング・システムに関するトピックを参照してください。

たとえば、次に示すWindows 32ビット・プラットフォーム用build.cmdファイルは、Coherence for C++のデモのファイルをビルド、コンパイルおよびリンクします。このファイルにある各変数の意味は次のとおりです。

- OPTおよびLOPTは、コンパイラのオプションをポイントします。

- INCは、includeディレクトリにあるCoherence for C++ APIのファイルをポイントします。

- SRCは、commonディレクトリにあるC++のヘッダー・ファイルとコード・ファイルをポイントします。

- OUTは、コードのコンパイルが完了したときにコンパイラやリンカーで生成する必要のあるファイルをポイントします。

- LIBPATHは、libraryディレクトリをポイントします。

- LIBSは、Coherence for C++の共有ライブラリ・ファイルをポイントします。

このファイルは、これらの環境変数を設定した後、C++のコード・ファイルとヘッダー・ファイル、APIファイルおよびOPTファイルをコンパイルし、LOPT、Coherence for C++の共有ライブラリ、生成されたオブジェクト・ファイルおよびOUTファイルをリンクします。オブジェクト・ファイルを削除することによってこの処理は終了します。build.cmdファイルの実行例を例7-1に示します。

例7-1 build.cmdファイルの実行例

@echo off
setlocal

set EXAMPLE=%1%

if "%EXAMPLE%"=="" (
echo You must supply the name of an example to build.
goto exit
)

set OPT=/c /nologo /EHsc /Zi /RTC1 /MD /GR /DWIN32
set LOPT=/NOLOGO /SUBSYSTEM:CONSOLE /INCREMENTAL:NO
set INC=/I%EXAMPLE% /Icommon /I..\include
set SRC=%EXAMPLE%\*.cpp common\*.cpp
set OUT=%EXAMPLE%\%EXAMPLE%.exe
set LIBPATH=..\lib
set LIBS=%LIBPATH%\coherence.lib

echo building %OUT% ...
cl %OPT% %INC% %SRC%
link %LOPT% %LIBS% *.obj /OUT:%OUT%

del *.obj

echo To run this example execute 'run %EXAMPLE%'

:exit

7.4 パスの構成

Coherence for C++ライブラリへの構成パスを設定します。この手順では、ライブラリをポイントする環境変数を設定します。環境変数名とライブラリのファイル名は、使用しているプラットフォーム環境によって異なります。プラットフォームごとの環境変数とライブラリ名のリストは、第6章「C++アプリケーション・ビルドの設定」を参照してください。

7.5 Coherence*Extendの構成

Coherence*Extendを構成するには、クラスタ側とクライアント側両方のキャッシュ構成ディスクリプタに適切な構成要素を追加します。クラスタ側のキャッシュ構成要素からCoherenceのDefaultCacheServerに対して、Coherence*Extendクライアントから受信したTCP/IPリクエストをリスニングするCoherence*Extendクラスタ・サービスを開始するように指示されます。クライアント側のキャッシュ構成要素は、クライアント・ライブラリによって、クラスタに接続するために使用されます。この構成は、クラスタの中でCoherence*Extendクラスタ・サービスを実行している1台以上のサーバーのIPアドレスとポートを特定します。これにより、ライブラリをクラスタに接続できます。この構成では、接続やリクエストのタイムアウトなど、接続に関連する様々なパラメータも記述します。

7.5.1 クラスタでのCoherence*Extendの構成

Coherence*ExtendクライアントをCoherenceクラスタに接続するには、そのクラスタにある1つ以上のDefaultCacheServer JVMで、TCP/IP Coherence*Extendクラスタ・サービスを実行している必要があります。このサービスを実行するようにDefaultCacheServerを構成するには、そのDefaultCacheServerで使用するキャッシュ構成ディスクリプタに、子にtcp-acceptor要素を持つproxy-scheme要素を追加する必要があります。

たとえば、例7-2のキャッシュ構成ディスクリプタは、2つのクラスタ・サービスを定義します。これは、リモートCoherence*ExtendクライアントをTCP/IPでCoherenceクラスタに接続できるようにするサービス、および標準のパーティション・キャッシュ・サービスです。このディスクリプタはDefaultCacheServerで使用しているため、クラスタ・サービスの終了時に自動的に再起動するように、各サービスの<autostart>構成要素をtrueに設定しておくことが重要です。proxy-scheme要素には、tcp-acceptorという子要素があり、この子要素には、TCP/IPを介してクライアント接続リクエストを受け入れるために必要なTCP/IP固有の情報がすべて含まれます。acceptor-configも、そのシリアライザ用にConfigurablePofContextを使用するように構成されています。C++ Extendのクライアントでは、シリアライズにPOFを使用する必要があります。

シリアライズとPIF/POFの詳細は、第10章「統合オブジェクトの構築(C++)」を参照してください。

次のように構成されたCoherence*Extendのクラスタ・サービスは、localhostアドレスとport 9099で、受信リクエストをリスニングします。たとえば、dist-extendというCoherenceキャッシュにクライアントが接続しようとすると、Coherence*Extendのクラスタ・サービスがNamedCacheへの後続リクエストを同じ名前で代行します。その名前は、この例ではパーティション・キャッシュとなります。

例7-2 2つのクラスタ・サービスのキャッシュ構成

<?xml version="1.0"?>

<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-*</cache-name>
<scheme-name>dist-default</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<distributed-scheme>
<scheme-name>dist-default</scheme-name>
<lease-granularity>member</lease-granularity>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
<serializer>
<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
</serializer>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>

7.5.2 クライアントでのCoherence*Extendの構成

Coherence*Extendのクライアントの構成にある主要な要素は<cache-config>です。この要素には、キャッシュ構成を含むキャッシュ構成ディスクリプタのパスを記述します。このキャッシュ構成ディスクリプタは、DefaultConfigurableCacheFactoryで使用されます。

Coherence*Extendクライアントでは、Coherenceクラスタ内で実行されるCoherence*Extendクラスタ・サービスへの接続およびCoherence*Extendクラスタ・サービスとの通信に、キャッシュ構成ディスクリプタの要素initiator-config内の情報が使用されます。

たとえば、例7-3のキャッシュ構成ディスクリプタは、リモートCoherenceクラスタに接続するキャッシング・スキームを定義します。remote-cache-scheme要素には、tcp-initiatorという子要素があり、この子要素には、リモートCoherenceクラスタ内でCoherence*Extendクラスタ・サービスが実行されているクライアントへの接続に必要なTCP/IP固有の情報がすべて含まれます。

クライアント・アプリケーションで、たとえばdist-extendという名前を使用してCacheFactoryで名前付きキャッシュを取得すると、Coherence*Extendクライアントは(アドレスlocalhostとport 9099による)TCP/IPを使用してCoherenceクラスタに接続し、NamedCache実装を返します。この実装は、リモート・クラスタの中で実行している同名のNamedCacheにリクエストをルーティングする機能を持っています。remote-addresses構成要素には、子要素socket-addressを複数記述できます。Coherence*Extendのクライアントは、記載されたアドレスをすべて試すか、またはTCP/IP接続が確立されるまで、アドレスへの接続をランダムに試行します。

例7-3 リモートCoherenceクラスタに接続するキャッシング・スキーム

<?xml version="1.0"?>

<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend</cache-name>
<scheme-name>extend-dist</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>

7.5.2.1 C++クライアント用ローカル・キャッシュの定義

ローカル・キャッシュは、特定のC++アプリケーションに対してローカルである(つまりアプリケーション内に完全に含まれる)キャッシュです。ローカル・キャッシュの特に興味深い属性について、次に示します。

- ローカル・キャッシュはリモート・キャッシュと同じインタフェースを実装します。つまり、ローカル・キャッシュを使用することとリモート・キャッシュを使用することにプログラミング上の違いはありません。

- ローカル・キャッシュのサイズは制限できます。サイズの制限とは、ローカル・キャッシュでキャッシュするエントリ数を制限し、キャッシュがいっぱいになったらエントリを自動的に削除できることを意味します。さらに、エントリのサイジングとエビクション・ポリシーの両方をカスタマイズできます。たとえば、キャッシュされたエントリで使用されるメモリーに基づいてキャッシュ・サイズを制限できます。デフォルトのエビクション・ポリシーでは、対数曲線で測定された、最も頻繁に使用する(MFU)情報と最後に使用した(MRU)情報の組合せを使用して削除するキャッシュ項目が決定されます。このアルゴリズムは、短期キャッシュと長期キャッシュの両方に対して十分に機能し、頻度と新しさのバランスをとってキャッシュ・スラッシングを回避するため、最適な汎用エビクション・アルゴリズムであるといえます。また、ピュアLRUアルゴリズムおよびピュアLFUアルゴリズムがサポートされ、カスタム・エビクション・ポリシーのプラグイン機能もサポートされています。

- ローカル・キャッシュはキャッシュ・エントリの自動失効をサポートしています。つまり、キャッシュ内の各キャッシュ・エントリに存続時間の値を割り当てることができます。さらに、定期的または事前に設定した時刻にフラッシュするようキャッシュ全体を構成できます。

- ローカル・キャッシュはスレッド・セーフで、高い並行性を備えています。

- ローカル・キャッシュでは、キャッシュのget統計が提供されます。ここには、キャッシュ・ヒットおよびキャッシュ・ミスの統計情報が保持されます。これらの実行時統計は、キャッシュの有効性を正確に推定できるため、キャッシュ実行時にサイズ制限や自動失効の設定を適宜調整できます。

ローカル・キャッシュの構成要素は<local-scheme>です。ローカル・キャッシュは通常、ニアスキームのフロント層としてなど、他のキャッシュ・スキーム内にネストされています。<local-scheme>には、キャッシュの特性を定義できるいくつかのサブ要素がオプションで用意されています。たとえば、<low-units>および<high-units>サブ要素はキャッシュのサイズを制限します。キャッシュが最大許容サイズに達すると、指定されたエビクション・ポリシー(<eviction-policy>)に従って削除対象エントリが決定され、指定されたより小さなサイズに戻ります。エントリおよびサイズの制限は、該当するスキームの単位換算カリキュレータ(<unit-calculator>)で計算される単位で測定されます。

キャッシュの有効期間も制限できます。<expiry-delay>サブ要素は、前回の更新からエントリが期限切れとしてマークされるまでの、キャッシュでエントリが保持される期間を指定します。期限切れのエントリを読み取るには、構成済のキャッシュ・ストア(<cachestore-scheme>)からエントリをリロードすることになります。期限切れになった値は、フラッシュ遅延に基づいてキャッシュから定期的に破棄されます。

<cache-store-scheme>が指定されていない場合、キャッシュされたデータはメモリー内に存在して、キャッシュに対して実行された操作のみが反映されます。使用可能なすべてのサブ要素の詳細は、<local-scheme>を参照してください。

例7-4は、ローカル・キャッシュ構成を示しています。

例7-4 ローカル・キャッシュ構成

<?xml version='1.0'?>

<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>example-local-cache</cache-name>
<scheme-name>example-local</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<local-scheme>
<scheme-name>example-local</scheme-name>
<eviction-policy>LRU</eviction-policy>
<high-units>32000</high-units>
<low-units>10</low-units>
<unit-calculator>FIXED</unit-calculator>
<expiry-delay>10ms</expiry-delay>
<cachestore-scheme>
<class-scheme>
<class-name>ExampleCacheStore</class-name>
</class-scheme>
</cachestore-scheme>
<pre-load>true</pre-load>
</local-scheme>
</caching-schemes>
</cache-config>

7.5.2.2 C++クライアント用ニア・キャッシュの定義

この章では、Coherence for C++クライアントに関係するニア・キャッシュについて説明します。ニア・キャッシュの概念、その構成およびバック層との同期を維持する方法の詳細は、『Oracle Coherenceでのアプリケーションの開発』のニア・キャッシュの構成に関する項を参照してください。

Coherence for C++でのニア・キャッシュは、リードスルー/ライトスルー方式を使用してフロント・キャッシュとバック・キャッシュをラップするcoherence::net::NamedCache実装です。バック・キャッシュがObservableCacheインタフェースを実装している場合、ニア・キャッシュはリスニング戦略にNone、Present、All、Autoのいずれかを使用して、バック・キャッシュで変更された可能性のあるフロント・キャッシュ・エントリを無効化します。

一般的なニア・キャッシュは、ローカル・キャッシュ(スレッド・セーフで並行性が高く、かつサイズが制限されていて、場合によっては自動的に失効するもの)をフロント・キャッシュとして使用し、リモート・キャッシュをバック・キャッシュとして使用するように構成されます。ニア・キャッシュの構成には、2つの子要素を持つnear-schemeが使用されます。1つはローカル(フロント)キャッシュを構成するためのfront-scheme、もう1つはリモート(バック)キャッシュを定義するためのback-schemeです。

ニア・キャッシュは、coherence-cache-configファイルの<near-scheme>要素を使用して構成します。この要素には、ローカル(フロント層)キャッシュを構成するためのfront-schemeと、リモート(バック層)キャッシュを定義するためのback-schemeの2つのサブ要素が要求されます。フロント層には通常、ローカル・キャッシュ(<local-scheme>)を選択しますが、JVMヒープ・ベース以外のキャッシュ(<external-scheme>または<paged-external-scheme>)またはJavaオブジェクトに基づくスキーム(<class-scheme>)も使用できます。

リモート、すなわちバック層のキャッシュは、<back-scheme>要素を使用して記述します。バック層のキャッシュには、分散キャッシュ(<distributed-scheme>)またはリモート・キャッシュ(<remote-cache-scheme>)を定義できます。<remote-cache-scheme>要素を使用すると、現在のクラスタの外部からクラスタ・キャッシュを使用できます。

<near-scheme>のオプションのサブ要素には、フロント層とバック層のオブジェクトの同期を維持する戦略を指定する<invalidation-strategy>、およびキャッシュで発生したイベントの通知を受け取るリスナーを指定する<listener>などがあります。

例7-5は、ニア・キャッシュの構成を示しています。

例7-5 ニア・キャッシュ構成

<?xml version="1.0"?>

<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend-near</cache-name>
<scheme-name>extend-near</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<near-scheme>
<scheme-name>extend-near</scheme-name>
<front-scheme>
<local-scheme>
<high-units>1000</high-units>
</local-scheme>
</front-scheme>
<back-scheme>
<remote-cache-scheme>
<scheme-ref>extend-dist</scheme-ref>
</remote-cache-scheme>
</back-scheme>
<invalidation-strategy>all</invalidation-strategy>
</near-scheme>

<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>

7.5.3 接続エラーの検出とフェイルオーバー

(ネットワーク、ソフトウェア、ハードウェアなどの障害によって)クライアントとクラスタ間の接続が切断されたことをCoherence*Extendのクライアント・サービスが検出すると、このCoherence*Extendのクライアント・サービスの実装(CacheServiceまたはInvocationService)によって(MemberEventHandlerデリゲートを使用して)MemberEventType.Leftイベントが発生し、このクライアント・サービスは停止します。クライアント・アプリケーションがその後もこのサービスを使用しようとする場合には、サービス自体が自動的に再起動してクラスタへの再接続を試行します。このサービスが接続に成功するとMemberEventType.Joinedイベントが発生し、接続に失敗するとクライアント・アプリケーションに修復できないエラーの例外がスローされます。

Coherence*Extendサービスには、接続の切断を検出するためのメカニズムがいくつか用意されています。その中には、(Extend-TCPのTCP/IPのように)基底プロトコルに固有のものもあれば、サービス自体に実装されるものもあります。後者のメカニズムは、<outgoing-message-handler要素を使用して構成されます。この要素の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。特に、<request-timeout値は、リクエストを中止するまでの応答を待機する時間を制御します。<heartbeat-intervalおよび<heartbeat-timeout値は、接続を閉じるまでのpingリクエストへの応答を待機する時間を制御します。

7.6 C++によるキャッシュ参照の取得

次のようにcoherence::net::CacheFactoryクラスを使用することによって、構成済ニア・キャッシュへの参照を名前によって取得できます。

NamedCache::Handle hCache = CacheFactory::getCache("example-near-cache");

7.7 キャッシュに関連付けられたリソースのクリーンアップ

すべてのNamedCache実装のインスタンスは、不要になった時点でNamedCache::release()メソッドをコールして明示的に解放し、インスタンスで保持されているリソースをすべて解放する必要があります。

特定のNamedCacheがアプリケーションの継続期間を通して使用される場合、リソースはそのアプリケーションがシャットダウンされたとき、または停止したときにクリーンアップされます。ただし、わずかの間だけ使用される場合は、使い終わった時点でアプリケーションからrelease()メソッドをコールする必要があります。

7.8 Coherence for C++クライアント・ライブラリの構成と使用

C++アプリケーションでCoherence for C++ライブラリを使用するには、そのアプリケーションにCoherence for C++ライブラリをリンクし、Coherence for C++のキャッシュ構成と場所を指定する必要があります。

キャッシュ構成ファイルの場所は、サンプル・アプリケーションの項で指定した環境変数、またはプログラム上の処理で設定できます。

7.8.1 環境変数による構成ファイルの場所の設定

「ランタイム・ライブラリと検索パスの設定」の説明のとおり、tangosol.coherence.cacheconfigシステム・プロパティは、キャッシュ構成ファイルの場所を指定します。Windowsでこの構成ファイルの場所を設定するには、次のコマンドを実行します。

c:\coherence_cpp\examples> set tangosol.coherence.cacheconfig=config\extend-cache-config.xml

7.8.2 プログラム処理による構成ファイルの場所の設定

DefaultConfigurableCacheFactory::createとCacheFactory::configure(必要に応じてCacheFactory::loadXmlFileヘルパー・メソッドを使用)のいずれかを使用して、プログラム処理で構成ファイルの場所を設定できます。

例7-6 構成ファイルの場所の設定

static Handle coherence::net::DefaultConfigurableCacheFactory::create (String::View vsFile = String::NULL_STRING)

DefaultConfigurableCacheFactoryクラスのcreateメソッドで、新しいCoherence cacheファクトリを作成します。vsFileパラメータで、ロードするCoherenceの構成ファイルの名前と場所を指定します。

例7-7 Coherenceキャッシュ・ファクトリの作成

static void coherence::net::CacheFactory::configure (XmlElement::View vXmlCache, XmlElement::View  vXmlCoherence = NULL)

configureメソッドで、CacheFactoryとローカル・メンバーを構成します。coherence-cache-config.xsdに対応するXML要素をvXmlCacheパラメータで指定し、coherence-operational-config.xsdに対応するXML要素をvXmlCoherenceパラメータで指定します。

例7-8 CacheFactoryとローカル・メンバーの構成

static XmlElement::Handle coherence::net::CacheFactory::loadXmlFile (String::View vsFile)

loadXmlFileメソッドで、指定されたファイルからXmlElementを読み取ります。このメソッドでは、CacheFactoryを構成しませんが、configureメソッドに対して指定できる構成を取得します。パラメータvsFileで、読込み元であるファイルの名前を指定します。

例7-9のC++コードでは、CacheFactory::configureメソッドを使用して、サーバー/クラスタのキャッシュ構成ファイル(coherence-extend-config.xml)の場所およびC++クライアントのキャッシュ構成ファイル(tangosol-operation-config.xml)の場所を設定します。

例7-9 サーバー/クラスタのキャッシュ構成ファイルの場所の設定

...
// Configure the cache
CacheFactory::configure(CacheFactory::loadXmlFile(String::create("C:\coherence-extend-config.xml")),
CacheFactory::loadXmlFile(String::create("C:\tangosol-operation-config.xml")));
...

7.9 オペレーション構成ファイル(tangosol-coherence-override.xml)

オペレーション構成オーバーライド・ファイル(デフォルトではtangosol-coherence-override.xml)では、Oracle Coherenceで使用する操作設定とランタイム設定を制御して、そのクラスタ・サービス、通信サービスおよびデータ管理サービスを作成、構成および維持します。Javaクライアント同様、C++クライアントでもこのファイルの使用はオプションです。

C++クライアントの場合、このファイルによって、具体的にキャッシングに関連していないCoherenceアプリケーションの一般的な操作設定を指定するかオーバーライドできます。C++クライアントの場合の主要な要素は、ロギング、Coherence製品のエディション、および特定のクラスタ・メンバーの場所とロールの割当てのためのものです。

オペレーション構成は、プログラム上の処理またはtangosol-coherence-override.xmlファイルで構成できます。プログラム上の処理でオペレーション構成を構成するには、CacheFactory::configureメソッド(coherence::net::CacheFactory::configure(View vXmlCache, View vXmlCoherence))のvXmlCoherenceパラメータに要素が記述され、coherence-operational-config.xsdスキーマに従ったXMLファイルを指定します。

- license-config: license-config要素には、Coherenceのエディションと操作モードの構成を可能にするサブ要素を記述します。edition-nameサブ要素は、メンバーが使用する製品エディション(Grid Edition、Enterprise Edition、Real Time Clientなど)を指定します。この方法では、使用するエディションをメンバーごとに指定することによって、同じくクラスタの中で複数の製品エディションを使用できます。Coherence for C++クライアントの場合は、RTC(リアルタイム・クライアント)およびDC(データ・クライアント)の各値のみを認識できます。license-configは、coherence要素のオプションのサブ要素で、デフォルト値はRTCです。

- logging-config: logging-config要素は、システムにメッセージのログを記録する方法の構成を可能にするサブ要素を記述します。この要素を使用して、ログ・メッセージの保存先、重大度および書式を指定できます。logging-configは、coherence要素の必須のサブ要素です。ロギングの詳細は、「Loggerの構成」を参照してください。

- member-identity: member-identity要素は、クラスタ・メンバーの場所とロールの定義に役立つ詳細な識別情報を指定します。この要素は、メンバーが属するクラスタ、ラック、サイト、コンピュータ名、ロールなどを指定するために使用できます。member-identityは、cluster-config要素のオプションのサブ要素です。例7-10は、サンプル・ファイルtangosol-coherence.xmlの内容を示しています。

例7-10 オペレーション構成のサンプル

<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/
coherence-operational-config coherence-operational-config.xsd">
<cluster-config>
<member-identity>
<site-name>extend site</site-name>
<rack-name>rack 1</rack-name>
<machine-name>computer 1</machine-name>
</member-identity>
</cluster-config>

<logging-config>
<destination>stderr</destination>
<severity-level>5</severity-level>
<message-format>(thread={thread}): {text}</message-format>
<character-limit>8192</character-limit>
</logging-config>

<license-config>
<edition-name>RTC</edition-name>
<license-mode>prod</license-mode>
</license-config>
</coherence>

「オペレーション構成の要素」では、オペレーション構成ファイルとそこで定義できる要素について詳しく説明しています。

7.10 Loggerの構成

Loggerは、オペレーション構成ファイルのlogging-config要素を使用して構成します。この要素では次の属性を指定します。これらの属性では、ログに記録されたエラーに関する詳細情報を記録できます。

- destination: Loggerで使用するLogOutputのタイプを指定します。有効な値は次のとおりです。

- stderr(Console.Errorの場合)

- stdout(Console.Outの場合)

- ファイル・パス(メッセージをファイルに送信する必要がある場合)

- severity-level: メッセージをログに記録するために満たすか、または超過する必要のあるログ・レベルを決定します。

- message-format: ログ・メッセージの書式を決定します。

- character-limit: ログ出力デーモンがメッセージ・キューから処理する文字の最大数を決定します。この数を超過すると、キューに残っているメッセージがすべて破棄されます。例7-11は、ロギングの構成を記述したオペレーション構成を示しています。オペレーション構成の詳細は、「オペレーション構成ファイル(tangosol-coherence-override.xml)」を参照してください。

例7-11 ログ出力を扱うオペレーション構成ファイル

<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/
coherence-operational-config coherence-operational-config.xsd">
<logging-config>
<destination>stderr</destination>
<severity-level>5</severity-level>
<message-format>(thread={thread}): {text}</message-format>
<character-limit>8192</character-limit>
</logging-config>
</coherence>

7.11 CoherenceのDefaultCacheServerプロキシの起動

すでに説明したクラスタ側のCoherenceキャッシュ構成を使用するDefaultCacheServerを起動し、TCP/IPを使用してCoherence for C++クライアントをCoherenceクラスタに接続できるようにするには、次の手順を実行する必要があります。

1. 現在のディレクトリをOracle Coherenceのライブラリ・ディレクトリに変更します(Windowsの場合は%COHERENCE_HOME%\lib、UNIXの場合は$COHERENCE_HOME/lib)。

2. Javaコマンドが実行されるようにパスを構成します。

3. 次のコマンドラインを使用してDefaultCacheServerを起動します。

例7-12 DefaultCacheServerを起動するコマンドのサンプル

java -cp coherence.jar -Dtangosol.coherence.cacheconfig=file://<path to the server-side cache configuration descriptor>
com.tangosol.net.DefaultCacheServer

8 CoherenceのC++オブジェクト・モデルの使用

この章では、Coherence for C++のオブジェクト・モデルについて説明します。オブジェクト・モデルはCoherence C++の基礎となっています。

この章には次の項が含まれます:

- オブジェクト・モデルの使用

- 新規管理クラスの作成

- 診断およびトラブルシューティング

- アプリケーション・ランチャ - Sanka

8.1 オブジェクト・モデルの使用

次の項では、オブジェクト・モデルを使用するコードの記述に関する一般的な情報について説明します。

8.1.1 Coherenceのネームスペース

このcoherenceのネームスペースには、次の汎用ネームスペースがあります。

- coherence::lang: オブジェクト・モデルを構成する必須クラス

- coherence::util: 各種コレクションなどのユーティリティ・コード

- coherence::net: ネットワークおよびキャッシュ

- coherence::stl: C++標準テンプレート・ライブラリ統合

- coherence::io: シリアライズ

各クラスは専用のヘッダー・ファイルで定義しますが、ネームスペース全体に適用するヘッダー・ファイルを使用すると、関連するクラスを容易に組み込めます。このオブジェクト・モデルを使用するコードには、少なくともcoherence/lang.nsを含めることをお薦めします。

8.1.2 ベース・オブジェクトの理解

coherence::lang::Objectクラスは、クラス階層のルートです。このクラスは、Coherenceのクラスのインスタンスを抽象化して扱うための共通インタフェースを提供します。オブジェクトは、次の関数をデフォルトで実装できるようにするインスタンス化可能クラスです。

- equals

- hashCode

- clone(オプション)

- toStream(Objectをstd::ostreamに書き込みます)

詳細は、C++ APIの「coherence::lang::Object」を参照してください。

8.1.3 自動管理メモリー

Objectクラスには、publicインタフェース以外にも、内部で使用する機能がいくつかあります。これらの機能のうち最も重要なものとして、参照カウンタがあります。これによって、オブジェクトに割り当てるメモリーを自動的に管理できます。この自動管理機能を使用すると、オブジェクト参照の妥当性とオブジェクト削除の担当範囲に関連付けられる問題の多くがなくなります。また、メモリーのリークや破損を引き起こすプログラミング上のエラーが発生する可能性も低下します。これにより、複雑なシステムを構築するための安定したプラットフォームが得られます。

参照カウンタなど、オブジェクトのライフサイクルに関する情報は、ロックフリーでアトミックなコンペア・アンド・セット操作を使用して、効率的でスレッド・セーフに動作します。これにより、カウントが破損したり別のスレッドの動作によってオブジェクトが予期せずに削除されることもなく、複数のスレッド間でオブジェクトを安全に共有できます。

8.1.3.1 管理オブジェクトの参照

特定のオブジェクトに対する参照の数を追跡するには、ポインタ割当てとメモリー・マネージャ(この場合はオブジェクト)の間に、あるレベルの協調関係が必要です。基本的には、管理オブジェクトを参照するポインタを設定するたびに、それをメモリー・マネージャに通知する必要があります。通常のC++ポインタを使用した場合は、ポインタを割り当てるたびにメモリー・マネージャへの通知タスクが発生するように、プログラマ側で準備することになります。この作業は煩雑であるばかりでなく、メモリー・マネージャに対するこの通知タスクを準備しておかないと、メモリーのリークや破損を引き起こします。この理由から、スマート・ポインタを使用することによって、メモリー・マネージャへの通知タスクをオブジェクト・モデルに置き、このタスクからアプリケーション開発者を解放しています。スマート・ポインタの構文は、通常のC++ポインタに類似していますが、自動的なブックキーピング機能を備えています。

CoherenceのC++オブジェクト・モデルには様々なタイプのスマート・ポインタが用意されています。その主なものは次のとおりです。

- View: 参照オブジェクトに対してconstメソッドのみをコールできるスマート・ポインタ。

- Handle: 参照オブジェクトに対してconstと非constの両メソッドをコールできるスマート・ポインタ。

- Holder: constまたは非constとしてオブジェクトを参照できるようにする特殊なタイプのハンドル。Holderは、オブジェクトが最初にどのように割り当てられたかを保持していて、それと互換性のある形式のみを返します。

View、HandleおよびHolderは最も使用頻度の高いスマート・ポインタです。特別な用途を持つこれ以外のスマート・ポインタについては、この項で後述します。

注意:

このドキュメントでいうハンドルとは、様々なオブジェクト・モデルのスマート・ポインタを指しています。また、Handleとは、具体的なHandleスマート・ポインタを指します。

8.1.3.2 ハンドルの使用

規則上、各管理クラスには、これらのハンドルに対応するネストしたタイプがあります。たとえば、管理クラスcoherence::lang::Stringでは、String::Handle、String::View、String::Holderを定義しています。

8.1.3.2.1 ハンドルの割当て

ハンドルの割当ては、通常の継承割当て規則に従います。つまり、HandleをViewに割り当てることはできますが、ViewをHandleに割り当てることはできません。これは、constポインタを非constポインタに割り当てることができないのと同様です。

8.1.3.2.2 ハンドルの間接参照

NULLを参照するハンドルを間接参照すると、従来のセグメンテーション・フォルトはトリガーされず、coherence::lang::NullPointerExceptionがスローされます。

たとえば、次のコードでhs == NULLとすると、NullPointerExceptionがスローされます。

String::Handle hs = getStringFromElsewhere();
cout << "length is " << hs->length() << end1;

8.1.3.3 管理オブジェクトのインスタンス化

すべての管理オブジェクトにはヒープが割り当てられます。オブジェクトをいつ削除できるかは、スタックではなく参照カウントで決まります。スタックに基づく割当てが誤って発生しないように、すべてのコンストラクタは保護され、オブジェクトのインスタンス化では、publicファクトリ・メソッドが使用されます。

このファクトリ・メソッドはcreateという名前で、各コンストラクタにはcreateメソッドが1つずつあります。createメソッドでは、生のポインタでなくHandleが返されます。たとえば、次のコードではStringの新しいインスタンスが作成されます。

String::Handle hs = String::create("hello world");

比較のためにあげた次のコード例は正しくなく、コンパイルできません。

String str("hello world");
String* ps = new String("hello world");

8.1.4 管理文字列

モデル内のオブジェクトはすべて、文字列も含め、Objectで管理され、拡張されます。オブジェクト・モデルでは、char*またはstd::stringを使用するかわりに、専用の管理クラスであるcoherence::lang::Stringを使用します。Stringクラスは、ASCIIおよびすべてのUnicode BMLキャラクタ・セットをサポートしています。

8.1.4.1 文字列のインスタンス化

Stringオブジェクトは、char*文字列またはstd::string文字列から容易に構成できます。次にその例を示します。

例8-1 Stringオブジェクトの構成例

const char*    pcstr = "hello world";
std:string     stdstr(pcstr);
String::Handle hs   = String::create(pcstr);
String::Handle hs2  = String::create(stdstr);

管理文字列は、指定した文字列のコピーですが、元の文字列に対する参照もポインタも含まれていません。getCString()メソッドを使用すると、管理文字列を変換して他の任意の型の文字列に戻すことができます。このメソッドでは、元のconst char*へのポインタが返されます。COH_TO_STRINGマクロを組み合せると、C++の標準的な演算子<<を使用してStringを作成することもできます。

例8-2 <<演算子を使用したStringオブジェクトの構成

String::Handle hs = COH_TO_STRING("hello " << getName() << " it is currently " << getTime());

8.1.4.2 自動ボックス付き文字列

引用符を使用した文字列リテラルを使用しやすくするために、String::HandleおよびString::Viewではconst char*およびconst std::stringでの自動ボックス付け処理をサポートしています。これにより、前述のサンプルのコードを次のように記述できます。

例8-3 自動ボックス付け処理の例

String::Handle hs  = "hello world";
String::Handle hs2 = stdstr;

自動ボックス付け処理は、他の型でも可能です。詳細は、「coherence::lang::BoxHandle」を参照してください。

8.1.5 型保証キャスト

Handleは、型保証であり、次の例ではStringではないObjectが存在するため、コンパイラでObject::HandleをString::Handleに割り当てることはできません。

Object::Handle ho = getObjectFromSomewhere();
String::Handel hs = ho; // does not compile

ただし、表8-0ではすべてのStringがObjectであるため、コンパイルが可能です。

例8-4 型保証キャストの例

String::Handle hs = String::create("hello world");
Object::Handle ho = hs; // does compile

8.1.5.1 ダウン・キャスト

派生したObject型にダウン・キャストする場合は、C++のRTTI(実行時型情報)チェックを使用して動的キャストを実行し、そのキャストが有効であるようにする必要があります。オブジェクト・モデルには、構文を容易にするヘルパー関数が用意されています。

- cast<H>(o): 指定されたハンドルoを型Hに変換します。失敗した場合はClassCastExceptionをスローします。

- instanceof<H>(o): oからHへのキャストが可能かどうかをテストします。可能な場合はtrue、不可能な場合はfalseをそれぞれ返します。

これらの関数は標準的なC++のdynamic_cast<T>に似ていますが、生のポインタへのアクセスを必要としません。

次の例は、Object::HandleからString::Handleにダウン・キャストする方法を示しています。

例8-5 ダウン・キャストの例

Object::Handle ho = getObjectFromSomewhere();
String::Handle hs = cast<String::Handle>(ho);

指定されたオブジェクトが予期された型ではない場合、cast<H>関数はcoherence::lang::ClassCastExceptionをスローします。instanceof<H>関数を使用すると、例外がスローされることなく、オブジェクトが特定の型であるかどうかがテストされます。このようなチェックは一般的に、実際の型に疑問がある場合にのみ必要となります。

例8-6 instanceof<H>関数によるオブジェクト型のチェック

Object::Handle ho = getObjectFromSomewhere();

if (instanceof<String::Handle>(ho))
{
String::Handle hs = cast<String::Handle>(ho);
}
else if (instanceof<Integer32::Handle>(ho))
{
Integer32::Handle hn = cast<Integer32::Handle>(ho);
}
else
{
...
}

8.1.6 マネージ配列

マネージ配列は、coherence::lang::Array<T>テンプレート・クラスを使用して得ることができます。このクラスは管理対象であり、安全な自動メモリー管理機能を追加するほか、配列全体の長さを含み、チェック済の索引付けをバインドします。

次の例のように、配列のHandleの添字演算子を使用して、その配列に索引を付けることができます。

例8-7 配列の索引付け

Array<int32_t>::Handle harr = Array<int32_t>::create(10);

int32_t nTotal = 0;
for (size32_t i = 0, c = harr->length; i < c; ++i)
{
nTotal += harr[i];
}

オブジェクト・モデルは、C++のプリミティブと管理されているObjectの配列をサポートしています。サポートされているのはObjectの配列のみで、派生したObject型の配列は対象外です。派生したハンドルの型を取得するには、キャストを採用する必要があります。Objectの配列は、技術的にはArray<MemberHolder<Object> >となりますが、わかりやすくするためにObjectArrayとして定義します。

8.1.7 コレクション・クラス

coherence::util*ネームスペースには、コレクション・クラスとインタフェースがいくつかあり、これらをアプリケーションで使用すると便利です。これらには、次のものが含まれます。

- coherence::util::Collection: インタフェース

- coherence::util::List: インタフェース

- coherence::util::Set: インタフェース

- coherence::util::Queue: インタフェース

- coherence::util::Map: インタフェース

- coherence::util::Arrays: 実装

- coherence::util::LinkedList: 実装

- coherence::util::HashSet: 実装

- coherence::util::DualQueue: 実装

- coherence::util::HashSet: 実装

- coherence::util::SafeHashMap: 実装

- coherence::util::WeakHashMap: 実装

- coherence::util::IdentityHashMap: 実装

これらのクラスは、Coherence Extend APIの一部にもなっています。

ObjectArrayと同様、CollectionにはObject::Holderが含まれているため、あらゆるタイプの管理オブジェクトのインスタンスを格納できます。

例8-8 管理オブジェクトのインスタンスの格納

Map::Handle  hMap = HashSet::create();
String::View vKey = "hello world";

hMap->put(vKey, Integer32::create(123));

Integer32::Handle hValue = cast<Integer32::Handle>(hMap->get(vKey));

8.1.8 マネージ例外

オブジェクト・モデルでは、例外も管理オブジェクトです。マネージ例外により、オブジェクト・スライシングを発生させないで、捕捉した例外をローカル変数またはデータ・メンバーとして保持できます。

Coherenceの例外はすべて、throwable_specを使用して定義し、coherence::lang::Exceptionクラスから派生します。また、このクラスはObjectから派生します。マネージ例外は、C++の標準的なthrow文を使用して明示的にスローされるのではなく、COH_THROWマクロを使用してスローされます。このマクロはスタック情報を設定してから、例外のraiseメソッドをコールします。このメソッドが最終的にスローをコールします。これによってスローされたオブジェクトは、対応する例外のView型または継承されたView型として捕捉できます。さらに、これらのマネージ例外は、標準的なconst std::exceptionクラスとして捕捉できます。次の例は、マネージ例外を使用したtry/catchブロックを示しています。

例8-9 マネージ例外を使用したtry/catchブロック

try
{
Object::Handle h = NULL;
h->hashCode(); // trigger an exception
}
catch (NullPointerException::View e)
{
cerr << "caught" << e <<endl;
COH_THROW(e); // rethrow
}

注意:

この例外は、Exception::Viewまたはconst std::exception&として捕捉することもできます。

8.1.9 オブジェクトの不変性

C++では、オブジェクトがどのように宣言されたか(たとえばconstとして宣言されたオブジェクト)という情報は、オブジェクトへのポインタや参照からは得られません。たとえば、const Foo*型のポインタでは、そのポインタのユーザーにはオブジェクトの状態を変えることができないという点が示されるのみです。参照先のオブジェクトが実際にconstとして宣言されたものかどうか、また変化しないことが確実なのかどうかはわかりません。オブジェクト・モデルでは、実行時の不変性機能を追加し、状態が変化しないオブジェクトを識別できるようにしています。

Objectクラスには、Handle用とView用の2つの参照カウンタが保持されています。Viewのみから参照されているオブジェクトは、定義上は不変です。これは、Viewではオブジェクトの状態を変えることができず、ViewからHandleを取得することもできないためです。(Objectクラスに含まれる)isImmutable()メソッドで、この状態をテストできます。これは仮想メソッドであり、不変の定義をサブクラスで変更できるようにします。たとえば、Stringには非constメソッドがないため、そのisImmutable()メソッドは必ずtrueを返します。

不変になったオブジェクトを可変に戻すことはできません。constの性質を捨ててViewをHandleに変えることは、確認済の不変性に違反するため不可能です。

キャッシングでは不変性は重要です。CoherenceのNearCacheおよびContinuousQueryCacheでは、不変性を利用することで、オブジェクトの直接参照をキャッシュに格納できるかどうか、または参照のコピーを作成する必要があるかどうかを判断できます。さらに、オブジェクトが変更不可能であることがわかれば、同期化を行わないで、マルチスレッドによる安全な対話処理が可能になります。

8.1.10 オブジェクト・モデルへの既存のクラスの統合

既存のクラスは、しばしばオブジェクト・モデルに統合することが必要になります。その典型的な例として、管理オブジェクトの格納のみをサポートしているCoherenceキャッシュにデータ・オブジェクトを格納する状況があげられます。以前から存在しているクラスに対してcoherence::lang::Objectの拡張への変更を要求することは合理的ではないため、オブジェクト・モデルにはアダプタが用意されています。このアダプタは、非管理の単純な古いC++クラスのインスタンスを実行時に管理クラスのインスタンスに自動的に変換します。

これは、coherence::lang::Managed<T>テンプレート・クラスを使用して実現できます。このテンプレート・クラスは、Objectおよび指定のテンプレート・パラメータ型Tを拡張したもので、実質的にObjectでもありTでもある新しいクラスが生成されます。この新しいクラスはTから初期化できます。また、変換してTに戻すこともできます。これによって得られる機能は、使用方法は簡単ですが、管理コードと非管理コードを結び付ける高度な性能を備えています。

詳細と例は、coherence::lang::Managedに関するAPIドキュメントを参照してください。

8.2 新規管理クラスの作成

次の項では、Objectを拡張したクラスである新規管理クラスの作成に必要な情報について説明します。新規管理クラスの作成は、EventListener、EntryProcessor、Filterのいずれかの型を新規に作成する場合に必要となります。既存のC++データ・オブジェクトを扱う場合やCoherenceのC++ APIを利用する場合は、管理クラスを新規に作成する必要はありません。オブジェクト・モデルへの非管理クラスの統合の詳細は、前の項を参照してください。

8.2.1 仕様に基づく管理クラスの定義

仕様に基づく定義(spec)を使用すると、C++で管理クラスを迅速に定義できます。

管理クラスの独自の実装を作成するときは、仕様に基づく定義が役に立ちます。

次のように、様々なタイプのクラスの作成に使用する数多くの形式のspecがあります。

- class_spec: 標準的なインスタンス化可能なクラスの定義

- cloneable_spec: クローニング可能なクラスの定義

- abstract_spec: 真の仮想メソッドをゼロ個以上持つ、インスタンス化不可能なクラスの定義

- interface_spec: インタフェース定義(真に仮想で多重継承可能なクラス)

- throwable_spec: 例外としてスロー可能な管理クラス

specでは、specの対象となるクラスに対して次の機能が自動的に定義されます。

- Handle、View、Holder

- 保護されたコンストラクタに委任される静的なcreate()メソッド

- コピー・コンストラクタに委任される仮想clone()メソッド

- ::sizeof()に基づく仮想sizeOf()

- 定義したクラスの派生元クラスを参照するためのスーパーtypedef

- coherence::lang::Objectからの継承(extends<>を使用して親クラスが指定されていない場合)

specを使用してクラスを定義するには、前述のspecからそのクラスをパブリックに継承します。これらのspecはそれぞれ、パラメータ化されたテンプレートです。このパラメータは次のとおりです。

- 定義するクラスの名前。

- パブリックに継承する元のクラスで、extends<>文を使用して指定します。この指定は、デフォルトではextends<Object>です。

- interface_specには、この要素はありません。

- extends<Object>を除き、親クラスは仮想的には派生しません。

- このクラスで実装するインタフェースのリスト。implements<>文で指定します。

- すべてのインタフェースは、パブリックな仮想継承を使用して派生します。

extends<>パラメータは、インタフェースの定義には使用しません。

例8-10は、interface_specを使用してComparableインタフェースを定義する方法を示しています。

例8-10 interface_specで定義するインタフェース

class Comparable
: public interface_spec<Comparable>
{
public:
virtual int32_t compareTo(Object::View v) const = 0;
};

例8-11は、interface_specを使用して派生インタフェースNumberを定義する方法を示しています。

例8-11 interface_specで定義する派生インタフェース

class Number
: public interface_spec<Number,
implements<Comparable> >
{
public:
virtual int32_t getValue() const = 0;
};

次に、cloneable_specを使用して実装を生成します。これについては例8-12に示しています。

注意:

自動生成のcreateメソッドをサポートするには、インスタンス化可能なクラスでcoherence::lang::factory<>テンプレートをフレンドとして宣言する必要があります。規則上は、これがクラス本体の先頭に記述する文となります。

例8-12 cloneable_specで定義する実装

class Integer
: public cloneable_spec<Integer,
extends<Object>,
implements<Number> >
{
friend class factory<Integer>;

protected:
Integer(int32_t n)
: super(), m_n(n)
{
}

Integer(const Integer& that)
: super(that), m_n(that.m_n)
{
}

public:
virtual int32_t getValue() const
{
return m_n;
}

virtual int32_t compareTo(Object::View v) const
{
return getValue() - cast<Integer::View>(v)->getValue();
}

virtual void toStream(std::ostream& out) const
{
out << getValue();
}

private:
int32_t m_n;
};

例8-12のクラス定義は、例8-13に示す、仕様に基づかないクラス定義と同等です。

例8-13 specを使用しないクラスの定義

class Integer
: public virtual Object, public virtual Number
{
public:
typedef TypedHandle<const Integer> View;   // was auto-generated
typedef TypedHandle<Integer>       Handle; // was auto-generated
typedef TypedHolder<Integer>       Holder; // was auto-generated
typedef super                      Object; // was auto-generated

// was auto-generated
static Integer::Handle create(const int32_t& n)
{
return new Integer(n);
}

protected:
Integer(int32_t n)
: super(), m_n(n)
{
}

Integer(const Integer& that)
: super(that), m_n(that.n)
{
}

public:
virtual int32_t getValue() const
{
return m_n;
}

virtual int32_t compareTo(Object::View v) const
{
return getValue() - cast<Integer::View>(v)->getValue();
}

virtual void toStream(std::ostream& out) const
{
out << getValue();
}

// was auto-generated
virtual Object::Handle clone() const
{
return new Integer(*this);
}

// was auto-generated
virtual size32_t sizeOf() const
{
return ::sizeof(Integer);
}

private:
int32_t m_n;
};

例8-14は、specの対象となるクラスを使用して定義する方法を示しています。

例8-14 specを使用したクラスの定義

Integer::Handle hNum1 = Integer::create(123);
Integer::Handle hNum2 = Integer::create(456);

if (hNum1->compareTo(hNum2) > 0)
{
std::cout << hNum1 << " is greater then " << hNum2 << std::endl;
}

8.2.2 等価性、ハッシング、クローニング、不変性およびシリアライズ

等価性、ハッシング、クローニング、不変性およびシリアライズはすべてオブジェクトの状態を示すもので、一般的に実装面で似たような問題点を抱えています。簡単に説明すると、これらのメソッドのいずれかで参照しているすべてのデータ・メンバーは、すべてのメソッドで参照する可能性があります。逆に、いずれかのメソッドで参照していないデータ・メンバーは、どのメソッドでも参照できなくなる可能性があります。

ここでは簡単な例として、HashSet::Entryに既知のキーと値のデータ・メンバーがあるとします。これらのデータ・メンバーは、equalsメソッドで考慮することになっています。データ・メンバーの等価性については、参照の等価性ではなく、それぞれが持つequalsメソッドへのコールを使用してテストします。このEntryが、HashSetの実装の一部として、HashSetのバケットの中で次の順番にあるEntryへのハンドルを持っていて、同時にHashSet自身へのハンドルも持っている場合、これらもequalsで考慮する必要があるかどうかを検討します。この場合、その必然性はないと考えられます。等価なキーと値を持ち、別々の2つのマップにある2つのエントリを比較すると、その結果は等価になると考えることが合理的です。この考え方に従うと、Entryに対するhashCodeメソッドでは、キーと値以外のデータ・メンバーが完全に無視され、EntryのhashCodeは、データ・メンバーのIDのhashCodeではなく、そのキーと値のhashCodeの結果を使用して計算されます。つまり、equalsによる詳細な等価性チェックでは、hashCodeによって詳細なハッシュが生成されることを意味します。

クローンの場合、クローニングが必要なのはキーと値のみです(すべてのデータ・メンバーではありません)。クローニングの過程で親Mapをクローニングするには、Entryでは意味はなく、次の順番にあるEntryへのハンドルのクローニングにも同様のことがいえます。この考え方は、isImmutableメソッドとシリアライズにも同様に適用できます。必ずしも必須で厳密な規則としての考え方ではありませんが、前述のメソッドのいずれかを実装する際には検討の余地があります。

8.2.3 スレッド処理

オブジェクト・モデルにはマネージ・スレッドが用意されており、これを使用すると、プラットフォームに依存しないマルチスレッドのアプリケーションを容易に作成できます。スレッド処理の抽象化では、スレッドの作成、割込みおよび結合のサポートを扱います。スレッド・ローカル記憶域は、coherence::lang::ThreadLocalreferenceクラスで利用できます。診断とトラブルシューティングのためにスレッドのダンプを利用することも可能です。究極的にはマネージ・スレッドとは、POSIXやWindowsのスレッドなど、システムがネイティブで持つタイプのスレッドのラッパーです。このスレッド処理の抽象化はCoherenceで内部的に使用されていますが、必要に応じてアプリケーションでも利用できます。

例8-15は、Runnableインスタンスを作成し、スレッドを生成する方法を示しています。

例8-15 Runnableインスタンスの作成とスレッドの生成

class HelloRunner
: public class_spec<HelloRunner,
extends<Object>,
implements<Runnable> >
{
friend class factory<HelloRunner>;

protected:
HelloRunner(int cReps)
: super(), m_cReps(cReps)
{
}

public:
virtual void run()
{
for (int i = 0; i < m_Reps; ++i)
{
Thread::sleep(1000);
std::cout << "hello world" << std::endl;
}
}

protected:
int m_cReps;
};

...

Thread::Handle hThread = Thread::create(HelloRunner::create(10));
hThread->start();
hThread->join();

詳細は、「coherence::lang::Thread」および「coherence::lang::Runnable」を参照してください。

8.2.4 弱参照

参照カウント・スキームの機能上の大きな制限として、循環オブジェクト・グラフの自動クリーンアップがあります。図8-1に示す簡単な双方向の関係について考えます。

図8-1 双方向の関係

「図8-1 双方向の関係」の説明

この図では、AとBの両方が、それぞれをアクティブに維持する参照カウントを1つ持っています。それらは、互いをアクティブに維持しているものがそれら自身のみであること、および外部からそれらを参照しているものが存在しないことを認識していません。参照カウントのみではこの自立型グラフを扱うことができず、メモリー・リークが発生します。

グラフを扱うために用意されているメカニズムが弱参照です。弱参照はオブジェクト参照の一種ですが、そのオブジェクトの削除が可能です。図8-2に示すように、次のように変更することによって、A->B->Aという問題を解決できます。

図8-2 弱参照の確立

「図8-2 弱参照の確立」の説明

ここでは、AがBに対する弱参照を持っています。Bに対する参照が弱参照のみになると、Bは自身に対する弱参照をすべてクリアしてから削除されます。この簡単な例では、BはAに対する参照のみを保持していたため、Aの削除もトリガーされます。

弱参照を使用すると、この例よりも複雑な構成が可能になります。ただし、どの参照が弱参照でどの参照が強参照かを規定する規則の採用が必要になります。図8-3に示すツリーを考えてみます。このツリーはA、B、Cの各ノードで構成され、このツリーに対する2つの外部参照XおよびYが存在します。

図8-3 ツリーに対する弱参照と強参照

「図8-3 ツリーに対する弱参照および強参照」の説明

このツリーでは、親(A)が子(BとC)に対して強参照を使用し、子は親に対して弱参照を使用しています。この図の状態であれば、参照Yは、子Bを起点としてツリー上をAに登ってからCに降りるという方法で、ツリー全体をナビゲートできます。ここで、参照XがNULLにリセットされた場合を考えてみます。この場合は、Aが弱参照のみされた状態で残り、自身に対する弱参照はすべてクリアされてから削除されます。Aが削除されると、Cに対する参照がまったく存在しなくなるので、Cも削除されます。この時点で、それまで何のアクションも起こしていない参照Yは、図8-4に示す状態を参照することになります。

図8-4 弱参照の削除によって発生した状態

「図8-4 弱参照の削除によって発生した状態」の説明

これが必ず問題となるわけではありませんが、弱参照の使用では考慮を必要とする状況です。この問題を回避するには、YのホルダーでもAに対する参照を保持することが考えられます。これにより、ツリーが予期せずに解消されないようにします。

使用方法の詳細は、coherence::lang::WeakReference、WeakHandleおよびWeakViewに関するJavadocを参照してください。

8.2.5 仮想コンストラクタ

C++では知られていることですが、作成中のオブジェクトを参照することは危険です。特にコンストラクタではこのような参照は避けてください。それは、コンストラクタの内部ではオブジェクトの初期化が完了していないためです。管理オブジェクトの場合、このようなコンストラクタからのハンドルを作成すると、ほとんどの場合、オブジェクトは作成が完了しないうちに破棄されます。かわりに、オブジェクト・モデルでは仮想コンストラクタがサポートされています。仮想コンストラクタonInitはObjectによって定義し、派生クラスでオーバーライドできます。このメソッドは、作成の完了直後、オブジェクト・モデルの静的createメソッドから新しいオブジェクトが返される直前に、オブジェクト・モデルから自動的にコールされます。onInitメソッドの内部では、この参照を行い、仮想関数のコールや、他のクラスのインスタンスへの新規オブジェクト参照の移譲などを実行しても安全です。onInitから派生したあらゆる実装では、super::onInit()のコールを指定して、親クラスで自身の初期化もできるようにする必要があります。

8.2.6 高度なハンドル・タイプ

すでに説明したHandleとViewのスマート・ポインタのほかに、オブジェクト・モデルには、使用できる専用のバリアントがいくつかあります。ほとんどの場合、これらの専用のスマート・ポインタは、その用途が管理クラスの作成に限定されているため、通常のアプリケーションのコードでは使用されません。

表8-1 Coherence for C++でサポートされている高度なハンドルのタイプ

タイプ

スレッド・セーフ対応

View

ノート

coherence:lang:TypedHandle<T>

いいえ

Tによって異なる

HandleおよびViewの実装。

coherence:lang:BoxHandle<T>

いいえ

Tによって異なる

プリミティブ・タイプから管理オブジェクトを自動的に作成できます。

coherence:lang:TypedHolder<T>

いいえ

可能性あり

HandleまたはViewとして機能できます。コレクションに格納される基本的なタイプです。

coherence:lang:Immutable<T>

いいえ

はい

参照しているオブジェクトがconstであることを保証します。

coherence:lang:WeakHandle<T>

はい

いいえ

参照しているオブジェクトの破棄を防止しません。

coherence:lang:WeakView<T>

はい

はい

参照しているオブジェクトの破棄を防止しません。

coherence:lang:WeakHolder<T>

はい

はい

参照しているオブジェクトの破棄を防止しません。

coherence:lang:MemberHandle<T>

はい

いいえ

包含オブジェクトが持つconstとしての特性を転送します。

coherence:lang:MemberView<T>

はい

はい

スレッド・セーフなView。

coherence:lang:MemberHolder<T>

はい

可能性あり

スレッド・セーフなHandleまたはViewとして機能できます。

coherence:lang:FinalHandle<T>

はい

いいえ

読取り専用のHandleを転送するスレッド・セーフなconst。

coherence:lang:FinalView<T>

はい

はい

スレッド・セーフな読取り専用View。

coherence:lang:FinalHolder<T>

はい

可能性あり

スレッド・セーフな読取り専用のHandleまたはViewとして機能できます。

8.2.7 スレッド・セーフティ

ベースのObjectクラスがスレッド・セーフであっても、その派生クラスの状態は自動的にはスレッド・セーフになりません。より高度なスレッド・セーフティを個々の派生クラスで実現できるかどうかは、個々のクラスの実装にかかっています。オブジェクト・モデルには、スレッド・セーフなコードの作成を支援するいくつかの機能があります。

8.2.7.1 同期および通知

オブジェクト・モデルにあるどのObjectも、同期と通知のポイントとすることができます。オブジェクトを同期し、その内部モニターを取得するには、例8-16に示すように、COH_SYNCHRONIZEDマクロ・コード・ブロックを使用します。

例8-16 COH_SYNCHRONIZEDマクロ・コード・ブロックのサンプル

SomeClass::Handle h = getObjectFromSomewhere();

COH_SYNCHRONIZED (h)
{
// monitor of Object referenced by h has been acquired

if (h->checkSomeState())
{
h->actOnThatState();
}
} // monitor is automatically released

このCOH_SYNCHRONIZEDブロックでは、モニターの取得と解放が実行されます。return、throw、COH_THROW、break、continue、gotoの各文を使用して、このブロックを安全に終了できます。

Objectクラスには、通知に使用するwait()、wait(timed)、notify()、notifyAll()の各メソッドがあります。これらのメソッドをコールするには、目的のObjectのモニターをコール元で取得しておく必要があります。詳細は、「coherence::lang::Object」を参照してください。

読取り/書込みロックも用意されています。詳細は、「coherence::util::ThreadGate」を参照してください。

8.2.7.2 スレッド・セーフなハンドル

管理クラスに対して定義されているHandle、ViewおよびHolderのネストされた型は、意図的にスレッド・セーフになっていません。したがって、1つのハンドルを複数のスレッドで共有することは安全ではありません。ここで説明するスレッド・セーフティはハンドルに関するものであり、ハンドルで参照するオブジェクトに関するものではありません。この点は明確に区別しておくことが重要です。同期処理を追加しなくても、それぞれ異なるスレッドで複数の独立したハンドルから1つの同じオブジェクトを参照すれば安全です。

これらのハンドル・タイプがスレッド・セーフティを備えていないことは、パフォーマンスの最適化の面で大きな利点となります。ハンドルの大半にはスタックが割り当てられるからです。これらのスタック割当てハンドルへの参照を複数のスレッドで共有しないかぎり、スレッド・セーフティに関する問題が発生することはありません。

1つのハンドルが複数のスレッドで共有される可能性がある場合は、スレッド・セーフなハンドルが必要になります。次はその典型的な例です。

- グローバル・ハンドル - 標準のハンドル・タイプをグローバル変数や静的変数として使用することは安全ではありません。

- 管理されていない複数スレッド・アプリケーション・コード - 複数のスレッドで共有される可能性のあるデータ構造内で標準のハンドルを使用することは安全ではありません。

- ハンドルをデータ・メンバーとして持つ管理クラス - 管理クラスのどのインスタンスであっても、複数のスレッドで共有される可能性を想定しておく必要があります。したがって、標準のハンドルをデータ・メンバーとして使用することは安全ではありません。すべての管理クラスが必ずしも複数のスレッドで共有されるわけではありませんが、明示的に管理できないコードにインスタンスを渡した場合(キャッシュに置いた場合など)、そのオブジェクトが他のスレッドからは隠蔽されるとはかぎりません。

このような場合は、標準ハンドルではなく、スレッド・セーフなハンドルを使用する必要があります。オブジェクト・モデルには、次のスレッド・セーフなハンドルが用意されています。

- coherence::lang::MemberHandle<T>: T::Handleのスレッド・セーフ・バージョン

- coherence::lang::MemberView<T>: T::Viewのスレッド・セーフ・バージョン

- coherence::lang::MemberHolder<T>: T::Holderのスレッド・セーフ・バージョン

- coherence::lang::FinalHandle<T>: T::Handleのスレッド・セーフ・バージョン

- coherence::lang::FinalView<T>: T::Viewのスレッド・セーフ・バージョン

- coherence::lang::FinalHolder<T>: T::Holderのスレッド・セーフ・バージョン

- coherence::lang::WeakHandle<T>: Tへのスレッド・セーフな弱参照ハンドル

- coherence::lang::WeakView<T>: Tへのスレッド・セーフな弱参照ビュー

- coherence::lang::WeakHolder<T>: スレッド・セーフな弱参照T::Holder

これらのハンドル・タイプは、同期処理を追加しなくても、複数のスレッドからの読取りと書込みが可能です。これらは主に他の管理クラスのデータ・メンバーとして使用することを目的としたもので、各インスタンスにはガーディアン管理Objectへの参照を指定します。ガーディアンのスレッド・セーフな内部アトミック状態を使用して、ハンドルのスレッド・セーフティを実現します。これらのハンドル・タイプを使用するとき、1つのコード・ブロックの中でそのハンドルへのアクセスが継続的に発生する場合には、通常のスタックに基づくハンドルに読み取ることをお薦めします。標準のスタックに基づくハンドルへのこの割当てはスレッド・セーフであり、割当ての完了後は、そのスタックに基づくハンドルを基本的に自由に間接参照できるようになります。スレッド・セーフ・ハンドルを初期化するときは、ガーディアンObjectへの参照を1番目のパラメータとして指定する必要があります。この参照は、包含オブジェクトに対してself()をコールすることで得られます。

この簡単な例を例8-17に示します。

例8-17 スレッド・セーフ・ハンドル

class Employee
: public class_spec<Employee>
{
friend class factory<Employee>;

protected:
Employee(String::View vsName, int32_t nId)
: super(), m_vsName(self(), vsName), m_nId(nId)
{
}

public:
String::View getName() const
{
return m_vsName; // read is automatically thread-safe
}

void setName(String::View vsName)
{
m_vsName = vsName; // write is automatically thread-safe
}

int32_t getId() const
{
return m_nId;
}

private:
MemberView<String>    m_vsName;
const int32_t         m_nId;
};

この同じ基本的な手法は、非管理クラスにも適用できます。非管理クラスはcoherence::lang::Objectを拡張したものではないので、スレッド・セーフなハンドルのガーディアンとしては使用できません。これ以外のObjectをガーディアンとして使用することは可能です。ただし、ガーディアンObjectの存続時間を、保護対象のスレッド・セーフなハンドルの存続時間よりも長くなるよう設定する必要があります。他のオブジェクトをガーディアンとして使用する場合、例8-18に示されているように、System::common()をコールしてcoherence::lang::Systemからランダムな永続的ガーディアンを取得します。

例8-18 非管理クラスとしてのスレッド・セーフ・ハンドル

class Employee
{
public:
Employee(String::View vsName, int32_t nId)
: m_vsName(System::common(), vsName), m_nId(nId)
{
}

public:
String::View getName() const
{
return m_vsName;
}

void setName(String::View vsName)
{
m_vsName = vsName;
}

int32_t getId() const
{
return m_nId;
}

private:
MemberView<String> m_vsName;
const int32_t m_nId;
};

管理クラスを作成する際に、self()、System::common()の順にコールしてガーディアンを取得することをお薦めします。

注意:

まれな状況として、mutableキーワードを使用してこれらのハンドルのいずれかを宣言している場合は、コンストラクションの際にfMutableをtrueに設定してそのことを通知する必要があります。

スレッド・セーフなハンドルも同様にクラス共有ではないデータで使用できます。たとえば、次のグローバル・ハンドルです。

MemberView<NamedCache> MY_CACHE(System::common());

int main(int argc, char** argv)
{
MY_CACHE = CacheFactory::getCache(argv[0]);
}

8.2.7.3 エスケープ分析

オブジェクト・モデルは、エスケープ分析に基づく最適化の機能を備えています。エスケープ分析は、管理オブジェクトを認識できるスレッドが1つのみである状態を自動的に特定し、特定した場合には不要な同期を排除した最適化を実行するために使用します。非エスケープ・オブジェクトに対して、次の操作タイプを最適化できます。

- 参照カウントの更新

- COH_SYNCHRONIZEDの取得と解放

- スレッド・セーフなハンドルの読取りと書込み

- 不変オブジェクトからのスレッド・セーフなハンドルの読取り

エスケープ分析は自動的に実行されますが、オブジェクト・モデルの使用ルールに従っているかぎり安全です。取得したスレッド・セーフなハンドルを使用せずに複数のスレッド間で管理オブジェクトを渡すのは、明らかに安全ではない操作です。外部の機能を使用して管理オブジェクトを渡すと、エスケープ分析でエスケープ状態を特定できないため、メモリー破損やその他のランタイム・エラーの原因となります。

8.2.7.3.1 共有ハンドル

管理クラス・タイプごとに、Handle、ViewおよびHolderのネストした定義があります。これらのハンドルは、Coherence APIやアプリケーション・コードで広く使用されています。これらは、管理オブジェクトへのスタックに基づく参照として使用することを目的としたものです。複数のスレッドへの公開は意図されていません。つまり、複数のスレッドで1つのハンドルを共有しないようにする必要があります。ただし、複数のスレッドから管理オブジェクトを参照することは、独立したHandleを使用するか、スレッド・セーフなMemberHandle/View/Holderを使用しているかぎり安全です。

重要な点として、管理オブジェクトへのグローバル・ハンドルは共有される可能性を除外できないため、前述のようにスレッド・セーフにしておく必要があります。グローバル・ハンドルをスレッド・セーフにしておかない場合、エスケープ・オブジェクトが適切に識別されないため、メモリーの破損が発生する可能性があります。

リリース3.4では、このようなスレッド・セーフではないハンドルであっても、外部の同期機能を使用するか、そのハンドルが読取り専用であれば、複数のスレッドで共有できました。リリース3.5以降では、この機能はサポートされていません。これらのハンドルは、読取り専用モードや外部の同期機能で使用しても、スレッド・セーフではありません。これは、1つのハンドルを別のハンドルに割り当てるという、日常的に発生する操作にかかるコストを大幅に削減するために、実装が根本的に変更されたためです。リリース3.4の方式でハンドルを使用するコードは、スレッド・セーフなハンドルを使用するように更新する必要があります。詳細は、「スレッド・セーフなハンドル」を参照してください。

8.2.7.3.2 constの正確性

Coherenceの様々な機能の中でも特にエスケープ分析では、オブジェクトについて計算した不変性を活用し、データ・メンバーの状態変更がこれからも起こり得るかどうかを判断します。つまり、オブジェクトがViewから参照されるのみであれば、そのデータ・メンバーにはこれ以上の更新が発生しないと見なされます。C++言語には、このconstのみに対するアクセスをバイパスし、constメソッドからのミューテーションを可能にする機能がいくつか用意されています。データ・メンバーの宣言での可変キーワードの使用やキャストによるconst性の破棄などがこの例です。より最適な解決策であり、オブジェクト・モデルでサポートされている手法は可変キーワードです。Coherenceのオブジェクト・モデルでは、スレッド・セーフなデータ・メンバーのハンドルを可変として宣言した場合は、その情報をそのデータ・メンバーに通知する必要があります。スレッド・セーフなすべてのデータ・メンバーは、オプションの3番目のパラメータとしてfMutableをサポートしています。可変キーワードを使用してデータ・メンバーを宣言している場合は、このパラメータをtrueに設定する必要があります。これにより、データ・メンバーの包含オブジェクトがViewを使用して参照されるのみであっても、そのデータ・メンバーをconstとは見なさないようにエスケープ分析ルーチンに通知できます。キャストによって管理オブジェクトのconst性を破棄する方法はサポートされていません。また、オブジェクトの状態の変更が発生しないという判断がオブジェクト・モデルでなされている場合、この方法ではランタイム・エラーが発生することがあります。

8.2.7.4 スレッドローカル・アロケータ

Coherence for C++は、APIで多用される動的割当てのパフォーマンス向上のためにスレッドローカル・アロケータを備えています。デフォルトでは、スレッドごとに最大64KBの再利用可能メモリー・ブロックのプールがあり、このプールは、動的なオブジェクト割当てのほとんどに対応しています。次のシステム・プロパティを使用すると、このプールを構成できます。

- tangosol.coherence.slot.size: プールからの割当ての対象と見なすオブジェクトの最大サイズを制御します。デフォルト値は128バイトです。このサイズを超えるオブジェクトの場合は、システムのmallocルーチンをコールして所要のメモリーを取得します。

- tangosol.coherence.slot.count: 各スレッドにおける割当てを処理するスロットの数を制御します。デフォルト値は512スロットです。利用できるスロットが存在しない場合、割当てはmallocにフォール・バックします。

- tangosol.coherence.slot.refill: プールへの補充を促すトリガーをスロットで取得しない比率を制御します。デフォルト値である10,000は、10,000のプールのうちの1つにはプールの補充に使用できる割当てを適用しないことを示しています。

プールに対するこのアロケータは、そのサイズまたは個数を0に設定することで無効にできます。

8.3 診断およびトラブルシューティング

この項では、オブジェクト・モデルを利用するアプリケーションで発生した問題の診断に役立つ情報について説明します。

8.3.1 スレッド・ダンプ

診断とトラブルシューティングのためにスレッドのダンプを利用することが可能です。このスレッドのダンプにはスタック・トレースも含まれます。スレッドのダンプを生成するには、Windowsの場合は[Ctrl]キーを押しながら[Break]キーを押し、UNIXの場合は[Ctrl]キーを押しながら[\]キーを押します。例8-19は、スレッドのダンプのサンプルを示しています。

例8-19 スレッドのダンプのサンプル

Thread dump Oracle Coherence for C++ v3.4b397 (Pre-release) (Apple Mac OS X x86 debug) pid=0xf853; spanning 190ms

"main" tid=0x101790 runnable: <native>
at coherence::lang::Object::wait(long long) const
at coherence::lang::Thread::dumpStacks(std::ostream&, long long)
at main
at start

"coherence::util::logging::Logger" tid=0x127eb0 runnable: Daemon{State=DAEMON_RUNNING, Notification=false,
StartTimeStamp=1216390067197, WaitTime=0, ThreadName=coherence::util::logging::Logger}
at coherence::lang::Object::wait(long long) const
at coherence::component::util::Daemon::onWait()
at coherence::component::util::Daemon::run()
at coherence::lang::Thread::run()

8.3.2 メモリー・リーク検出

管理されているオブジェクト・モデルの参照カウントはメモリー・リークの防止に効果的ですが、それでもメモリー・リークが発生する可能性はあります。この発生要因としてよく見られるものに、循環オブジェクト・グラフがあります。オブジェクト・モデルではヒープ分析がサポートされています。これは、システムに存在するアクティブなオブジェクトの数を追跡することで、リークが発生しているかどうかの識別を容易にする機能です。これは、時間の経過に応じてオブジェクトの数を比較し、その数が一貫して増加しているかどうかを検出する簡単な方法です。この数が増加していると、リークが発生している可能性があります。リークの可能性が検出された場合は、その発生源がどの型のオブジェクトであるかについて得られた統計により、ヒープ・アナライザを使用してリークを追跡できます。

Coherenceには、プラガブルなcoherence::lang::HeapAnalyzerインタフェースが用意されています。HeapAnalyzerの実装は、tangosol.coherence.heap.analyzerシステム・プロパティを使用して指定できます。このプロパティは、次の値に設定できます。

- none: ヒープ分析を実行しません。これがデフォルトの設定です。

- object: coherence::lang::ObjectCountHeapAnalyzerを使用します。この指定では、システムに存在するアクティブなオブジェクトの数のみに基づいて、簡単なヒープ分析を実行します。

- class: coherence::lang::ClassBasedHeapAnalyzerを使用します。この指定では、クラス・レベルでのヒープ分析を実行します。つまり、アクティブなオブジェクトの数とそれに伴うバイト・レベルの使用量を、クラスごとに追跡します。

- alloc: coherence::lang::ClassBasedHeapAnalyzerを特殊化したもので、クラス・レベルの割当て数を追加で追跡します。

- custom: 独自の分析ルーチンを定義できます。SystemClassLoaderに登録済のクラスの名前を指定します。

Windowsでは[Ctrl]キーを押しながら[Break]キーを押し、UNIXでは[Ctrl]キーを押しながら[\]キーを押すと、ヒープ情報が返されます。

例8-20は、クラス・ベースのアナライザで返されたヒープ分析情報の例です。ここでは、Mapに新しいエントリを挿入したことで得られたヒープ分析の差分が返されます。

例8-20 ヒープ・アナライザから返されたデータ

Space           Count           Class
44 B            1               coherence::lang::Integer32
70 B            1               coherence::lang::String
132 B           1               coherence::util::SafeHashMap::Entry

Total: 246 B, 3 objects, 3 classes

8.3.3 メモリー破損の検出

メモリー破損を防止するためにオブジェクト・モデルで実行する機能はすべて、破損を引き起こす可能性のある非管理コードで使用することが普通です。このために、オブジェクト・モデルではメモリー破損の検出がサポートされています。メモリー破損の検出が有効になっていると、オブジェクト・モデルのメモリー・アロケータによって、構成可能なパッド・バイト数で、各オブジェクトへの割当ての先頭と末尾がパディングされます。このパディングは、パッドが変更されていないことを後で検証できるようなパターンでエンコードされています。メモリー破損が発生し、パッドが影響を受けると、以降の検証でこの破損が検出されます。検証は、オブジェクトが破棄されたときに実行されます。

Coherence C++ APIのデバッグ・バージョンでは、2×ワード・サイズの大きさを持つパッドをオブジェクトへの割当ての両側に置くパディング機能が、デフォルトで有効になっています。32ビットのビルドでは、オブジェクト当たり16バイトが追加されます。パディングのサイズを大きくすると、破損によってパッドが影響を受ける可能性が高くなるため、破損を検出できる確率も高くなります。

パッドの大きさはtangosol.coherence.heap.paddingシステム・プロパティを使用して構成できます。このプロパティは、パッドの前後に置くバイト数に設定できます。このシステム・プロパティをゼロ以外の値に設定すると、破損の検出機能が有効になり、リリース・ビルドでも利用できるようになります。

例8-21は、メモリー破損検出のインスタンスから得られた結果を示しています。

例8-21 メモリー破損検出の実行結果

Error during ~MemberHolder: coherence::lang::IllegalStateException: memory corruption detected in 5B post-padding at offset 4 of memory allocated at 0x132095

8.4 アプリケーション・ランチャ - Sanka

Coherenceでは、共有ライブラリに埋め込まれている実行可能ファイル・クラスを起動するアプリケーション・ランチャを使用します。このランチャによって、ユーティリティやテスト用実行可能ファイルを共有ライブラリに格納できるので、スタンドアロンの実行可能ファイルのバイナリを別途出荷する必要がありません。

8.4.1 コマンドラインの構文

sankaというランチャは、ロードする共有ライブラリの名前と実行するクラスの完全修飾名を指定する点で動作がjavaに似ています。

ge: sanka [-options] <native class> [args...]

available options include:
-l <native library list>  dynamic libraries to load, separated by : or ;
-D<property>=<value>      set a system property
-version                  print the Coherence version
-?                        print this help message
<native class>            the fully qualified class. For example,
coherence::net::CacheFactory

指定するライブラリは、オペレーティング・システムのライブラリ・パス(PATH, LD_LIBRARY_PATH, DYLD_LIBRARY_PATH)からアクセス可能であるか、その場所が絶対パスまたは相対パスで指定可能であることが必要です。ライブラリ名は、その動作を表す接頭辞や接尾辞を省略して指定してもかまいません。たとえば、UNIXのlibfoo.soやWindowsのfoo.dllを単にfooと指定できます。アプリケーションのリンク先となっているCoherence共有ライブラリにも、同様にシステムのライブラリ・パスからアクセスできる必要があります。

8.4.2 組込み実行可能ファイル

Coherenceの共有ライブラリには、次のユーティリティ実行可能ファイル・クラスがあります。

- coherence::net::CacheFactory: Coherence C++コンソールを実行します。

- coherence::lang::SystemClassLoader: 登録済の管理クラスを出力します。

- coherence::io::pof::SystemPofContext: 登録済のPOF型を出力します。

このうち、最後の2つの実行可能ファイルでは検査対象とする共有ライブラリを指定することもできます。その場合は、すべてのライブラリではなく、指定したライブラリに存在する登録が出力されます。

注意:

これまでにサンプルとして出荷されていたコンソールは、組込み実行可能ファイル・クラスとして出荷されるようになりました。

8.4.3 カスタム実行可能ファイル・クラスのサンプル

当然、これまでと同様に、従来のC++の手法でグローバルなmain関数を使用してアプリケーションを実行可能ファイルにすることができます。また必要に応じて、Sankaを使用して独自のクラスの実行可能ファイルを作成することもできます。実行可能ファイル・クラスの簡単な例を次に示します。

#include "coherence/lang.ns"

COH_OPEN_NAMESPACE2(my,test)

using namespace coherence::lang;

class Echo
: public class_spec<Echo>
{
friend class factory<Echo>;

public:
static void main(ObjectArray::View vasArg)
{
for (size32_t i = 0, c = vasArg->length; i < c; ++i)
{
std::cout << vasArg[i] << std::endl;
}
}
};
COH_REGISTER_EXECUTABLE_CLASS(Echo); // must appear in .cpp

COH_CLOSE_NAMESPACE2

この例のように、指定のクラスはExecutableClassとして登録しておく必要があり、mainメソッドは次のシグネチャに一致している必要があります。

static void main(ObjectArray::View)

指定するObjectArrayパラメータは、コマンドライン上で実行可能ファイル・クラス名に続く引数に対応するString::Viewオブジェクトの配列です。

libecho.soやecho.dllなどの共有ライブラリにリンクすると、次のようにEchoクラスを実行できます。

> sanka -l echo my::test::Echo Hello World
Hello
World

9 Coherence for C++クライアントAPIの使用

この章では、Coherence for C++ APIについて説明します。このAPIを使用すると、C++アプリケーションで、Coherenceクラスタ外部からCoherenceクラスタ・サービスにアクセスできます。

Coherence for C++ APIのドキュメントは2つの場所にあります。1つはOracle Coherence C++ APIリファレンスで、もう1つはCoherence for C++のdocディレクトリです。

この章には次の項が含まれます:

- CacheFactory

- NamedCache

- QueryMap

- ObservableMap

- InvocableMap

- Filter

- 値エクストラクタ

- 入力プロセッサ

- エントリ・アグリゲータ

9.1 CacheFactory

CacheFactoryは、NamedCacheのインスタンスを取得および解放する、次の静的メソッドを提供します。

- NamedCache::Handle getCache(String::View vsName): 指定の名前を持ち、リモートCoherenceクラスタで稼働しているNamedCacheに対応するNamedCache実装を取得します。

- void releaseCache(NamedCache::Handle hCache): キャッシュの指定のインスタンスに関連付けられているローカル・リソースをすべて解放します。解放したキャッシュは使用できなくなります。ただし、そのキャッシュの内容は影響を受けません。

- void destroyCache(NamedCache::Handle hCache): Coherenceクラスタ全体にある指定のキャッシュを破棄します。

9.2 NamedCache

NamedCacheは、クラスタのメンバー間で共有しているリソースのマップです。NamedCacheは、キャッシュおよびサービスの名前の取得とキャッシュの解放または破棄に使用する、次のメソッドを提供します。

- String::View getCacheName(): キャッシュの名前をStringとして返します。

- CacheService::Handle getCacheService(): このNamedCacheが属するCacheServiceへのハンドルを返します。

- bool isActive(): このNamedCacheがアクティブかどうかを指定します。

- void release(): NamedCacheのこのインスタンスに関連付けられているローカル・リソースを解放します。リソースを解放したキャッシュは使用できなくなりますが、その内容は影響を受けません。

- void destroy(): NamedCacheのこのインスタンスを解放し、破棄します。

NamedCacheインタフェースは、QueryMap、InvocableMap、ConcurrentMap、CacheMap、ObservableMapの各インタフェースの拡張でもあります。

9.3 QueryMap

QueryMapは、Mapクラスに問合せ機能を追加して拡張したものと考えることができます。この機能により、様々なフィルタを使用してキャッシュを問い合せることができます。フィルタについては、「Filter」で説明しています。

- Set::View keySet(Filter::View vFilter): このマップにあるキーのうち、フィルタで指定した基準を満足するエントリを対象とした一連のキーを返します。

- Set::View entrySet(Filter::View vFilter): このマップにあるエントリのうち、フィルタで指定した基準を満足する一連のエントリを返します。返されたセットにある各要素は、Map::Entryオブジェクトです。

- Set::View entrySet(Filter::View vFilter, Comparator::View vComparator): このマップにあるエントリのうち、フィルタで指定した基準を満足する一連のエントリを返します。返されたセットにある各要素は、Map::Entryオブジェクトです。このentrySetを使用すると、指定のComparatorまたは自然の順番でソートされたエントリ値に基づいて、イテレータがこのセットを昇順で確認していることがより確実となります。

さらに、QueryMapクラスには、索引の追加機能と削除機能があります。索引を使用すると、キャッシュに格納されている値とそれに対応するキーが関連付けられます。また、keySetメソッドとentrySetメソッドのパフォーマンスが大幅に向上します。

- void addIndex(ValueExtractor::View vExtractor, boolean_t fOrdered, Comparator::View vComparator): このQueryMapに索引を追加します。索引により、この索引付きのMapに格納されている値(またはそれらの値の属性)と、同じMapの中でそれらの値に対応するキーを関連付けることができ、keySetメソッドとentrySetメソッドのパフォーマンスが向上します。

- void removeIndex(ValueExtractor::View vExtractor): このQueryMapから索引を削除します。

問合せの詳細は、「キャッシュの問合せ(C++)」を参照してください。また、「単純な問合せの実行」にあるC++の例も参照してください。

9.4 ObservableMap

ObservableMapは、キャッシュの変更をリスニングする機能をアプリケーションに提供します。ObservableMapを実装したアプリケーションでは、キーとフィルタのリスナーを追加して、あらゆるキャッシュで発生したイベントを受信できます。これは、そのキャッシュがローカル、パーティション、ニア、レプリケーションのいずれであっても可能であり、またリードスルー、ライトスルー、ライトビハインド、オーバーフロー、ディスク記憶域などを使用しているかどうかに関係なく可能です。ObservableMapには、これらのリスナーを削除するメソッドもあります。

- void addKeyListener(MapListener::Handle hListener, Object::View vKey, bool fLite): 特定のキーのマップ・リスナーを追加します。

- void removeKeyListener(MapListener::Handle hListener, Object::View vKey): 特定のキーに関するイベントに以前サインアップしたマップ・リスナーを削除します。

- void addFilterListener(MapListener::Handle hListener, Filter::View vFilter = NULL, bool fLite = false): フィルタによる評価に基づいてイベントを受信するマップ・リスナーを追加します。

- void removeFilterListener(MapListener::Handle hListener, Filter::View vFilter = NULL): フィルタによる評価に基づいてイベントに以前サインアップしたマップ・リスナーを削除します。

「すべてのイベントのサインアップ」にあるC++の例を参照してください。

9.5 InvocableMap

InvocableMapは、エントリ別処理と集計操作の両方を起動できるキャッシュです。キャッシュの内容に対する操作は、キャッシュによって(したがって、特定の領域に制限されたキャッシュの内容の中で)実行できます。このメソッドは処理を特定の領域に制限できるため、分散環境で特に効率的です。つまり、キャッシュの内容に対する処理を、その処理の対象となるエントリを管理している場所に移動できます。プロセッサとアグリゲータの詳細は、「入力プロセッサ」および「エントリ・アグリゲータ」を参照してください。

- Object::Holder invoke(Object::View vKey, EntryProcessor::Handle hAgent): 渡されたキーで指定されたエントリ(Entry)を対象として、渡されたプロセッサ(EntryProcessor)を起動し、その起動の結果を返します。

- Map::View invokeAll(Collection::View vCollKeys, EntryProcessor::Handle hAgent): 渡されたキーで指定された複数のエントリ(Entryオブジェクト)のそれぞれを対象として、渡されたプロセッサ(EntryProcessor)を起動し、それぞれの起動の結果を返します。

- Map::View invokeAll(Filter::View vFilter, EntryProcessor::Handle hAgent): 指定したフィルタで選択された複数のエントリ(Entryオブジェクト)のそれぞれを対象として、渡されたプロセッサ(EntryProcessor)を起動し、それぞれの起動の結果を返します。

- Object::Holder aggregate(Collection::View vCollKeys, EntryAggregator::Handle hAgent): 渡されたキーで指定されたエントリを対象として集計操作を実行します。

- Object::Holder aggregate(Filter::View vFilter, EntryAggregator::Handle hAgent): 指定したフィルタで選択されたエントリを対象として集計操作を実行します。

9.6 Filter

Filter は、結果をフィルタ処理し、指定の基準に一致するオブジェクトのみを返す機能を提供します。すべてのフィルタではFilterを実装する必要があります。多くの場合、フィルタをQueryMap APIとともに使用して、指定の基準に一致するエントリをキャッシュに問い合せます。「QueryMap」も参照。

- bool evaluate(Object::View v): 指定のオブジェクトにテストを適用し、テストに合格した場合はtrue、不合格の場合はfalseを返します。

Coherence for C++では、coherence::util::filterネームスペースに、実用的なFilter実装が数多く用意されています。使用頻度が高いフィルタを次にいくつか示します。

- EqualsFilterは、等価性のテストに使用します。オブジェクトが5に等しいことをテストするEqualsFilterを作成するメソッドは次のとおりです。

例9-1 EqualsFilterメソッドの使用方法

EqualsFilter::View vEqualsFilter = EqualsFilter::create(IdentityExtractor::getInstance(), Integer32::valueOf(5));

- GreaterEqualsFilterは、「以上」条件のテストに使用します。オブジェクトの値が55以上であることをテストするGreaterEqualsFilterを作成するメソッドは次のとおりです。

例9-2 GreaterEqualsFilterメソッドの使用方法

GreaterEqualsFilter::View vGreaterEqualsFilter = GreaterEqualsFilter::create(IdentityExtractor::getInstance(), Integer32::valueOf(55));

- LikeFilterは、パターンの照合に使用します。文字列で表現したオブジェクトの先頭がBelgであることをテストするLikeFilterを作成するメソッドは次のとおりです。

例9-3 LikeFilterメソッドの使用方法

LikeFilter::View vLikeFilter = LikeFilter::create(IdentityExtractor::getInstance(), "Belg%");

フィルタの中には、2つを組み合せることで複合条件を作成できるものがあります。

- AndFilterは、2つのフィルタを組み合せてAND条件を作成します。オブジェクトの値が10より大きく20より小さいことをテストするAndFilterを作成するメソッドは次のとおりです。

例9-4 AndFilterメソッドの使用方法

AndFilter::View vAndFilter = AndFilter::create(
GreaterFilter::create(IdentityExtractor::getInstance(), Integer32::valueOf(10)),
LessFilter::create(IdentityExtractor::getInstance(), Integer32::valueOf(20)));

- OrFilterは、2つのフィルタを組み合せてOR条件を作成します。オブジェクトの値が10より小さいか、または20より大きいことをテストするOrFilterを作成するメソッドは次のとおりです。

例9-5 OrFilterメソッドの使用方法

OrFilter::View vOrFilter = OrFilter::create(
LessFilter::create(IdentityExtractor::getInstance(), Integer32::valueOf(10)),
GreaterFilter::create(IdentityExtractor::getInstance(), Integer32::valueOf(20)));

9.7 値エクストラクタ

値 エクストラクタ は、オブジェクトから値を抽出し、その抽出を識別する情報を提供します。すべてのエクストラクタではValueExtractorを実装する必要があります。

注意:

実用的なすべてのエクストラクタ実装では、オブジェクトのシリアル化可能な状態のみに基づくようにhashCode関数とequals関数を明示的に実装することも必要です。

- Object::Holder extract(Object::Holder ohTarget): 渡されたオブジェクトから値を抽出します。

- bool equals(Object::View v): ValueExtractorと別のオブジェクトを比較し、両方が等価かどうかを判断します。2つのValueExtractorオブジェクトであるve1とve2は、vのあらゆる値について、ve1->extract(v)とve2->extract(v)が等しい場合にのみ、等価であると見なされます。

- size32_t hashCode(): 一般的なObject#hashCode()の規定に従って、ValueExtractorオブジェクトのハッシュ値を決定します。

Coherence for C++には次のエクストラクタがあります。

- ChainedExtractor: エクストラクタの配列に基づく複合的なValueExtractor実装です。配列内のエクストラクタは左から右に順次適用され、前のエクストラクタの結果が次のエクストラクタのターゲット・オブジェクトとなります。

- ComparisonValueExtractor: 同じターゲットから抽出した2つの値の比較結果を返します。

- IdentityExtractor: 渡された値から何も抽出せず、その値そのものを返す単純な実装です。

- KeyExtractor: 値ではなく主要なオブジェクトに対して問合せを実行する必要があることを示す、特殊な目的の実装です。

- MultiExtractor: エクストラクタの配列に基づく複合的なValueExtractor実装です。配列内のエクストラタはすべて、同じターゲット・オブジェクトに適用され、抽出した値のリストが抽出結果となります。

- ReflectionExtractor: 指定したオブジェクトのプロパティから値を抽出します。

「問合せの概念の理解」にあるC++の例を参照してください。

9.8 入力プロセッサ

入力プロセッサは、キャッシュ内のエントリ・オブジェクトに対して作動するエージェントです。すべての入力プロセッサではEntryProcessorを実装する必要があります。

- Object::Holder process(InvocableMap::Entry::Handle hEntry): 指定したエントリを処理します。

- Map::View processAll(Set::View vSetEntries): エントリのコレクションを処理します。

Coherence for C++では、coherence::util::processorネームスペースに、EntryProcessor実装がいくつか用意されています。

Coherence Javaディストリビューションの一部であるC++の例を参照してください。

9.9 エントリ・アグリゲータ

エントリ・アグリゲータは、InvocableMapにあるエントリの一部のサブセットに対して実行し、集計結果を得るように指定できる処理を表します。集計の一般的な例として、最小、最大、合計、平均などの関数があります。ただし、集計の概念は、エントリのグループを評価して1つの答えを算出する必要のある任意のプロセスに適用されます。集計は、分散環境などで並列に実行する機能を明示的に備えています。

すべてのアグリゲータではEntryAggregatorインタフェースを実装する必要があります。

- Object::Holder aggregate(Collection::View vCollKeys): エントリのコレクションを処理して集計結果を生成します。

Coherence for C++では、coherence::util::aggregatorネームスペースに、EntryAggregator実装がいくつか用意されています。

注意:

キャッシュした値オブジェクト同様、Filter、ValueExtractor、EntryProcessorおよびEntryAggregatorのすべてのカスタム実装クラスは、C++アプリケーションのPOFコンテキストおよびクライアントが接続されているクラスタ側ノードのPOFコンテキストに正しく登録する必要があります。したがって、カスタムのC++型の対応するJava実装を、クラスタ側ノードで作成、コンパイルおよびデプロイする必要があります。このようなカスタム型を実際に実行するのは、C++の実装ではなくJavaの実装であることに注意してください。詳細は、第10章「統合オブジェクトの構築(C++)」を参照してください。

10 統合オブジェクトの構築(C++)

この章では、C++クライアント作成時にPortable Object Format (POF)シリアライズ形式を使用する手順を説明します。

注意:

このドキュメントでは、仕様に基づくクラス定義などの高度な概念も含め、CoherenceのC++オブジェクト・モデルに精通していると想定しています。これらのトピックの詳細は、第8章「CoherenceのC++オブジェクト・モデルの使用方法」を参照してください。

この章には次の項が含まれます:

- 統合オブジェクトの構築(C++)の概要

- POFの組込み型

- シリアライズの各オプション

- POFオブジェクト参照の使用方法

- カスタムC++型の登録

- JavaバージョンのC++オブジェクトの実装

- シリアライズのパフォーマンスの理解

- POF注釈を使用したオブジェクトのシリアライズ

10.1 統合オブジェクトの構築(C++)の概要

C++クライアントを有効にしてCoherenceクラスタにC++ベースのオブジェクトを正しく格納するには、POF (Portable Object Format)という、プラットフォームに依存しないシリアライズ形式が必要です。POFを使用すると、値オブジェクトのプラットフォームおよび元の言語と関係ない方法で、値オブジェクトをバイナリ・ストリームにエンコードできます。このストリームは、類似するPOFベースのクラス定義を使用して、別の言語でデシリアライズできます。POFバイナリ・ストリームの詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

Coherence C++ APIにはPOFシリアライズ可能クラスがいくつか用意されていますが、カスタムのデータ型ではこの章で説明するようにシリアライズのサポートが必要です。

10.2 POFの組込み型

次の型はPOFで内部的にサポートされているので、ユーザー側で特別な処理をする必要はありません。

- String

- Integer16 ..Integer64

- Float32、Float64

- プリミティブの配列<>

- ObjectArray

- Boolean

- Octet

- Character16

また、次の一般的なインタフェースを実装するクラスでは自動POFシリアライズが可能です。

- Map

- Collection

- Exception

10.3 シリアライズの各オプション

Coherence C++ APIが備えているシリアライズ形式は1つのみ(POF)ですが、クラスをシリアライズ可能にするAPIは多数用意されています。どのようなアプローチを採用しても、最終的には同じバイナリPOF形式が生成されます。クラスをシリアライズ可能にするには、次のアプローチを利用できます。

- Managed<T>アダプタ・テンプレートを使用して、外部の自由関数シリアライザを追加します。詳細は、「Managed<T>(自由関数シリアライズ)」を参照してください。

- データ・オブジェクトを変更してObjectを拡張し、PortableObjectインタフェースを実装して、オブジェクトで自己シリアライズができるようにします。詳細は、「PortableObject(自己シリアライズ)」を参照してください。

- データ・オブジェクトを変更してObjectを拡張し、PofSerializerクラスを作成して外部シリアライズを実行します。詳細は、「PofSerializer(外部シリアライズ)」を参照してください。

表10-1は、それぞれのアプローチの要件と制限をいくつか示しています。

表10-1 シリアライズの各オプションの要件と制限

アプローチ

データ・オブジェクトのCoherenceヘッダー

Objectからの派生の必要性

constデータ・メンバーのサポート

外部シリアライズ・ルーチン

引数がないコンストラクタの必要性

Managed<T>

いいえ

いいえ

はい

はい

はい

PortableObject

はい

はい

いいえ

いいえ

はい

PofSerializer

はい

はい

はい

はい

いいえ

これらのアプローチにはすべて、次のような共通点があります。

- データ・アイテムをPOFにエンコードできるようにするシリアライズ・ルーチンを実装する必要があります。

- データ・オブジェクトのフィールドを特定するには、数値インデックスを使用します。

- データ・オブジェクト・クラスとシリアライズのメカニズムをCoherenceに登録する必要があります。

- キャッシュ・キーとして使用するデータ・オブジェクトは、等価比較とハッシュをサポートしている必要があります。

10.3.1 Managed<T>(自由関数シリアライズ)

既存のデータ・オブジェクト・クラスのほとんどでは、Managed<T>を使用すると、最も容易にCoherence for C++に統合できます。

非管理クラスがManaged<T>と互換性を持つようにするには、そのクラスに次のような特性があることが必要です。

- パラメータのないコンストラクタ(publicまたはprotected): CustomType::CustomType()

- コピー・コンストラクタ(publicまたはprotected): CustomType::CustomType(const CustomType&)

- 等価比較の演算子: ブール演算子==(const CustomType&, const CustomType&)

- std::ostream出力関数: std::ostream& operator<<(std::ostream&, const CustomType&)

- ハッシュ関数: size_t hash_value(const CustomType&)

次の例は、簡単なAddressクラスを示しています。このクラスは、Coherenceの直接の知識は不要ですが、Managed<T>テンプレートでの使用に適しています。

注意:

見やすさを考慮して、ここではクラス定義の例を宣言の中に記述しています。

例10-1 非管理クラス

#include <iostream>
#include <string>
using namespace std;

class Address
{
public:
Address(const std::string& sCity, const std::string& sState, int nZip)
: m_sCity(sCity), m_sState(sState), m_nZip(nZip) {}

Address(const Address& that) // required by Managed<T>
: m_sCity(that.m_sCity), m_sState(that.m_sState), m_nZip(that.m_nZip) {}

protected:
Address() // required by Managed<T>
: m_nZip(0) {}

public:
std::string  getCity()  const {return m_sCity;}
std::string  getState() const {return m_sState;}
int          getZip()   const {return m_nZip;}

private:
const std::string m_sCity;
const std::string m_sState;
const int         m_nZip;
};

bool operator==(const Address& addra, const Address& addrb) // required by Managed<T>
{
return addra.getZip()   == addrb.getZip() &&
addra.getState() == addrb.getState() &&
addra.getCity()  == addrb.getCity();
}

std::ostream& operator<<(std::ostream& out, const Address& addr) // required by Managed<T>
{
out << addr.getCity() << ", " << addr.getState() << "  " << addr.getZip();
return out;
}

size_t hash_value(const Address& addr) // required by Managed<T>
{
return (size_t) addr.getZip();
}

Managed<T>と組み合せたこの簡単なクラス定義は、真の管理オブジェクトとなり、Coherence C++ APIで使用できるようになります。この定義のみでは、まだシリアライズに対処できません。例10-2では、シリアライズのサポートが追加されています。

例10-2 シリアライズを使用した管理クラス

#include "coherence/io/pof/SystemPofContext.hpp"

#include "Address.hpp"

using namespace coherence::io::pof;

COH_REGISTER_MANAGED_CLASS(1234, Address); // type ID registration—this must
// appear in the .cpp not the .hpp

template<> void serialize<Address>(PofWriter::Handle hOut, const Address& addr)
{
hOut->writeString(0, addr.getCity());
hOut->writeString(1, addr.getState());
hOut->writeInt32 (2, addr.getZip());
}

template<> Address deserialize<Address>(PofReader::Handle hIn)
{
std::string sCity  = hIn->readString(0);
std::string sState = hIn->readString(1);
int         nZip   = hIn->readInt32 (2);
return Address(sCity, sState, nZip);
}

注意:

このシリアライズ・ルーチンでは、Coherenceの知識が必要です。ただし、クラス定義ファイルの中に記述する必要はありません。独立したソース・ファイルに記述してもかまいません。最終的なアプリケーションでそのファイルをリンクすると、ルーチンとして正常に機能します。

例10-3は、前述の例を使用して、AddressクラスのインスタンスをManaged<T>でラップしてManaged<Address>とし、Coherence APIに提供することを示しています。

例10-3 Managed<T>でラップしたクラスのインスタンス

// construct the non-managed version as usual
Address office("Redwood Shores", "CA", 94065);

// the managed version can be initialized from the non-managed version
// the result is a new object, which does not reference the original
Managed<Address>::View vOffice = Managed<Address>::create(office);
String::View           vKey    = "Oracle";

// the managed version is suitable for use with caches
hCache->put(vKey, vAddr);
vOffice = cast<Managed<Address>::View>(hCache->get(vKey));

// the non-managed class's public methods/fields remain accessible
assert(vOffice->getCity()  == office.getCity());
assert(vOffice->getState() == office.getState());
assert(vOffice->getZip()   == office.getZip());

// conversion back to the non-managed type may be performed using the
// non-managed class's copy constructor.
Address officeOut = *vOffice;

10.3.2 PortableObject(自己シリアライズ)

PortableObjectインタフェースは、概念の面から見ると、オブジェクトのシリアライズ方法をそのオブジェクト自身で制御できるようにするjava.io.Externalizableに類似しています。coherence::lang::Objectを拡張したクラスであれば、coherence::io::pof::PortableObjectインタフェースを自由に実装してシリアライズのサポートを追加できます。このクラスはObjectを拡張したものであることが必要で、拡張後のクラスのライフサイクルはこのObjectで規定します。

例10-4では、前述のAddressの例を管理クラスとして書き換え、PortableObjectインタフェースを実装できます。ここでは、このクラスの定義の中でCoherenceオブジェクト・モデル全体を扱うようにしています。たとえば、データ・メンバーに対してstd::stringではなく、coherence::lang::Stringを使用します。

例10-4 PortableObjectを実装する管理クラス

#include "coherence/lang.ns"

#include "coherence/io/pof/PofReader.hpp"
#include "coherence/io/pof/PofWriter.hpp"
#include "coherence/io/pof/PortableObject.hpp"

#include "coherence/io/pof/SystemPofContext.hpp"

using namespace coherence::lang;

using coherence::io::pof::PofReader;
using coherence::io::pof::PofWriter;
using coherence::io::pof::PortableObject;

class Address
: public cloneable_spec<Address,
extends<Object>,
implements<PortableObject> >
{
friend class factory<Address>;

protected: // constructors
Address(String::View vsCity, String::View vsState, int32_t nZip)
: m_vsCity(self(), vsCity), m_vsState(self(), vsState), m_nZip(nZip) {}

Address(const Address& that)
: super(that), m_vsCity(self(), that.m_vsCity), m_vsState(self(),
that.m_vsState), m_nZip(that.m_nZip) {}

Address() // required by PortableObject
: m_vsCity(self()),
m_vsState(self()),
m_nZip(0) {}

public: // Address interface
virtual String::View  getCity()  const {return m_vsCity;}
virtual String::View  getState() const {return m_vsState;}
virtual int32_t       getZip()   const {return m_nZip;}

public: // PortableObject interface    virtual void writeExternal(PofWriter::Handle hOut) const
{
hOut->writeString(0, getCity());
hOut->writeString(1, getState());
hOut->writeInt32 (2, getZip());
}

virtual void readExternal(PofReader::Handle hIn)
{
initialize(m_vsCity, hIn->readString(0));
initialize(m_vsState, hIn->readString(1));
m_nZip    = hIn->readInt32 (2);
}

public: // Objectinterface    virtual bool equals(Object::View that) const
{
if (instanceof<Address::View>(that))
{
Address::View vThat = cast<Address::View>(that);

return getZip() == vThat->getZip() &&
Object::equals(getState(), vThat->getState()) &&
Object::equals(getCity(), vThat->getCity());
}

return false;
}

virtual size32_t hashCode() const
{
return (size32_t) m_nZip;
}

virtual void toStream(std::ostream& out) const
{
out << getCity() << ", " << getState() << "  " << getZip();
}

private:
FinalView<String> m_vsCity;
FinalView<String> m_vsState;
int32_t     m_nZip;
};
COH_REGISTER_PORTABLE_CLASS(1234, Address); // type ID registration—this must
// appear in the .cpp not the .hpp

例10-5は、Addressの管理バリアントを示しています。このバリアントは、Managed<T>アダプタの使用を必要とせず、Coherence APIで直接使用できます。

例10-5 Managed<T>を使用しない管理クラス

Address::View vAddr = Address::create("Redwood Shores", "CA", 94065);
String::View  vKey  = "Oracle";

hCache->put(vKey, vAddr);
Address::View vOffice = cast<Address::View>(hCache->get(vKey));

Coherenceオブジェクト・モデルを利用してデータ・オブジェクトを記述することにしているアプリケーションでは、PortableObjectを使用したシリアライズが最適です。PortableObjectの短所として、constデータ・メンバーのサポートが容易ではないという点があります。これは、コンストラクタの実行後にreadExternalメソッドがコールされ、その時点でconstデータ・メンバーの値を割り当てる必要があるためです。

10.3.3 PofSerializer(外部シリアライズ)

3番目のシリアライズ・オプションも最低レベルのものです。PofSerializerは、自身以外のクラスにシリアライズ・ロジックを提供するクラスです。たとえば、前述の管理Addressクラスの非PortableObjectバージョンをシリアライズできるAddressSerializerを記述します。前述の2つのアプローチでは、これらは明示的に作成していたのではなく、PofSerializerに委任されていた保護の下で自動的に作成されていました。通常は、Managed<T>とPortableObjectのいずれかのアプローチで十分であるため、このアプローチを採用する必要はありません。このアプローチが効果的なのは、constデータ・メンバーを持つ管理オブジェクトを扱う場合です。例10-6では、非PortableObjectバージョンの管理Addressを検討します。

例10-6 非PortableObjectバージョンの管理クラス

#include "coherence/lang.ns"

using namespace coherence::lang;

class Address
: public cloneable_spec<Address> // extends<Object> is implied
{
friend class factory<Address>;

protected: // constructors
Address(String::View vsCity, String::View vsState, int32_t nZip)
: m_vsCity(self(), vsCity), m_vsState(self(), vsState), m_nZip(nZip) {}

Address(const Address& that)
: super(that), m_vsCity(self(), that.getCity()), m_vsState(self(),
that.getState()), m_nZip(that.getZip()) {}

public: // Address interface
virtual String::View  getCity()  const {return m_vsCity;}
virtual String::View  getState() const {return m_vsState;}
virtual int32_t getZip() const {return m_nZip;}

public: // Objectinterface
virtual bool equals(Object::View that) const
{
if (instanceof<Address::View>(that))
{
Address::View vThat = cast<Address::View>(that);

return getZip() == vThat->getZip() &&
Object::equals(getState(), vThat->getState()) &&
Object::equals(getCity(), vThat->getCity());
}

return false;
}

virtual size32_t hashCode() const
{
return (size32_t) m_nZip;
}

virtual void toStream(std::ostream& out) const
{
out << getCity() << ", " << getState() << "  " << getZip();
}

private:
const MemberView<String> m_vsCity;
const MemberView<String> m_vsState;
const int32_t      m_nZip;
};

このバージョンはconstデータ・メンバーを使用しているため、PortableObjectには適していません。例10-7は、Addressインスタンスのシリアライズを担当するものとして登録される外部クラスAddressSerializerを示しています。

例10-7 シリアライズを担当する外部クラス

#include "coherence/lang.ns"

#include "coherence/io/pof/PofReader.hpp"
#include "coherence/io/pof/PofWriter.hpp"
#include "coherence/io/pof/PortableObject.hpp"
#include "coherence/io/pof/PofSerializer.hpp"
#include "coherence/io/pof/SystemPofContext.hpp"

#include "Address.hpp"

using namespace coherence::lang;

using coherence::io::pof::PofReader;
using coherence::io::pof::PofWriter;
using coherence::io::pof::PofSerializer;

class AddressSerializer
: public class_spec<AddressSerializer,
extends<Object>,
implements<PofSerializer> >
{
friend class factory<AddressSerializer>;

protected:
AddressSerializer();

public: // PofSerializer interface    virtual void serialize(PofWriter::Handle hOut, Object::View v) const
{
Address::View vAddr = cast<Address::View>(v);
hOut->writeString(0, vAddr->getCity());
hOut->writeString(1, vAddr->getState());
hOut->writeInt32 (2, vAddr->getZip());
hOut->writeRemainder(NULL);
}

virtual Object::Holder deserialize(PofReader::Handle hIn) const
{
String::View vsCity  = hIn->readString(0);
String::View vsState = hIn->readString(1);
int32_t      nZip    = hIn->readInt32 (2);
hIn->readRemainder();

return Address::create(vsCity, vsState, nZip);
}
};
COH_REGISTER_POF_SERIALIZER(1234, TypedBarrenClass<Address>::create(),AddressSerializer::create()); // This must appear in the .cpp not the .hpp

Addressの使用方法は、次のようにこれまでと同じです。

Address::View vAddr = Address::create("Redwood Shores", "CA", 94065);
String::View  vKey  = "Oracle";

hCache->put(vKey, vAddr);
Address::View vOffice = cast<Address::View>(hCache->get(vKey));

10.4 POFオブジェクト参照の使用方法

POFでは、POFストリーム内で複数回出現するオブジェクトに、オブジェクトのIDや参照の使用がサポートされています。オブジェクトには、IDが付けられ、同じPOFストリーム内で2回目以降に出現するラベルが付いたオブジェクトは、そのIDで参照されます。

参照を使用することで、同じオブジェクトを複数回エンコーディングすることを防ぎ、データサイズを削減できます。一般に、参照を使用するのは、サイズの大きな多数のオブジェクトが複数回生成されるときや、オブジェクトでネストや循環データ構造が使用されるときです。ただし、大量のデータがあり、繰返しが少ないアプリケーションの場合、オブジェクト参照を使用してもオブジェクトのIDや参照の追跡によって生じるオーバーヘッドのために、利点はほとんどありません。

オブジェクト・アイデンティティおよび参照の使用には次の制限があります。

- オブジェクト参照には、ユーザー定義のオブジェクト型のみがサポートされています。

- Evolvableオブジェクトでは、オブジェクト参照はサポートされていません。

- キーでは、オブジェクト参照はサポートされていません。

- 参照をサポートしていないPOFコンテキストによって記述されたオブジェクトは、参照をサポートするPOFコンテキストで読み込むことができません。また、この逆の場合も同様です。

- POFエクストラクタを使用して、オブジェクト・アイデンティティおよび参照を使用するPOFオブジェクトを問い合せることはできません。かわりに、ValueExtractor APIを使用してオブジェクト値を問い合せるか、またはオブジェクト参照を無効にしてください。

この項には、次のトピックが含まれます:

- POFオブジェクト参照の有効化

- 循環構造のオブジェクトやネストされたオブジェクトへのPOFオブジェクトIDの登録

10.4.1 POFオブジェクト参照の有効化

オブジェクト参照は、デフォルトでは無効になっており、POFコンテキストを作成するときにsetReferenceEnabledを使用して有効にする必要があります。例:

SystemPofContext::Handle hCtx = SystemPofContext::getInstance();
hCtx->setReferenceEnabled(true);

10.4.2 循環構造のオブジェクトやネストされたオブジェクトへのPOFオブジェクトIDの登録

循環構造のオブジェクトやネストされたオブジェクトは、オブジェクトの作成時に手動でIDを登録する必要があります。これを行わないと、親を参照する子が、参照マップで親のIDを検出しません。オブジェクトのIDは、PofReader.registerIdentityメソッドを使用し、デシリアライズ・ルーチンでシリアライザから登録できます。

次の例では、循環参照を含んだ2つのオブジェクト(CustomerおよびProduct)と、CustomerオブジェクトのIDを登録するシリアライザ実装を示しています。

Customerオブジェクトの定義は次のとおりです。

class Customer
: public class_spec<Customer,
extends<Object> >
{
friend class factory<Customer>;

protected:
Customer()
: m_vsName(self(), String::null_string),
m_vProduct(self(), NULL)
{
}

Customer(String::View vsName)
: m_vsName(self(), vsName),
m_vProduct(self(), NULL)
{
}

Customer(String::View vsName, Product::View vProduct)
: m_vsName(self(), vsName),
m_vProduct(self(), vProduct)
{
}

public:
String::View getName() const
{
return m_vsName;
}

void setName(String::View vsName)
{
m_vsName = vsName;
}

Product::View getProduct() const
{
return m_vProduct;
}

void setProduct(Product::View vProduct)
{
m_vProduct = vProduct;
}

private:
MemberView<String> m_vsName;
MemberView<Product> m_vProduct;
};

Productオブジェクトの定義は次のとおりです。

class Product
: public class_spec<Product,
extends<Object> >
{
friend class factory<Product>;

protected:
Product()
: m_vCustomer(self(), NULL)
{
}

Product(Customer::View vCustomer)
: m_vCustomer(self(), vCustomer)
{
}

public:
Customer::View getCustomer() const
{
return m_vCustomer;
}

void setCustomer(Customer::View vCustomer)
{
m_vCustomer= vCustomer;
}

private:
MemberView<Customer> m_vCustomer;
};

デシリアライズの間にIDを登録するシリアライザ実装の定義は次のとおりです。

class CustomerSerializer
: public class_spec<CustomerSerializer,
extends<Object>,
implements<PofSerializer> >
{
friend class factory<CustomerSerializer>;

public:
void serialize(PofWriter::Handle hOut, Object::View v) const
{
Customer::View vCustomer = cast<Customer::View>(v);
hOut->writeString(0, vCustomer->getName());
hOut->writeObject(1, vCustomer->getProduct());
hOut->writeRemainder(NULL);
}

Object::Holder deserialize(PofReader::Handle hIn) const
{
String::View vsName = cast<String::View>(hIn->readString(0));
Customer::Holder ohCustomer = Customer::create(vsName);

hIn->registerIdentity(ohCustomer);
ohCustomer->setProduct(cast<Product::View>(hIn->readObject(1)));
hIn->readRemainder();
return ohCustomer;
}
};

10.5 カスタムのC++型の登録

シリアライズ可能にすることに加え、各クラスには数値型のIDを関連付ける必要があります。これらのIDはクラスタ全体で既知の状態になっています。クラスタでは、POFユーザー定義型の構成要素を使用して、IDとクラスとのマッピングを構成します。C++では、IDの登録の形式でクラス定義の中にこのマッピングを埋め込みます。これは、クラスの .cppソース・ファイルに記述します。

この登録の手法は、次のようにシリアライズのアプローチごとに少々異なります。

- COH_REGISTER_MANAGED_CLASS(ID, TYPE): Managed<T>による方法の場合

- COH_REGISTER_PORTABLE_CLASS(ID, TYPE): PortableObjectによる方法の場合

- COH_REGISTER_POF_SERIALIZER(ID, CLASS, SERIALIZER): PofSerializerによる方法の場合

これらの登録の例は、前述の例に記載されています。

注意:

登録を記述するファイルは実装ファイル(.cpp)のみとします。POF構成ファイルは、オブジェクトをシリアライズおよびデシリアライズするノードでのみ必要です。

10.6 JavaバージョンのC++オブジェクトの実装

POFの使用によって、並列のJava実装を必要とせずに、キーおよび値オブジェクトをクラスタ内に格納できます。これは、基本的なgetとputベースの操作を実行する場合に適しています。さらに、PofExtractorおよびPofUpdater APIでシリアライズされたオブジェクトを直接操作することにより、並列のJava実装が特定の状況で必要なくなります。ただし、高度なデータ・グリッド機能を使用する場合は、データ・オブジェクトのシリアライズ表現を保持するのではなく、Javaベースのキャッシュ・サーバーを使用してデータ・オブジェクトと対話できる必要があります。Java実装は、キャッシュ・サーバーに配置される必要があり、オブジェクトと対話し、そのプロパティにアクセスするために使用します。JavaバージョンのPOFでシリアライズ可能にする方法は前述の例とほぼ同じです。詳細は、com.tangosol.io.pof.PortableObjectおよびcom.tangosol.io.pof.PofSerializerを参照してください。これらのAPIは、C++の3つの方法すべてと互換性があります。

並列のJava実装の組込みが必要になる状況

基本的なgetとputの操作よりも高度な多くのデータ・グリッド機能では、オブジェクトがクラスタ内に並列のJava実装を持つことを必要とします。これらの機能は、次のとおりです。

- 問合せ

- フィルタ

- 入力プロセッサとアグリゲータ

- データ・ソースの永続性

キーの関連付けチェックの遅延

キー・クラスは、クラスタ側Java実装を必要としません。これはKeyAssociationを使用してデータのアフィニティを指定している場合でも同様です。キー・クラスは、クライアント側でチェックされ、修飾されたバイナリがクラスタによって作成および使用されます。ただし、キーの関連付けをJavaキー・クラスに依存している既存のクライアント実装は、Javaキー・クラスの使用を強制するためにdefer-key-association-checkパラメータを設定する必要があります。キーの関連付けを使用する既存クライアント・アプリケーションで、クライアント側のキー・バイナリを利用する場合は、getAssociatedKey()実装を既存のJavaクラスから対応するクライアント・クラスに移植する必要があります。

キーの関連付け処理をExtendクライアントによってではなくクラスタ側で実行するには、クライアント側キャッシュの構成で<remote-cache-scheme>要素の<defer-key-association-check>要素をtrueに設定します。例:

<remote-cache-scheme>
...
<defer-key-association-check>true</defer-key-association-check>
</remote-cache-scheme>

注意:

パラメータがtrueに設定されている場合、Javaキー・クラス実装は、キーの関連付けを使用していない場合でも、クラスタに存在する必要があります。

10.7 シリアライズのパフォーマンスの理解

Managed<T>とPortableObjectは、いずれもバックグラウンドでPofSerializerを使用してシリアライズを実行します。これらのアプローチのそれぞれで独自のオーバーヘッドが発生します。たとえば、Managed<T>によるアプローチでは、デシリアライズの過程で、一時バージョンのデータ・オブジェクトが非管理形式で作成されます。PortableObjectの場合は、constデータ・メンバーに対するサポートがないことから、constデータ・メンバーに対して可能な最適化が回避されるために、余分なコストが発生する可能性があります。全体としてはパフォーマンスの差は無視できますが、可能なかぎり最大のパフォーマンス実現を追求する場合は、PofSerializerを直接使用することも検討に値します。

10.8 POF注釈を使用したオブジェクトのシリアライズ

POF注釈は、オブジェクトにシリアライズやデシリアライズ・ルーチンの実装を自動化する方法を提供します。POF注釈は、PofSerializerインタフェースの実装であるPofAnnotationSerializerクラスを使用してシリアライズまたはデシリアライズします。注釈は、Managed<T>アダプタ、PortableObjectインタフェースおよびPofSerializerインタフェースのかわりに使用でき、オブジェクトをシリアライズ可能にするために必要な時間やコードの量を削減します。

この項には、次のトピックが含まれます:

- POFシリアライズでのオブジェクトへの注釈付け

- POF注釈付きオブジェクトの登録

- 自動索引付けの有効化

- カスタム・コーデックの提供

10.8.1 POFシリアライズでのオブジェクトへの注釈付け

クラスとクラスのメソッドがPOFシリアライズ可能であることを示すために利用できる注釈は2つあります。

- Portable - クラスをPOFシリアライズ可能とマークします。注釈は、クラス・レベルのみに使用でき、メンバーを含みません。

- PortableProperty - メソッド・アクセッサをPOFシリアライズ化されたプロパティとしてマークします。注釈が付けられたメソッドは、アクセッサの表記法(get、set、is)に従っている必要があります。メンバーを、POF索引や、シリアライズまたはデシリアライズの前後で実行するカスタム・コーデックの指定に使用できます。索引の値は省略可能で、自動的に割り当てられます。カスタム・コーデックを入力しない場合は、デフォルトのコーデックが使用されます。

次の例は、クラスとメソッドへの注釈付けと、プロパティ索引値の明示的な割当てを示しています。クラスはシステム・クラス・ローダーCOH_REGISTER_CLASSとともに登録する必要があります。

class Person
: public class_spec<Person>
{
friend class factory<Person>;

Public:
String::View getFirstName() const
{
return m_vsFirstName;
}

void setFirstName(String::View vsFirstName)
{
m_vsFirstName = vsFirstName;
}

private: String m_firstName;
MemberView<String> m_vsFirstName;
MemberView<String> m_vsLastName;
int32_t            m_nAge;

public:
static const int32_t FIRST_NAME = 0;
static const int32_t LAST_NAME  = 1;
static const int32_t AGE        = 2;
};

COH_REGISTER_CLASS(TypedClass<Person>::create()
->annotate(Portable::create())
->declare(COH_PROPERTY(Person, FirstName, String::View)
->annotate(PortableProperty::create(Person::FIRST_NAME)))
->declare(COH_PROPERTY(Person, LastName, String::View)
->annotate(PortableProperty::create(Person::LAST_NAME)))
->declare(COH_PROPERTY(Person, Age, BoxHandle<const Integer32>)
->annotate(PortableProperty::create(Person::AGE)))
);

10.8.2 POF注釈付きオブジェクトの登録

POF注釈付きオブジェクトは、COH_REGISTER_POF_ANNOTATED_CLASSマクロを使用してユーザー定義型として登録する必要があります。次の例では、注釈付きPersonオブジェクトのユーザー定義型を登録します。

COH_REGISTER_POF_ANNOTATED_CLASS(1001, Person);

10.8.3 自動索引付けの有効化

POF注釈では、自動索引付けがサポートされており、明示的な索引値の割当てや管理の必要性を軽減されます。PortableProperty注釈を定義していれば、索引値は省略可能です。明示的に索引値を割り当てるプロパティによって、自動索引値が割り当てられることはありません。自動索引のアルゴリズムを表すと、次のようになります。

名前

明示的索引

決定された索引

c

1

1

a

省略

0

b

省略

2

注意:

自動索引では、現在、進化可能なクラスがサポートされていません。

自動索引付けを有効にするには、ユーザー定義型を登録するときにCOH_REGISTER_POF_ANNOTATED_CLASS_AIプリプロセッサを使用します。次の例では、自動索引付けを使用する注釈付きPersonオブジェクトのユーザー定義型を登録します。

COH_REGISTER_POF_ANNOTATED_CLASS_AI(1001, Person);

10.8.4 カスタム・コーデックの提供

コーデックによって、シリアライズまたはデシリアライズの前後でコードを実行できます。コーデックでは、PofWriterおよびPofReaderインタフェースを使用して、移植可能なプロパティをエンコードおよびデコードする方法を定義できます。コーデックは、一般に、デシリアライズ中に消失する可能性がある実用的な実装に使用します。または、オブジェクトをシリアライズする前にPofWriterインタフェースで特定のメソッドを明示的にコールするために使用します。

コーデックを作成するには、Codecインタフェースを実装するクラスを作成します。次の例は、リンクされたリスト型の実用的な実装を定義するコーデックを示しています。

class LinkedListCodec
: public class_spec<LinkedListCodec,
extends<Object>,
implements<Codec> >
{
friend class factory<LinkedListCodec>;

public:
void encode(PofWriter::Handle hOut, int32_t nIndex, Object::View ovValue)
const
{
hOut->writeCollection(nIndex, cast<Collection::View>(ovValue));
}

Object::Holder decode(PofReader::Handle hIn, int32_t nIndex) const
{
LinkedList::Handle hLinkeList = LinkedList::create();
return hIn->readCollection(nIndex, hLinkeList);
}
};
COH_REGISTER_TYPED_CLASS(LinkedListCodec);

コーデックをプロパティに割り当てるには、コーデックをPortableProperty注釈のメンバーとして入力します。コーデックを指定しない場合は、デフォルトのコーデック(DefaultCodec)が使用されます。次の例は、前述のLinkedListCodecコーデックの割当て方法を示しています。

COH_REGISTER_CLASS(TypedClass<Person>::create()
->annotate(Portable::create())
->declare(COH_PROPERTY(Person, FirstName, String::View)
->annotate(PortableProperty::create(Person::FIRST_NAME)))
->declare(COH_PROPERTY(Person, LastName, String::View)
->annotate(PortableProperty::create(Person::LAST_NAME)))
->declare(COH_PROPERTY(Person, Age, BoxHandle<const Integer32>)
->annotate(PortableProperty::create(Person::ALIASES,
SystemClassLoader::getInstance()->loadByType(typeid(LinkedListCodec)) )))
);

11 キャッシュの問合せ(C++)

この章では、C++クライアントからCoherenceキャッシュの問合せを実行する手順を示します。

この章には次の項が含まれます:

- 問合せの機能の概要

- 単純な問合せの実行

- 問合せの概念の理解

- 複数値属性が関係する問合せの実行

- 問合せでの連鎖エクストラクタの使用

- 問合せレコーダの使用

11.1 問合せの機能の概要

Coherenceでは、現在キャッシュされているデータのうち、指定された一連の基準を満たすものに対して、問合せと索引を実行できます。問合せと索引は、Coherence付属のフィルタを採用した単純なものにするか、またはコレクションや配列などの複数値属性に対して実行できます。結果セットは必要に応じてソートできます。問合せは、コミット読取り分離を使用して評価されます。

問合せは、キャッシュされたデータにしか適用されないことに注意してください(CacheLoaderインタフェースを使用して、問合せに適合するデータが追加で取得されることもありません)。このため、問合せが実行される前にデータセット全体をキャッシュにロードする必要があります。データセットが大きすぎて使用可能なメモリーに収まらない場合は、特定のディメンション(日付など)に従ってキャッシュの内容を制限し、問合せの構造に基づいてキャッシュ問合せとデータベース問合せを手動で切り替えることができます。保守性の面から、通常はキャッシュ対応のデータ・アクセス・オブジェクト(DAO)の内部にこの処理を実装するのが最適です。

索引を付けるには、各パーティション・キャッシュ・ノードで属性を抽出できることが必要です。専用のCacheServerインスタンスの場合は、これを実現するために(通常は)アプリケーション・クラスをCacheServerクラスパスにインストールする必要があります。

ローカル・キャッシュおよびレプリケーション・キャッシュについては、索引のないデータに対して問合せがローカルで評価されます。パーティション・キャッシュについては、索引を使用して(使用可能な場合)問合せがクラスタ全体で並列に実行されます。Coherenceにはコストベース・オプティマイザ(CBO)が搭載されています。索引のない属性にアクセスするには、オブジェクトをデシリアライズする必要があります(ただし、他の属性に索引を付けると、評価が必要なオブジェクトを減らすことができます)。

11.2 単純な問合せの実行

キャッシュの内容を問い合せる操作は、例11-1に示すように非常に単純です。

例11-1 キャッシュの内容の問合せ

ValueExtractor::Handle hExtractor = ReflectionExtractor::create("getAge");
Filter::View vFilter = GreaterEqualsFilter::create(hExtractor, Integer32::valueOf(18));

for (Iterator::Handle hIter = hCache->entrySet(vFilter)->iterator(); hIter->hasNext(); )
{
Map::Entry::Handle hEntry  = cast<Map::Entry::Handle>(hIter->next());
Integer32::View    vKey    = cast<Integer32::View>(hEntry->getKey());
Person::Handle     hPerson = cast<Person::Handle>(hEntry->getValue());
std::cout << "key=" << vKey << " person=" << hPerson;
}

Coherenceでは、coherence::util::Filterパッケージに多様なフィルタが用意されています。LimitFilterを使用すると、クライアントに送信されるデータ量を制限できるほか、ユーザー側でページングを実現できます。

例11-2 LimitFilterメソッドの使用方法

int32_t                nPageSize  = 25;
ValueExtractor::Handle hExtractor = ReflectionExtractor::create("getAge");
Filter::View           vFilter    = GreaterEqualsFilter::create(hExtractor, Integer32::valueOf(18));

// get entries 1-25
LimitFilter::Handle    hLimitFilter = LimitFilter::create(vFilter, nPageSize);
Set::View              vEntries     = hCache->entrySet(hLimitFilter);

// get entries 26-50
hLimitFilter->nextPage();
vEntries = hCache->entrySet(hLimitFilter);

問合せ可能な属性には、addIndexクラスのQueryMapメソッドで索引を付けることができます。

例11-3 問合せ可能な属性に対する索引付け

// addIndex(ValueExtractor::View vExtractor, boolean_t fOrdered, Comparator::View vComparator)
hCache->addIndex(hExtractor, true, NULL);

fOrdered引数では、索引構造をソートするかどうかを指定します。ソートされた索引は、「2つの日付の間に収まるエントリをすべて選択」や「姓がSで始まる従業員をすべて選択」などの範囲問合せに役立ちます。等価問合せの場合は、順序付けられていない索引を使用できます。この索引を使用すると、領域と時間の面で効率が向上することがあります。

comparator引数は、索引の順序付け用にカスタムのjava.util.Comparatorを指定します。

注意:

このメソッドは、単にキャッシュ実装のヒントとして示したものであり、索引がサポートされていない場合や目的の索引(またはそれに類似した索引)が存在する場合は、キャッシュによって無視されることがあります。アプリケーションでは、確実に索引が提示されるようにするために、索引が存在する場合でもこのメソッドをコールして索引を提示することが求められます。たとえば、分散環境では各サーバーが起動時に同じ索引セットを提示する可能性があり、別のサーバーが同じ索引を要求しているかどうかに関係なく、アプリケーションがそれらの索引を不必要に要求しても不都合は生じません。

Coherenceでは必要に応じて問合せを結合することができます。またCoherenceには、索引の使用優先順位を決めるコストベース・オプティマイザ(CBO)が搭載されています。索引を利用するには、問合せで使用されているエクストラクタと同等((Object->equals())のエクストラクタを、同じ問合せで使用する必要があります。

11.2.1 パーティション・キャッシュの問合せ

パーティション・キャッシュは、Parallel Query機能を使用してQueryMapインタフェースを実行するため、大きなデータセットでも高性能の問合せが可能です。

11.2.2 ニア・キャッシュの問合せ

ニア・キャッシュを通じて問合せを実行することは可能ですが、問合せではニア・キャッシュのフロント部分が使用されません。問合せでニア・キャッシュを使用する場合は、次のシーケンスを使用するのが最適のアプローチです。

Set::View vSetKeys   = hCache->keySet(vFilter);
Map::View vMapResult = hCache->getAll(vSetKeys);

11.3 問合せの概念の理解

この項では、問合せインタフェースの設計について、コアなコンポーネントから順に詳しく説明していきます。

問合せ処理の概念は、ValueExtractorインタフェースに基づいています。値エクストラクタは、問合せで指定のオブジェクトから属性を抽出するために使用されます(索引付けの場合も同様)。ほとんどの開発者に必要となるのは、このインタフェースのReflectionExtractor実装のみです。ReflectionExtractorは、リフレクションを使用してメソッド名(通常はgetName()のようなgetterメソッド)を参照することにより、値オブジェクトから属性を抽出します。

ReflectionExtractor::Handle hExtractor = ReflectionExtractor::create("getName");

toString()のようなObjectメソッドをはじめとする任意のvoid引数メソッドを使用できます(プロトタイプ作成/デバッグに有用)。索引には、従来のフィールド索引(オブジェクトのフィールドに付けられた索引)または機能別索引(仮想のオブジェクト属性に付けられた索引)を使用できます。たとえば、クラスにフィールド・アクセッサgetFirstNameおよびgetLastNameがある場合、そのクラスではこれらの名前を連結する関数getFullNameを定義し、その関数に索引を付けることができます。

getName属性を持つオブジェクトが含まれているキャッシュに問合せを実行するには、Filterを使用する必要があります。フィルタには、指定したオブジェクトが基準を満たしているかどうかを判別するメソッドが1つあります。

Filter::Handle hEqualsFilter = EqualsFilter::create(hExtractor, String::create("Bob Smith"));

特定のフィルタに適合するキャッシュ・エントリを選択する方法は次のとおりです。

例11-4 特定のフィルタに適合するキャッシュ・エントリの選択

for (Iterator::Handle hIter = hCache->entrySet(hEqualsFilter)->iterator(); hIter->hasNext(); )
{
Map::Entry::Handle hEntry  = cast<Map::Entry::Handle>(hIter->next());
Integer32::View    vKey    = cast<Integer32::View>(hEntry->getKey());
Person::Handle     hPerson = cast<Person::Handle>(hEntry->getValue());
std::cout << "key=" << vKey << " person=" << hPerson;
}

エントリを選択してソートする方法は次のとおりです。

例11-5 エントリの選択およびソート

// entrySet(Filter::View vFilter, Comparator::View vComparator)
Iterator::Handle hIter = hCache->entrySet(hEqualsFilter, NULL)->iterator();

NULL引数を追加することで、キャッシュ内の比較可能なオブジェクトの自然な順序で結果セットをソートするように指定しています。クライアントでは、Comparatorの実装を提供することで、結果セットの順序を明示的に指定できます。ソート処理を行う場合は、ソートの前に結果セット全体を取得しておく必要があるために、Coherenceで適用できる最適化が著しく制限されるので注意してください。

keySet形式の問合せをgetAll()と組み合せることで、メモリー使用量をより細かく制御できます。

例11-6 keySet形式の問合せの使用

// keySet(Filter::View vFilter)
Set::View   vSetKeys     = hCache->keySet(vFilter);
Set::Handle hSetPageKeys = HashSet::create();
int32_t     PAGE_SIZE    = 100;
for (Iterator::Handle hIter = vSetKeys->iterator(); hIter->hasNext();)
{
hSetPageKeys->add(hIter->next());
if (hSetPageKeys->size() == PAGE_SIZE || !hIter->hasNext())
{
// get a block of values
Map::View vMapResult = hCache->getAll(hSetPageKeys);

// process the block
// ...

hSetPageKeys->clear();
}
}

11.4 複数値属性が関係する問合せの実行

Coherenceでは、コレクションや配列を含めた複数値属性の索引付けおよび問合せがサポートされています。オブジェクトに索引を付けるときには、そのオブジェクトが複数値タイプかどうかがチェックされてから、シングルトンでなくコレクションとして索引が付けられます。このようなコレクションに対する問合せには、ContainsAllFilter、ContainsAnyFilterおよびContainsFilterが使用されます。

例11-7 複数値属性に対する索引付けおよび問合せ

Set::Handle hSearchTerms = HashSet::create();
hSearchTerms->add(String::create("java"));
hSearchTerms->add(String::create("clustering"));
hSearchTerms->add(String::create("books"));

// The cache contains instances of a class "Document" which has a method
// "getWords" which returns a Collection<String> containing the set of
// words that appear in the document.
ValueExtractor::Handle hExtractor = ReflectionExtractor::create("getWords");
Filter::View           vFilter    = ContainsAllFilter::create(hExtractor, hSearchTerms);

Set::View vEntrySet = hCache->entrySet(vFilter);

// iterate through the search results
// ...

11.5 問合せでの連鎖エクストラクタの使用

ChainedExtractor実装を使用すると、ゼロ引数(アクセッサ)メソッドの連鎖起動が可能となります。例11-8では、エクストラクタはまず、キャッシュされている各Personオブジェクトに対し、リフレクションを使用してgetName()をコールし、返されたStringに対し、リフレクションを使用してlength()をコールします。このエクストラクタを問合せに渡し、(たとえば)名前が10文字以内の人をすべて、問合せで選択することができます。

例11-8 ChainedExtractor実装の使用

ChainedExtractor::Handle hExtractor =
ChainedExtractor::create(ChainedExtractor::createExtractors("getName.length"));

メソッドの起動は、getName.trim.lengthのように、無限に連鎖させることができます。

11.6 問合せレコーダの使用

QueryRecorderクラスは指定されたフィルタの説明またはトレース・レコードを生成します。このクラスは、クラスタ内のすべてのノードを問い合せ、結果を集約する機能を持つ並列アグリゲータの実装です。このクラスでは2種類のレコードがサポートされています。その1つはQueryRecorder::explainレコードで、問合せ処理の間に実行されたフィルタの評価の見積りコストを提供します。もう1つはQueryRecorder::traceレコードで、問合せ処理の間に実行されたフィルタの評価の実際のコストを提供します。両方の問合せレコードでは、フィルタで索引が使用可能かどうかが考慮されます。EXPLAIN PLANレコードおよびトレース・レコードで提供されるデータの詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

問合せレコードを作成するには、RecordTypeパラメータを指定する新しいQueryRecorderインスタンスを作成します。テストするインスタンスとフィルタをAggregateメソッドのパラメータとして含めます。次の例では、説明レコードを作成しています。

NamedCache::Handle hCache = CacheFactory::getCache("MyCache");

IdentityExtractor::View hExtract = IdentityExtractor::getInstance();
OrFilter::Handle hFilter = OrFilter::create(
GreaterEqualsFilter::create(hExtract, Integer32::create(50)),
LessEqualsFilter::create(hExtract, Integer32::create(20)));

QueryRecord::View vRecord = cast<QueryRecord::View>(hCache->aggregate(
(Filter::View) hFilter, QueryRecorder::create(QueryRecorder::explain)));

cout << vRecord;

トレース・レコードを作成するには、RecordTypeパラメータをtraceに変更します。

QueryRecord::View vRecord = cast<QueryRecord::View>(hCache->aggregate(
(Filter::View) hFilter, QueryRecorder::create(QueryRecorder::trace)));

12 連続問合せの実行(C++)

この章では、C++クライアントで連続問合せキャッシュを使用して、問合せが常にキャッシュから最新の結果をリアルタイムに取得する手順を説明します。

この章には次の項が含まれます:

- 連続問合せの実行の概要(C++)

- 連続問合せキャッシュの実装の理解

- 連続問合せキャッシュの定義

- 連続問合せキャッシュ・リソースのクリーンアップ

- キーのみのキャッシングと、キーおよび値のキャッシング

- 連続問合せキャッシュのリスニング

- 連続問合せキャッシュを読取り専用にする

12.1 連続問合せの実行の概要(C++)

問合せは、Coherenceキャッシュから特定の時点の問合せ結果を取得でき、さらに問合せの結果が変更された場合のイベントを受信できます。また、連続問合せ機能では問合せ結果を関連するイベントの連続的なストリームと結合し、リアルタイムに最新の問合せ結果を維持することが可能です。目的の問合せの待機時間が0である場合と同じ効果を持ち、問合せが1ミリ秒ごとに数回繰り返されるため、この機能は連続問合せと呼ばれています。

連続問合せキャッシュは、Oracleデータベースのマテリアライズド・ビューに似ています。マテリアライズド・ビューでは、データベース表に問い合せたデータがビューにコピーされます。データベース内のデータが変更されると、ビュー内のデータが自動的に更新されます。マテリアライズド・ビューによって、結果セットへの変更を参照できます。連続問合せでは、クライアント上にキャッシュのローカル・コピーが作成されます。フィルタを使用することで、キャッシュのサイズと内容を制限できます。イベント・リスナーを組み合せることで、キャッシュをリアルタイムに更新できます。

たとえば、複数の顧客のすべての発注をリアルタイムに監視するとします。連続問合せキャッシュを作成し、対象の顧客に関係するあらゆるイベントをリスニングするイベント・リスナーを設定します。Coherenceは、グリッド上で個々の顧客に関係するデータ・オブジェクトをすべて問い合せ、そのオブジェクトをローカル・キャッシュにコピーします。この問合せのイベント・リスナーでは、その顧客に対してグリッドで行われるあらゆる挿入、更新または削除がリスニングされます。イベントが発生すると、顧客データのローカル・コピーが更新されます。

12.1.1 連続問合せキャッシュのユース・ケースの理解

連続問合せキャッシュには、いくつかの異なる一般的な用途があります。

- これは、複合イベント処理(CEP: Complex Event Processing)システムやイベント相関エンジンにおける有用な構成要素です。

- これは、アプリケーションが特定の問合せを繰り返し実行し、その問合せの最新の結果に常に即座にアクセスできることが有益である状況では、効果的です。

- 連続問合せキャッシュはマテリアライズド・ビューに類似しており、標準のNamedCache APIを使用して問合せの結果にアクセスし、操作する場合、およびその問合せに関連するイベントの現行ストリームを受信する場合に役立ちます。

- 連続問合せキャッシュは、最新のデータセットを使用場所(特定のサーバー・ノードやクライアントなど)でローカルに保持できるため、ニア・キャッシュと同様の方法で使用できます。ただし、ニア・キャッシュは無効化ベースですが、連続問合せキャッシュではデータを実際に最新の状態で保持します。

Coherence*Extend機能を連続問合せキャッシュと組み合せることにより、アプリケーションで文字どおり何万もの同時ユーザーをサポートできます。

注意:

連続問合せキャッシュは、分散される可能性のあるより大きなキャッシュ・データセットの特定のサブセットについて、その最新のローカル・コピーを非常に簡単かつ効果的に維持する機能を提供します。そのため、クライアントベースおよびサーバーベースのアプリケーションを含め、ほとんどすべてのタイプのアプリケーションに有用です。

12.2 連続問合せキャッシュの実装の理解

Coherenceでの連続問合せの実装には、ContinuousQueryCacheクラスを使用します。このクラスは、Coherenceのすべてのキャッシュと同様、次の機能を備えた標準のNamedCacheインタフェースを実装します。

- Mapインタフェースを使用したキャッシュのアクセスと操作: NamedCacheは、Javaコレクション・フレームワークのMapインタフェースに基づくMapインタフェースを拡張します。

- キャッシュ内で発生するすべてのオブジェクト変更に対するイベント: NamedCacheはObservableMapインタフェースを拡張します。

- キャッシュ内オブジェクトの問合せ: NamedCacheはQueryMapインタフェースを拡張します。

- キャッシュ内オブジェクトの分散パラレル処理および集約: NamedCacheはInvocableMapインタフェースを拡張します。

ContinuousQueryCacheは、Coherenceのすべてのキャッシュで提供されるAPIであるNamedCacheインタフェースを実装しているため、非常に使いやすく、その機能が必要になった場合に別のキャッシュと簡単に置き換えることができます。

12.3 連続問合せキャッシュの定義

連続問合せキャッシュは、次の2つの機能で定義されます。

- 連続問合せの基礎となるキャッシュ

- その基礎となるキャッシュの問合せ(連続問合せキャッシュにキャッシュされるサブセットを生成)

基礎となるキャッシュには、別の連続問合せキャッシュを含めた任意のCoherenceキャッシュを使用できます。キャッシュを取得する最も簡単な方法は、CacheFactoryクラスを使用することです。このクラスを使用すると、名前を指定するだけでキャッシュを作成できます。キャッシュは自動的に作成され、アプリケーションのキャッシュ構成要素に基づいて構成されます。たとえば、次のコード行ではordersという名前のキャッシュが作成されます。

NamedCache::Handle hCache = CacheFactory::getCache("orders");

この問合せは、 他のキャッシュの問合せに使用される問合せと同じタイプです。例12-1は、コード・フィルタを使用して、特定の注文ステータスにある特定のトレーダーを検出する方法を示しています。

例12-1 フィルタを使用した問合せ

ValueExtractor::Handle hTraderExtractor = ReflectionExtractor::create("getTrader");
ValueExtractor::Handle hStatusExtractor = ReflectionExtractor::create("getStatus");

Filter::Handle hFilter = AndFilter::create(EqualsFilter::create(hTraderExtractor, vTraderId),
EqualsFilter::create(hStatusExtractor, vStatus));

通常、キャッシュを問い合せるには、QueryMapクラスのメソッドを使用します。たとえば、このトレーダーの未決済ポジションすべてのスナップショットを取得するには、次のコードを使用します。

Set::View vSetOpenTrades = hCache->entrySet(hFilter);

これに対し、連続問合せキャッシュはContinuousQueryCache::createメソッドでキャッシュとフィルタを渡すことによって構成されます。

ContinuousQueryCache::Handle hCacheOpenTrades  = ContinuousQueryCache::create(hCache, hFilter);

12.4 連続問合せキャッシュ・リソースのクリーンアップ

連続問合せキャッシュでは、その基礎となるキャッシュに1つ以上のイベント・リスナーが配置されます。連続問合せキャッシュがアプリケーションの継続期間を通して使用される場合、リソースはそのノードがシャットダウンされたとき、または停止したときにクリーンアップされます。ただし、連続問合せキャッシュがわずかの間だけ使用される場合は、使い終わった時点で連続問合せキャッシュに対してアプリケーションからrelease()メソッドをコールする必要があります。

12.5 キーのみのキャッシングと、キーおよび値のキャッシング

連続問合せキャッシュを構成する際、問合せで取得されたキーだけをキャッシュで追跡し、要求された場合にのみ、その値を基礎となるキャッシュから取得するように指定することができます。この機能は、問合せの結果セットが非常に膨大になる連続問合せキャッシュを作成する場合、または値をリクエストされることがないか、ほとんどない場合に役立ちます。キーのみをキャッシュするように指定するには、ContinuousQueryCacheを作成する際に、次の例のようにfalseを渡します。

ContinuousQueryCache::Handle hCacheOpenTrades  =
ContinuousQueryCache::create(hCache, hFilter, false);

次の例に示すように、必要に応じて、キャッシュがインスタンス化された後にCacheValuesプロパティを変更することもできます。

hCacheOpenTrades->setCacheValues(true);

12.5.1 CacheValuesプロパティとイベント・リスナー

連続問合せキャッシュに標準の(非Lite)イベント・リスナーがある場合、またはイベント・リスナーのいずれかがフィルタリングされる場合は、CacheValuesプロパティが自動的にtrueに設定されます。これは、イベントをフィルタリングする際、および発生させたイベントに古い値と新しい値を提供する際に、ローカルにキャッシュされた値を連続問合せキャッシュが使用するためです。

12.5.2 連続問合せキャッシュでのReflectionExtractorの使用方法

連続問合せキャッシュが値をキャッシュするように構成されている場合は、ReflectionExtractorの使用がサポートされません。これは、ReflectionExtractorではC++でのリフレクションがサポートされていないためです。この場合は、カスタム・エクストラクタを用意する必要があります。連続問合せキャッシュで値がローカルにキャッシュされていない場合は、ReflectionExtractorを使用できます。これは、このエクストラクタがクライアントで抽出を実行せず、かわりに必要な抽出情報をクラスタに渡して問合せを実行するためです。

12.6 連続問合せキャッシュのリスニング

連続問合せキャッシュ自体は監視可能であるため、クライアントが連続問合せキャッシュに1つ以上のイベント・リスナーを配置することが可能です。例:

例12-2 連続問合せキャッシュへのリスナーの配置

ContinuousQueryCache::Handle hCacheOpenTrades  = ContinuousQueryCache::create(hCache, hFilter);
hCacheOpenTrades->addFilterListener(hListener);

キャッシュに格納されているすべてのアイテム、およびキャッシュに追加されるすべてのアイテムに対して、アプリケーションでなんらかの処理を実行する必要がある場合は、作成中にリスナーを設定します。連続問合せキャッシュ内のアイテムが(問合せに含まれていたため)最初から存在していたか、キャッシュの作成中または作成後に追加されたかに関係なく、作成されたキャッシュはアイテムごとに1つのイベントを受信します。ContinuousQueryCacheのファクトリ作成メソッドには、キャッシュ、フィルタおよびリスナーを指定できる形式があります。

例12-3 フィルタとリスナーを使用する連続問合せキャッシュの作成

ContinuousQueryCache::Handle hCacheOpenTrades  = ContinuousQueryCache::create(
hRemoteCache, hFilter, true, hListener);

12.6.1 予期しない結果の回避

連続問合せキャッシュ内のアイテムを処理するには2つのアプローチがありますが、どちらも予期しない結果や望ましくない結果をもたらす場合があります。まず、処理を実行した後、その後の追加に対応するためにリスナーを追加すると、反復処理が終了してリスナーが追加されるまでのわずかの時間に発生したイベントを見逃すことになります。これを例12-4に示します。

例12-4 データを処理してからリスナーを追加する場合

ContinuousQueryCache::Handle hCacheOpenTrades  = ContinuousQueryCache::create(hCache, hFilter);

for (Iterator::Handle hIter = hCacheOpenTrades->entrySet()->iterator(); hIter->hasNext(); )
{
Map::Entry::View vEntry = cast<Map::Entry::View>(hIter->next());
// .. process the cache entry
}
hCacheOpenTrades->addFilterListener(hListener);

2番目のアプローチでは、イベントを見逃さないように、まずリスナーを追加し、その後で処理を実行します。ただし、イベントとイテレータの両方に同じエントリが出現する可能性があります。イベントは非同期の可能性があるため、操作の順序は保証されません。

例12-5 リスナーを追加してからデータを処理する場合

ContinuousQueryCache::Handle hCacheOpenTrades  =
ContinuousQueryCache::create(hRemoteCache, hFilter);

hCacheOpenTrades->addFilterListener(hListener);
for (Iterator::Handle hIter = hCacheOpenTrades->entrySet()->iterator(); hIter->hasNext(); )
{
Map::Entry::View vEntry = cast<Map::Entry::View>(hIter->next());
// .. process the cache entry
}

12.6.2 安定したマテリアライズド・ビューの実現

連続問合せキャッシュの実装にも同じ課題がありました。同じキャッシュから変更イベントのストリームを受信しながら、基礎となるキャッシュの正確なポイント・イン・タイム・スナップショットをいかにアセンブルするかということです。その解決法は、いくつかの部分に分かれています。まず、Coherenceでは同期イベントのオプションがサポートされており、これによって順序付けが保証されます。第2に、連続問合せキャッシュでは、その初期移入の実装が2つのフェーズに分かれているため、まず基礎となるキャッシュに対して問合せを実行し、その後、最初のフェーズ中に発生したイベントをすべて解決できます。このようにイベントを見逃したり重複させたりすることなくデータの可視性を保証する操作はかなり複雑であるため、ContinuousQueryCacheでは、アプリケーション開発者が作成時にリスナーを渡すことで、この複雑さに対処しなくても済むようにしています。

12.6.3 同期および非同期リスナーのサポート

デフォルトでは、連続問合せキャッシュに対するリスナーによって、リスナーのイベントが非同期に配信されます。ただしContinuousQueryCacheでは、SynchronousListenerインタフェースで規定されているとおり、同期イベントのオプションが考慮されます。

12.7 連続問合せキャッシュを読取り専用にする

連続問合せキャッシュは読取り専用キャッシュにすることができます。そのためには、次の例のように、ContinuousQueryCacheクラスのブール・メソッドsetReadOnlyを使用します。

hCacheOpenTrades->setReadOnly(true);

読取り専用の連続問合せキャッシュでは、オブジェクトの追加、変更、削除またはロックができません。

連続問合せキャッシュを読取り専用に設定した後は、読取り/書込みに戻すことはできません。

13 リモート起動の実行(C++)

この章では、C++クライアントからCoherenceキャッシュでリモート起動を実行する手順を示します。

この章には次の項が含まれます:

- リモート起動の実行の概要(C++)

- リモート起動サービスの構成と使用

- Invocable実装クラスの登録

13.1 リモート起動の実行の概要(C++)

Invocableは任意のアクションを実行でき、作業を行うために必要な任意のクラスタ側サービス(キャッシュ・サービスやグリッド・サービスなど)を使用できます。Invocableの操作はステートフルにすることもできます。つまり、その状態がシリアライズされ、Invocableが実行されるグリッド・ノードに転送されます。

Coherence for C++では、クライアントが接続されているクラスタ側JVM内でのInvocableの実行を可能にするリモート起動サービスを提供しています。JavaでのInvocableは、com.tangosol.net.Invocableインタフェースを実装する単純な実行可能アプリケーション・クラスです。Coherence for C++でInvocableを採用するには、InvocableのC++実装であるcoherence::net::Invocableを提供するほかに、InvocableタスクのコンパイルされたJava実装をクラスタ側ノードにデプロイする必要があります。実行はサーバー側(つまりJava)で行われるため、C++のInvocableは状態にのみ関係します。メソッド自体はno-operation(操作なし)になっている場合があります。

13.2 リモート起動サービスの構成と使用

リモート起動サービスは、キャッシュ構成ディスクリプタのremote-invocation-scheme要素を使用して構成します。例13-1は、リモート起動スキーム構成のサンプルを示しています。

例13-1 リモート起動スキーム構成のサンプル

<remote-invocation-scheme>
<scheme-name>example-invocation</scheme-name>
<service-name>ExtendTcpInvocationService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>

<outgoing-message-handler>
<request-timeout>30s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-invocation-scheme>

coherence::net::CacheFactoryクラスを使用することによって、構成済リモート起動サービスへの参照を名前によって取得できます。

例13-2 リモート起動サービスへの参照

InvocationService::Handle hService = hService::getService("ExtendTcpInvocationService");

クライアントが接続されているグリッド・ノードでエージェントを実行するために必要なコードは、次の1行のみです。

Map::View hResult = hService->query(myTask::create(), NULL);

問合せから返されたMapには、問合せが実行されたメンバーがキー設定されます。Extendクライアントの場合はメンバーシップの概念がないため、結果には、CacheFactory::getConfigurableCacheFactory()::GetLocalMember()をコールして取得されるローカル・メンバーがキー設定されます。

13.3 Invocable実装クラスの登録

キャッシュされた値オブジェクト同様、すべてのInvocable実装クラスは、C++アプリケーション(「PortableObject(自己シリアライズ)」を参照)のPOFコンテキストおよびクライアントが接続されているクラスタ側ノードのPOFコンテキストに正しく登録する必要があります。したがって、InvocableタスクのJava実装(com.tangosol.net.Invocable実装)は、クラスタ側ノードで作成、コンパイルおよびデプロイする必要があります。

詳細は、「クラスタでのカスタム型の登録」を参照してください。

14 キャッシュ・イベントの使用方法(C++)

この章では、マップ・イベント・リスナーを使用して、キャッシュ・イベントやObservableMapインタフェースを実装するCoherenceの任意のクラスからのイベントを受信する手順を説明します。

この章には次の項が含まれます:

- マップ・イベントの概要(C++)

- すべてのイベントのサインアップ

- 多重化マップ・リスナーの使用

- キャッシュ用のMapListenerの構成

- 特定のIDのイベントのサインアップ

- イベントのフィルタリング

- Liteイベントの使用

- 問合せのリスニング

- 統合イベントの使用

- バッキング・マップ・イベントの使用

- 同期イベント・リスナーの使用

14.1 マップ・イベントの概要(C++)

イベント・モデルはEventListenerインタフェースから成り、すべてのリスナーでこれを拡張する必要があります。Coherenceには、MapListenerインタフェースが用意されており、これによりCoherenceキャッシュのデータが追加、変更または削除されたときにアプリケーション・ロジックでイベントを受信できます。

MapListenerインタフェースを実装するアプリケーション・オブジェクトは、アプリケーションのMapListener実装のインスタンスをaddMapListener()メソッドに渡すことで、ObservableMapインタフェースを実装する任意のCoherenceキャッシュまたはクラスからイベントにサインアップできます。

MapListenerに渡されるMapEventオブジェクトは、イベントの発生元になったソース(ObservableMap)、イベントに関連付けられたID(キー)、そのIDに対するアクション(挿入、更新、削除)、古い値と新しい値など、発生したイベントについて必要なすべての情報を保持します。

14.1.1 イベントをサポートするキャッシュとクラス

すべてのCoherenceキャッシュには、ObservableMapが実装されます。実際に、すべてのCoherenceキャッシュで実装されるNamedCacheインタフェースは、ObservableMapインタフェースを拡張します。つまり、キャッシュが、ローカル、パーティション、ニア、レプリケーションであるかどうか、また、リードスルー、ライトスルー、ライトビハインド、オーバーフロー、ディスク記憶域などを使用しているかどうかに関係なく、アプリケーションはサインアップして任意のキャッシュからイベントを受信できます。

注意:

キャッシュ・トポロジやサーバーの数に関係なく、また他のサーバーが変更している場合でも、これらのイベントはアプリケーションのリスナーに配信されます。

Coherenceキャッシュ(Coherenceキャッシュ・ファクトリを介して取得されたオブジェクト)に加えて、次のように、Coherenceでサポートされる他のいくつかのクラスでもObservableMapインタフェースが実装されます。

- ObservableHashMap

- LocalCache

- OverflowMap

- NearCache

- ReadWriteBackingMap

- AbstractSerializationCache、SerializationCacheおよびSerializationPagedCache

- WrapperObservableMap、WrapperConcurrentMapおよびWrapperNamedCache

公開されている実装クラスの一覧は、Coherence APIの「ObservableMap」を参照してください。

14.2 すべてのイベントのサインアップ

イベントにサインアップするには、MapListenerインタフェースを実装するオブジェクトをObservableMapのaddMapListenerメソッドに渡します。

例14-1 ObservableMapのメソッド

virtual void addKeyListener(MapListener::Handle hListener, Object::View vKey, bool fLite) = 0;
virtual void removeKeyListener(MapListener::Handle hListener, Object::View vKey) = 0;
virtual void addFilterListener(MapListener::Handle hListener, Filter::View vFilter = NULL, bool fLite = false) = 0;
virtual void removeFilterListener(MapListener::Handle hListener, Filter::View vFilter = NULL) = 0;

MapListener実装のサンプルを作成してみましょう。

例14-2 MapListener実装のサンプル

#include "coherence/util/MapEvent.hpp"
#include "coherence/util/MapListener.hpp"

#include <iostream>

using coherence::util::MapEvent;
using coherence::util::MapListener;
using namespace std;

/**
* A MapListener implementation that prints each event as it receives
* them.
*/
class EventPrinter
: public class_spec<EventPrinter,
extends<Object>,
implements<MapListener> >
{
friend class factory<EventPrinter>;

public:
virtual void entryInserted(MapEventView vEvent)
{
cout << vEvent << endl;
}

virtual void entryUpdated(MapEventView vEvent)
{
cout << vEvent << endl;
}

virtual void entryDeleted(MapEventView vEvent)
{
cout << vEvent << endl;
}
};

この実装を使用すると、任意のキャッシュからすべてのイベントを簡単に出力できます(すべてのキャッシュでObservableMapインタフェースが実装されているため)。

例14-3 イベントの出力

NamedCache::Handle hCache;
...
hCache->addFilterListener(EventPrinter::create());

ただし、後でリスナーを削除できるように、リスナーへの参照を保持する必要があります。

例14-4 リスナーへの参照の保持

MapListener::Handle hListener = EventPrinter::create();
hCache->addFilterListener(hListener);
m_hListener = hListener; // store the listener in a member field

後でリスナーを削除するには、次のように処理します。

例14-5 リスナーへの参照の削除

MapListener::Handle hListener = m_hListener;
if (hListener != NULL)
{
hCache->removeFilterListener(hListener);
m_hListener = NULL; // clean up the listener field
}

ObservableMapインタフェースの各add*Listenerメソッドには、対応するremove*Listenerメソッドがあります。リスナーを削除するには、そのリスナーの追加に使用したadd*Listenerメソッドに対応するremove*Listenerメソッドを使用します。

14.3 多重化マップ・リスナーの使用

MapListenerの作成に役立つもう1つのベース・クラスは、MultiplexingMapListenerです。これは、すべてのイベントを1つのメソッドにルーティングして処理します。例14-6に、EventPrinterの例を簡略化したものを示します。

例14-6 MultiplexingMapListenerを使用したイベントのルーティング

#include "coherence/util/MultiplexingMapListener.hpp"

#include <iostream>

using coherence::util::MultiplexingMapListener;

class EventPrinter
: public class_spec<EventPrinter,
extends<MultiplexingMapListener> >
{
public:
virtual void onMapEvent(MapEventView vEvent)
{
std::cout << vEvent << std::endl;
}
};

14.4 キャッシュ用のMapListenerの構成

特定のキャッシュにリスナーを常駐させる必要がある場合、<listener>要素を使用して、それをキャッシュ構成に配置します。キャッシュ構成の際に、リスナーは自動的に追加されます。

14.5 特定のIDのイベントのサインアップ

特定のID(キー)に対して発生したイベントのサインアップは非常に簡単です。例14-7のC++コードでは、Integerキー5に対して発生したすべてのイベントが出力されます。

例14-7 指定したIntegerキーに対して発生したイベントの出力

hCache->addKeyListener(EventPrinter::create(), Integer32::create(5), false);

例14-8のコードでは、Integerキー5が挿入または更新された場合にのみイベントがトリガーされます。

例14-8 指定したIntegerキーの値に対するイベントのトリガー

for (int32_t i = 0; i < 10; ++i)
{
Integer32::View vKey   = Integer32::create(i);
Integer32::View vValue = vKey;
hCache->put(vKey, vValue);
}

14.6 イベントのフィルタリング

特定のキーのリスニングと同様に、特定のイベントをリスニングすることもできます。例14-9では、削除イベントのみを受信できるフィルタを指定したリスナーが、キャッシュに追加されます。

例14-9 削除されたイベントのみを許可するフィルタを指定したリスナーの追加

// Filters used with partitioned caches must implement coherence::io::pof::PortableObject

#include "coherence/io/pof/PofReader.hpp"
#include "coherence/io/pof/PofWriter.hpp"
#include "coherence/io/pof/PortableObject.hpp"
#include "coherence/util/Filter.hpp"
#include "coherence/util/MapEvent.hpp"

using coherence::io::pof::PofReader;
using coherence::io::pof::PofWriter;
using coherence::io::pof::PortableObject;
using coherence::util::Filter;
using coherence::util::MapEvent;

class DeletedFilter
: public class_spec<DeletedFilter,
extends<Object>,
implements<Filter, PortableObject> >
{
public:
// Filter interface        virtual bool evaluate(Object::View v) const
{
MapEvent::View vEvt = cast<MapEvent::View>(v);
return MapEvent::entry_deleted == vEvt->getId();
}

// PortableObject interface        virtual void readExternal(PofReader::Handle hIn)
{
}

virtual void writeExternal(PofWriter::Handle hOut) const
{
}
};

hCache->addFilterListener(EventPrinter::create(), DeletedFilter::create(), false);

たとえば、次の一連のコールが実行されたとします。

例14-10 キャッシュに対するデータの挿入および削除

cache::put(String::create("hello"), String::create("world"));
cache::put(String::create("hello"), String::create("again"));
cache::remove(String::create("hello"));

次のような結果になります。

CacheEvent{LocalCache deleted: key=hello, value=again}

詳細は、「問合せのリスニング」を参照してください。

イベントのフィルタリングとキャッシュされたデータのフィルタリングの比較

問合せのFilterを作成する場合、Filterのevaluateメソッドに渡すオブジェクトはキャッシュからの値になります。または、FilterでEntryFilterインタフェースを実装する場合は、キャッシュからのMap::Entry全体になります。MapListenerのイベントをフィルタリングするFilterを作成する場合、Filterのevaluateメソッドに渡すオブジェクトは常にMapEvent型になります。

問合せフィルタを使用してキャッシュ・イベントをリスニングする方法の詳細は、「応用: 問合せのリスニング」を参照してください。

14.7 Liteイベントの使用

デフォルトでは、イベントの一部として古い値と新しい値が両方とも提供されます。次の例があります。

例14-11 値の挿入、更新、削除

MapListener::Handle hListener = EventPrinter::create();
// add listener with the default"lite" value of falsehCache->addFilterListener(hListener);

// insert a 1KB value
String::View vKey = String::create("test");
hCache->put(vKey, Array<octet_t>::create(1024));

// update with a 2KB value
hCache->put(vKey, Array<octet_t>::create(2048));

// remove the value
hCache->remove(vKey);

このコードを実行すると、挿入イベントには新しい1KBの値、更新イベントには古い1KBの値と新しい2KBの値、削除イベントには削除された2KBの値がそれぞれ保持されます。

アプリケーションでイベントに古い値と新しい値を両方とも含める必要がない場合、Liteイベントのみをリクエストして、そのように指定することができます。リスナーの追加時にLiteイベントをリクエストするには、追加のブール・パラメータfLiteを使用するaddFilterListenerメソッドとaddKeyListenerメソッドのいずれかを使用できます。前述の例の場合、変更は次の箇所のみです。

例14-12 Liteイベントのみのリクエスト

cache->addFilterListener(hListener, (Filter::View) NULL, true);

注意:

Liteイベントの古い値と新しい値は、NULLにすることができます。ただし、Liteイベントをリクエストしても、イベントの生成と配信に余分な負荷がかからない場合は、古い値と新しい値が含まれることがあります。つまり、MapListener受信Liteイベントを要求することは、MapListenerがイベントについて古い値と新しい値の情報を必要としないことを単純にシステムに通知することになります。

14.8 問合せのリスニング

すべてのCoherenceキャッシュはどの基準による問合せもサポートしています。アプリケーションでキャッシュからのデータを問い合せる場合、その結果はID(keySet)のセットまたはID/値のペア(entrySet)のセットとしてのポイント・イン・タイム・スナップショットになります。結果セットの内容を判断するメカニズムは、フィルタリングと呼ばれ、これによりアプリケーションの開発者は豊富な既定のフィルタ(equals、less-than、like、betweenなど)を使用してどのように複雑な問合せも構築でき、また独自のカスタム・フィルタ(XPathなど)を提供できます。

キャッシュの問合せに使用するフィルタと同じフィルタを、キャッシュからのイベントのリスニングに使用します。たとえば、トレーディング・システムにおいて、特定のトレーダーの未決済Orderオブジェクトをすべて問い合せることができます。

注意:

クラスタでの問合せの実行: 例14-13では、coherence::util::extractor::ReflectionExtractorクラスが使用されています。C++クライアントではリフレクションがサポートされませんが、クラスタ内で実行される問合せにはReflectionExtractorを使用できます。この場合、ReflectionExtractorは、問合せを実行するクラスタに、必要な抽出情報を渡すのみです。ReflectionExtractorがクライアントでデータを抽出することになる場合(値をローカルにキャッシュするときのContinuousQueryCacheなど)は、ReflectionExtractorの使用はサポートされません。この場合は、カスタム・エクストラクタを用意する必要があります。

例14-13 キャッシュ・イベントのフィルタリング

NamedCache::Handle hMapTrades = ...
Filter::Handle hFilter = AndFilter::create(
EqualsFilter::create(ReflectionExtractor::create("getTrader"), vTraderId),
EqualsFilter::create(ReflectionExtractor::create("getStatus"), Status::OPEN));
Set::View vSetOpenTrades = hMapTrades->entrySet(hFilter);

そのトレーダーが新しいポジションを建てた、そのトレーダーがポジションを決済した、トレーダー間でポジションを付け替えた、という情報を受信するために、アプリケーションで同じフィルタを使用できます。

例14-14 特化されたイベントのフィルタリング

// receive events for all trade IDs that this trader is interested in
hMapTrades->addFilterListener(hListener, MapEventFilter::create(hFilter), true);

MapEventFilterは、問合せフィルタをイベント・フィルタに変換します。

注意:

イベントのフィルタリングとキャッシュされたデータのフィルタリングの比較: 問合せのFilterを作成する場合、Filterのevaluateメソッドに渡すオブジェクトはキャッシュからの値になります。または、FilterでEntryFilterインタフェースを実装する場合は、キャッシュからのMap::Entry全体になります。MapListenerのイベントをフィルタリングするFilterを作成する場合、Filterのevaluateメソッドに渡すオブジェクトは常にMapEvent型になります。

MapEventFilterは、問合せに使用するFilterをMapListenerのイベントのフィルタリングに使用するFilterに変換します。つまり、MapEventFilterはキャッシュを問い合せるFilterから作成されますが、作成されたMapEventFilterは、問合せFilterが期待するオブジェクトに変換することによってMapEventオブジェクトを評価するフィルタになります。

MapEventFilterには、いくつもの非常に強力なオプションがあります。これにより、アプリケーション・リスナーは特に関心のあるイベントのみを受信できます。スケーラビリティとパフォーマンスの観点からさらに重要なこととして、必要なイベントのみがネットワーク上で通信されるため、それらの特定イベントを対象とするサーバーとクライアントにのみ配信されます。例:

例14-15 ネットワークを介した、特化されたイベントのみの伝達

// receive all events for all trades that this trader is interested in
int32_t nMask = MapEventFilter::e_all;
hMapTrades->addFilterListener(hListener, MapEventFilter::create(nMask, hFilter), true);

// receive events for all this trader's trades that are closed or
// re-assigned to a different trader
nMask = MapEventFilter::e_updated_left | MapEventFilter::e_deleted;
hMapTrades->addFilterListener(hListener, MapEventFilter::create(nMask, hFilter), true);

// receive events for all trades as they are assigned to this trader
nMask = MapEventFilter::e_inserted | MapEventFilter::e_updated_entered;
hMapTrades->addFilterListener(hListener, MapEventFilter::create(nMask, hFilter), true);

// receive events only for new trades assigned to this trader
nMask = MapEventFilter::e_inserted;
hMapTrades->addFilterListener(hListener, MapEventFilter::create(nMask, hFilter), true);

サポートされる各種オプションの詳細は、MapEventFilterのAPIドキュメントを参照してください。

14.9 統合イベントの使用

イベントは通常、キャッシュで発生している変更を反映します。たとえば、あるサーバーがキャッシュ内の1つのエントリを変更し、別のサーバーがキャッシュに複数のアイテムを追加し、3つ目のサーバーが同じキャッシュから1つのアイテムを削除している間に、クラスタ内の各サーバーで50個のスレッドが同じキャッシュのデータにアクセスすることがあります。すべての変更操作によりイベントが生成されますが、それをクラスタ内の任意のサーバーで受信するように選択できます。これらの操作をクライアント・アクションと呼び、そのイベントは、クライアントにディスパッチされた状態にあります(この場合の「クライアント」は実際には「サーバー」)。これはCoherenceクラスタなどの、真のpeer-to-peerアーキテクチャでは自然の概念です。いずれのピアもクライアントでありサーバーでもあるので、他のピアからサービスを受け、他のピアにサービスを提供します。一般的なJava Enterpriseアプリケーションでは、ピアはアプリケーションのコンテナとして動作するアプリケーション・サーバー・インスタンスで、クライアントは直接キャッシュに対してアクセスおよび変更を行い、キャッシュからのイベントをリスニングするアプリケーションの一部です。

イベントの中には、キャッシュ内部で起動されるものもあります。多くの例がありますが、最も一般的なケースは次のとおりです。

- キャッシュのエントリが自動失効した場合

- キャッシュの最大サイズに達したため、エントリがキャッシュから削除された場合

- リードスルー操作の結果としてエントリが透過的にキャッシュに追加された場合

- リードアヘッドまたはリフレッシュアヘッド操作の結果としてキャッシュ内のエントリが透過的に更新された場合

これらは変更の各例ですが、変更とはキャッシュ内部での自然な(通常は自動的な)各操作を表します。これらのイベントを統合イベントと呼びます。

必要に応じて、アプリケーションはイベントに問い合せて、それがクライアントに起因するイベントか、または統合イベントかを区別できます。この情報は、CacheEventというMapEventのサブクラスで保持されます。前述のEventPrinterの例を使用して、統合イベントのみを出力できます。

例14-16 クライアントに起因するイベントと統合イベントの区別

class EventPrinter
: public class_spec<EventPrinter,
extends<MultiplexingMapListener> >
{
friend class factory<EventPrinter>;

public:
void onMapEvent(MapEvent::View vEvt)
{
if (instanceof<CacheEvent::View>(vEvt) &&
(cast<CacheEvent::View>(vEvt)->isSynthetic()))
{
std::cout << vEvt;
}
}
};

この機能の詳細は、CacheEventのAPIドキュメントを参照してください。

14.10 バッキング・マップ・イベントの使用

Coherenceキャッシュのイベントをリスニングし、データに関して分散、パーティション、レプリケーション、ニア・キャッシュ、連続問合せ、リードスルー/ライトスルー、ライトビハインドのローカル表示を確認できる一方で、いわば「こっそりのぞき見る」こともできます。

いくつかの応用例の中には、サービスの背後でマップをリスニングする必要がある場合があります。分散環境でのレプリケーション、パーティション、およびその他のデータ管理方式は、いずれも分散サービスです。このサービスにはさらに実際にデータを管理するための機能が必要です。それが「バッキング・マップ」と呼ばれるものです。

バッキング・マップは構成可能です。特定のキャッシュのすべてのデータを、ヒープのオブジェクト形式で保持する必要がある場合、無制限で失効期限のないLocalCache(統計が不要な場合はSafeHashMap)を使用します。メモリーに保持するアイテムの数が少ない場合は、LocalCacheを使用します。データを必要に応じてデータベースから読み取る場合は、ReadWriteBackingMapを使用します(アプリケーションのDAO実装を介した読取りおよび書込み方法を指定します)。ReadWriteBackingMapに、SafeHashMapやLocalCacheなどのバッキング・マップを提供してデータを保存します。

バッキング・マップの中には監視可能なものがあります。これらのバッキング・マップから取得されたイベントは、一般的にはアプリケーションに直接関係がありません。かわりに、Coherenceではそれらを(Coherenceで)実行する必要があるアクションに変換してデータを同期的に保持し正しくバックアップを行い、またアプリケーション・リスナーでのリクエストに応じてそれをクラスタ全体に配信されるクラスタ化されたイベントに変換します。たとえば、パーティション・キャッシュにバッキング・マップとしてLocalCacheがあり、ローカル・キャッシュでエントリが失効した場合、そのイベントによってエントリのすべてのバックアップ・コピーが失効します。さらに、リスナーがパーティション・キャッシュに登録されている場合、イベントがイベント・フィルタに適合すると、そのイベントはそのリスナーが登録されているサーバーのリスナーに配信されます。

応用例の中には、データが保持されているサーバー上のイベントをアプリケーションで処理する必要があるものや、それを実際にデータを管理している構造(バッキング・マップ)で行う必要があるものがあります。そのような場合、バッキング・マップが監視可能なマップであれば、リスナーをバッキング・マップに構成したり、プログラムによってリスナーをバッキング・マップに追加することができます(バッキング・マップが監視可能でない場合、WrapperObservableMapでラップすることにより監視可能になります)。

これらのAPIの詳細は、Oracle Coherence C++ APIリファレンスを参照してください。

14.11 同期イベント・リスナーの使用

イベントの中には、アプリケーション・リスナーがイベントを生成するキャッシュ・サービスを妨害しないように、非同期に配信されるものがあります。まれなケースですが、非同期配信では進行している処理の結果に比べてイベントの順序があいまいになる場合があります。クラスタ・システムのローカル表示が単一スレッドであるかのようにキャッシュAPI操作およびイベントの順序を保証するには、MapListenerでSynchronousListenerマーカー・インタフェースを実装する必要があります。

Coherence自体で同期リスナーを使用する例にニア・キャッシュがあります。これにより、ローカルでキャッシュされたデータを、イベントを使用して無効化できます(通称、Seppuku)。

このAPIの詳細は、Oracle Coherence C++ APIリファレンスを参照してください。

15 トランザクションの実行(C++)

この章では、トランザクション・フレームワークAPIを使用して、C++クライアント使用時にトランザクション内で必ずキャッシュ操作が実行されるようにする手順について説明します。この手順では、トランザクションAPIの詳細な使用方法は説明しません。トランザクションAPIの使用方法の詳細は、『Oracle Coherenceでのアプリケーションの開発』のトランザクション・フレームワークAPIに関する項を参照してください。

この章は、トランザクションの実行に必要な次の各項で構成されています。

- 入力プロセッサ内でのトランザクションAPIの使用方法

- トランザクション入力プロセッサ用のスタブ・クラスの作成

- トランザクション入力プロセッサのユーザー・タイプの登録

- クラスタ側のトランザクション・キャッシュの構成

- クライアント側のリモート・キャッシュの構成

- C++クライアントからのトランザクション入力プロセッサの使用方法

15.1 入力プロセッサ内でのトランザクションAPIの使用方法

C++クライアントは、トランザクション・フレームワークAPIを利用することによって、トランザクション内でキャッシュ操作を実行します。トランザクションAPIは、C++でネイティブではサポートされていないため、入力プロセッサ内で使用する必要があります。入力プロセッサはJavaでクラスタ上に実装され、入力プロセッサのスタブ・クラスはC++でクライアント上に実装されます。いずれのクラスでも、POFを使用して、JavaとC++の間でシリアライズを行います。

例15-1は、トランザクションAPIを使用してトランザクション内で単純なupdate操作を実行する入力プロセッサを示しています。実行時には、拡張プロキシ・サーバーのクラスパス上にクラスを配置する必要があります。

例15-1 拡張クライアント・トランザクション用の入力プロセッサ

package coherence.tests;

import com.tangosol.coherence.transaction.Connection;
import com.tangosol.coherence.transaction.ConnectionFactory;
import com.tangosol.coherence.transaction.DefaultConnectionFactory;
import com.tangosol.coherence.transaction.OptimisticNamedCache;
import
com.tangosol.coherence.transaction.exception.PredicateFailedException;
import com.tangosol.coherence.transaction.exception.RollbackException;
import
com.tangosol.coherence.transaction.exception.UnableToAcquireLockException;
import com.tangosol.util.Filter;
import com.tangosol.util.InvocableMap;
import com.tangosol.util.extractor.IdentityExtractor;
import com.tangosol.util.filter.EqualsFilter;
import com.tangosol.util.processor.AbstractProcessor;

public class MyTxProcessor extends AbstractProcessor implements PortableObject
{
public Object process(InvocableMap.Entry entry)
{
// obtain a connection and transaction cache
ConnectionFactory connFactory = new DefaultConnectionFactory();
Connection conn = connFactory.createConnection("TransactionalCache");
OptimisticNamedCache cache = conn.getNamedCache("MyTxCache");

conn.setAutoCommit(false);

// get a value for an existing entry
String sValue = (String) cache.get("existingEntry");

// create predicate filter
Filter predicate = new EqualsFilter(IdentityExtractor.INSTANCE, sValue);

try
{
// update the previously obtained value
cache.update("existingEntry", "newValue", predicate);
}
catch (PredicateFailedException e)
{
// value was updated after it was read
conn.rollback();
return false;
}
catch (UnableToAcquireLockException e)
{
// row is being updated by another tranaction
conn.rollback();
return false;
}
try
{
conn.commit();
}
catch (RollbackException e)
{
// transaction was rolled back
return false;
}
return true;
}

public void readExternal(PofReader in)
throws IOException
{
}

public void writeExternal(PofWriter out)
throws IOException
{
}
}

15.2 トランザクション入力プロセッサ用のスタブ・クラスの作成

入力プロセッサのスタブ・クラスを使用すると、クライアントはクラスタ上でトランザクション入力プロセッサを利用できます。スタブ・クラスはC++で実装され、POFを使用してシリアライズを行います。POFを使用することにより、C++とJavaの間で入力プロセッサをシリアライズできます。入力プロセッサのスタブ・クラスにはトランザクション・ロジックは必要ありません。これはトランザクション入力プロセッサのスケルトンです。C++でPOFを使用する際の詳細は、第10章「統合オブジェクトの構築(C++)」を参照してください。

例15-2および例15-3は、スタブ・クラスと、例15-1で作成したトランザクション入力プロセッサの関連ヘッダー・ファイルを示しています。この例では、POFの登録はクラス内で実行されます。

例15-2 トランザクション入力プロセッサのC++スタブ・クラス

#include "coherence/tests/MyTxProcessor.hpp"
#include "coherence/io/pof/SystemPofContext.hpp"

COH_OPEN_NAMESPACE2(coherence,tests)
COH_REGISTER_PORTABLE_CLASS(1599, MyTxProcessor);

MyTxProcessor::MyTxProcessor()
{
}

void MyTxProcessor::readExternal(PofReader::Handle hIn)
{
}

void MyTxProcessor::writeExternal(PofWriter::Handle hOut) const
{
}

Object::Holder MyTxProcessor::process(InvocableMap::Entry::Handle hEntry) const
{
return NULL;
}

COH_CLOSE_NAMESPACE2

例15-3 トランザクション入力プロセッサのC++スタブ・クラス・ヘッダー・ファイル

#ifndef COH_TX_EP_HPP
#define COH_TX_EP_HPP

#include "coherence/lang.ns"
#include "coherence/io/pof/PofReader.hpp"
#include "coherence/io/pof/PofWriter.hpp"
#include "coherence/io/pof/PortableObject.hpp"
#include "coherence/util/InvocableMap.hpp"
#include "coherence/util/processor/AbstractProcessor.hpp";

COH_OPEN_NAMESPACE2(coherence,tests)

using coherence::io::pof::PofReader;
using coherence::io::pof::PofWriter;
using coherence::io::pof::PortableObject;
using coherence::util::InvocableMap;
using coherence::util::processor::AbstractProcessor;

class MyTxProcessor
: public class_spec<MyTxProcessor,
extends<AbstractProcessor>,
implements<PortableObject> >

{
friend class factory<MyTxProcessor>;

protected:
MyTxProcessor();

public:
virtual Object::Holder process(InvocableMap::Entry::Handle hEntry) const;

public:
virtual void readExternal(PofReader::Handle hIn);
virtual void writeExternal(PofWriter::Handle hOut) const;
};

COH_CLOSE_NAMESPACE2
#endif // COH_TX_EP_HPP

15.3 トランザクション入力プロセッサのユーザー・タイプの登録

入力プロセッサのクラスは、POFユーザー・タイプとして、クラスタ側のPOF構成ファイルで登録する必要があります。登録の際は、クライアント側でスタブ・クラスの登録に使用した同じタイプIDを使用する必要があります。次の例は、例15-1で作成したMyTxProcessorクラスの登録を示しており、例15-2で登録された同じタイプIDを使用しています。

<?xml version="1.0"?>

<pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config
coherence-pof-config.xsd">
<user-type-list>
<include>coherence-pof-config.xml</include>
<include>txn-pof-config.xml</include>
<user-type>
<type-id>1599</type-id>
<class-name>coherence.tests.MyTxProcessor</class-name>
</user-type>
</user-type-list>
</pof-config>

15.4 クラスタ側のトランザクション・キャッシュの構成

トランザクションを実行するには、クラスタ側のキャッシュ構成ファイルでトランザクション・キャッシュを定義する必要があります。トランザクション・キャッシュは、トランザクション・フレームワークでトランザクション保証を行うために使用します。トランザクション・キャッシュの詳細は、『Oracle Coherenceでのアプリケーションの開発』のトランザクション・キャッシュの定義に関する項を参照してください。

次の例では、MyTxCacheという名前のトランザクション・キャッシュを作成します。これは、例15-1で入力プロセッサによって使用されていたキャッシュ名です。この構成には、リモート・クライアントから入力プロセッサを実行する際に必要なプロキシ・スキームと分散キャッシュ・スキームも含まれています。プロキシは、ポート9099のlocalhostでクライアントのTCP/IP接続を受け入れるように構成します。Coherence*Extend使用時にクラスタ側のキャッシュを構成する方法の詳細は、第4章「Coherence*Extendの設定」を参照してください。

<?xml version='1.0'?>

<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
coherence-cache-config.xsd">
<defaults>
<serializer>pof</serializer>
</defaults>
<caching-scheme-mapping>
<cache-mapping>
<cache-name>MyTxCache</cache-name>
<scheme-name>example-transactional</scheme-name>
</cache-mapping>
<cache-mapping>
<cache-name>dist-example</cache-name>
<scheme-name>example-distributed</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<transactional-scheme>
<scheme-name>example-transactional</scheme-name>
<service-name>TransactionalCache</service-name>
<thread-count>7</thread-count>
<high-units>15M</high-units>
<task-timeout>0</task-timeout>
<autostart>true</autostart>
</transactional-scheme>

<distributed-scheme>
<scheme-name>example-distributed</scheme-name>
<service-name>DistributedCache</service-name>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>

15.5 クライアント側のリモート・キャッシュの構成

クラスタのプロキシに接続してトランザクション入力プロセッサを実行するには、リモート・クライアントにリモート・キャッシュが必要です。リモート・キャッシュは、クライアント側のキャッシュ構成ファイルで定義します。クライアント側のキャッシュを構成する方法の詳細は、第4章「Coherence*Extendの設定」を参照してください。

次の例では、リモート・キャッシュをポート9099のlocalhostに配置されているプロキシに接続するように構成します。また、リモート・キャッシュの名前(dist-example)はトランザクション入力プロセッサの開始時に使用されるクラスタ側のキャッシュの名前と一致している必要があります。

<?xml version='1.0'?>

<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
coherence-cache-config.xsd">
<defaults>
<serializer>pof</serializer>
</defaults>
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-example</cache-name>
<scheme-name>extend</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>30s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>30s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>

15.6 C++クライアントからのトランザクション入力プロセッサの使用方法

クライアントで入力プロセッサのスタブ・クラスを起動する方法は、入力プロセッサを起動する方法と同じです。ただし、実行時にはクラスタ側の入力プロセッサが起動されます。起動がJavaクラスに委任されたことは、クライアント側では認識されません。次の例は、入力プロセッサのスタブ・クラスを使用して、結果的に例15-1で作成したトランザクション入力プロセッサを起動するクライアントを示しています。

String::View vsCacheName = "dist-example";
String::View vsKey       = "AnyKey";

// retrieve the named cache
NamedCache::Handle hCache = CacheFactory::getCache(vsCacheName);

// invoke the cache
Object::View oResult = hCache->invoke(vsKey, MyTxProcessor::create());
std::cout << "Result of extend transaction execution: " << oResult << std::endl;

第IV部

.NET Extendクライアントの作成

Coherence for .NETを使用すると、データ、データ・イベント、データ処理などのCoherenceクラスタ・サービスに、Coherenceクラスタ外部から.NETアプリケーションを使用してアクセスできます。Coherence for .NETは通常、Coherenceキャッシュへのアクセスを必要とするデスクトップ・アプリケーションやWebアプリケーションで使用されます。

Coherence for .NETは、Coherenceクラスタ内で稼働するCoherence*Extendクラスタ・サービス・インスタンスに、高性能なTCP/IPベースの通信レイヤーを使用して接続する軽量の.NETライブラリで構成されます。このライブラリからCoherence*Extendクラスタ・サービスにすべてのクライアント・リクエストが送信され、このサービスは実際のCoherenceクラスタ・サービス(パーティション・キャッシュ・サービス、レプリケーション・キャッシュ・サービスなど)に委任することで、クライアント・リクエストに応答します。

INamedCacheインスタンスは、CacheFactory.GetCache(...) APIコールを使用して取得されます。これが取得されると、クライアントはCoherenceクラスタに組み込まれている場合と同じようにINamedCacheにアクセスします。INamedCacheの操作はリモートのクラスタ・ノードに(TCP/IPを介して)送信されますが、この処理はクライアント・アプリケーションに対して完全に透過的に行われます。

「Coherence for .NET」は次の章で構成されています。

- 第16章「.NETクライアントの構成と使用」

- 第17章「統合オブジェクトの構築(.NET)」

- 第18章「Coherence .NETクライアント・ライブラリの使用」

- 第19章「連続問合せの実行(.NET)」

- 第20章「リモート起動の実行(.NET)」

- 第21章「トランザクションの実行(.NET)」

- 第22章「ASP.NETセッション状態の管理」

16 .NETクライアントの構成と使用

この章では、Coherence for .NETクライアントの設定手順を説明します。

この章には次の項が含まれます:

- 一般的な手順

- Coherence*Extendの構成

- CoherenceのDefaultCacheServerプロセスの起動

- .NETによるキャッシュ参照の取得

- キャッシュに関連付けられたリソースのクリーンアップ

- ネットワーク・フィルタの使用方法

16.1 一般的な手順

Coherence for .NETを構成して使用するには、次の5つの基本的な手順が必要です。

1. クライアント、およびクラスタにある1つ以上のJVMの両方にCoherence*Extendを構成します。詳細は、次の「Coherence*Extendの構成」を参照してください。

2. クライアント、およびクラスタの中でCoherence*Extendのクラスタ・サービスを実行しているすべてのJVMにPOFコンテキストを構成します。「統合オブジェクトの構築(.NET)の概要」を参照してください。

3. Coherence for .NET APIを使用して.NETクライアント・アプリケーションを実装します。「Coherence .NET APIの使用」を参照してください。

4. Coherenceクラスタが稼動中であることを確認します。「CoherenceのDefaultCacheServerプロセスの起動」を参照してください。

5. .NETクライアント・アプリケーションを起動します。

16.2 Coherence*Extendの構成

Coherence*Extendを構成するには、クラスタ側とクライアント側両方のキャッシュ構成ディスクリプタに適切な構成要素を追加する必要があります。クラスタ側のキャッシュ構成要素からCoherenceのDefaultCacheServerに対して、Coherence*Extendクライアントから受信したTCP/IPリクエストをリスニングするCoherence*Extendクラスタ・サービスを開始するように指示されます。クライアント側のキャッシュ構成要素は、クラスタの中でCoherence*Extendクラスタ・サービスを実行している1台以上のサーバーのIPアドレスとポートを特定するためにクライアント・ライブラリで使用されます。これにより、ライブラリをクラスタに接続できます。この構成では、接続やリクエストのタイムアウトなど、接続に関連する様々なパラメータも記述します。

16.2.1 クラスタでのCoherence*Extendの構成

Coherence*ExtendクライアントをCoherenceクラスタに接続するには、そのクラスタにある1つ以上のDefaultCacheServer JVMで、TCP/IP Coherence*Extendクラスタ・サービスを実行している必要があります。このサービスを実行するようにDefaultCacheServerを構成するには、そのDefaultCacheServerで使用するキャッシュ構成ディスクリプタに、tcp-acceptor子要素を持つproxy-scheme要素を追加する必要があります。これを例16-1に示します。

例16-1 Coherence*Extendに対応したデフォルト・キャッシュ・サーバーの構成

<?xml version="1.0"?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-*</cache-name>
<scheme-name>dist-default</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<distributed-scheme>
<scheme-name>dist-default</scheme-name>
<lease-granularity>member</lease-granularity>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>

このキャッシュ構成ディスクリプタは、2つのクラスタ・サービスを定義します。これは、リモートCoherence*ExtendクライアントをTCP/IPでCoherenceクラスタに接続できるようにするサービス、および標準のパーティション・キャッシュ・サービスです。このディスクリプタはDefaultCacheServerで使用しているため、クラスタ・サービスの終了時に自動的に再起動するように、各サービスのautostart構成要素をtrueに設定しておくことが重要です。proxy-scheme要素には、tcp-acceptorという子要素があり、この子要素には、TCP/IPを介してクライアント接続リクエストを受け入れるために必要なTCP/IP固有の情報がすべて含まれます。

前述のように構成されたCoherence*Extendのクラスタ・サービスは、localhostアドレスとport 9099で、受信リクエストをリスニングします。たとえば、dist-extendというCoherenceキャッシュにクライアントが接続しようとすると、Coherence*Extendのクラスタ・サービスがNamedCacheへの後続リクエストを同じ名前で代行します。その名前は、この例ではパーティション・キャッシュとなります。

16.2.2 クライアントでのCoherence*Extendの構成

Coherence*Extendクライアントでは、Coherenceクラスタ内で実行されるCoherence*Extendクラスタ・サービスへの接続およびCoherence*Extendクラスタ・サービスとの通信に、キャッシュ構成ディスクリプタの要素initiator-config内の情報が使用されます。これを例16-2に示します。

例16-2 リモートCoherenceクラスタに接続するための構成

<?xml version='1.0'?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend</cache-name>
<scheme-name>extend-dist</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>

このキャッシュ構成ディスクリプタは、リモートCoherenceクラスタに接続するキャッシング・スキームを定義します。remote-cache-scheme要素には、tcp-initiatorという子要素があり、この子要素には、リモートCoherenceクラスタ内でCoherence*Extendクラスタ・サービスが実行されているクライアントへの接続に必要なTCP/IP固有の情報がすべて含まれます。

クライアント・アプリケーションで、たとえばdist-extendという名前を使用してCacheFactoryで名前付きキャッシュを取得すると、Coherence*Extendクライアントは(アドレスlocalhostとport 9099による)TCP/IPを使用してCoherenceクラスタに接続し、INamedCache実装を返します。この実装は、リモート・クラスタの中で実行している同名のNamedCacheにリクエストをルーティングする機能を持っています。remote-addresses構成要素には、子要素socket-addressを複数記述できます。Coherence*Extendのクライアントは、記載されたアドレスをすべて試すか、またはTCP/IP接続が確立されるまで、アドレスへの接続をランダムに試行します。

16.2.2.1 .NETクライアント用ローカル・キャッシュの定義

ローカル・キャッシュは、特定の.NETアプリケーションに対してローカルである(つまりアプリケーション内に完全に含まれる)キャッシュです。ローカル・キャッシュの特に興味深い属性について、次に示します。

- ローカル・キャッシュは、リモート・キャッシュが実装するものと同じ標準キャッシュ・インタフェースを実装します(ICache、IObservableCache、IConcurrentCache、IQueryCacheおよびIInvocableCache)。つまり、使用するキャッシュがローカルであってもリモートであっても、プログラミング上の違いはありません。

- ローカル・キャッシュのサイズは制限できます。サイズの制限とは、ローカル・キャッシュでキャッシュするエントリ数を制限し、キャッシュがいっぱいになったらエントリを自動的に削除できることを意味します。さらに、エントリのサイジングとエビクション・ポリシーの両方をカスタマイズできます。たとえば、キャッシュされたエントリで使用されるメモリーに基づいてキャッシュ・サイズを制限できます。デフォルトのエビクション・ポリシーでは、対数曲線で測定された、最も頻繁に使用する(MFU)情報と最後に使用した(MRU)情報の組合せを使用して削除するキャッシュ項目が決定されます。このアルゴリズムは、短期キャッシュと長期キャッシュの両方に対して十分に機能し、頻度と新しさのバランスをとってキャッシュ・スラッシングを回避するため、最適な汎用エビクション・アルゴリズムであるといえます。また、ピュアLRUアルゴリズムおよびピュアLFUアルゴリズムがサポートされ、カスタム・エビクション・ポリシーのプラグイン機能もサポートされています。

- ローカル・キャッシュはキャッシュ・エントリの自動失効をサポートしています。つまり、キャッシュ内の各キャッシュ・エントリに存続時間の値を割り当てることができます。さらに、定期的または事前に設定した時刻にフラッシュするようキャッシュ全体を構成できます。

- ローカル・キャッシュはスレッド・セーフで、高い並行性を備えています。

- ローカル・キャッシュでは、キャッシュのget統計が提供されます。ここには、キャッシュ・ヒットおよびキャッシュ・ミスの統計情報が保持されます。これらの実行時統計は、キャッシュの有効性を正確に推定できるため、キャッシュ実行時にそのサイズ制限や自動失効の設定を適宜調整できます。

Coherence for .NETのローカル・キャッシュ機能は、Tangosol.Net.Cache.LocalCacheクラスによって実装されます。したがって、このキャッシュはプログラムでインスタンス化して構成することが可能ですが、Coherence for .NETの他のキャッシュ同様、LocalCacheはキャッシュ構成ディスクリプタを使用して構成することをお薦めします。

ローカル・キャッシュの主要な構成要素は<local-scheme>です。ローカル・キャッシュは通常、ニアスキームのフロント層としてなど、他のキャッシュ・スキーム内にネストされています。このため、この要素はcoherence-cache-configファイル内の、<caching-schemes>、<distributed-scheme>、<replicated-scheme>、<optimistic-scheme>、<near-scheme>、<overflow-scheme>および<read-write-backing-map>の各要素のサブ要素として使用できます。

<local-scheme>には、キャッシュの特性を定義できるいくつかのサブ要素がオプションで用意されています。たとえば、<low-units>および<high-units>サブ要素はキャッシュのサイズを制限します。キャッシュが最大許容サイズに達すると、指定されたエビクション・ポリシー(<eviction-policy>)に従って削除対象エントリが決定され、指定されたより小さなサイズに戻ります。エントリおよびサイズの制限は、該当するスキームの単位換算カリキュレータ(<unit-calculator>)で計算される単位で測定されます。カスタム・クラスを定義するには、<eviction-policy>要素と<unit-calculator>要素の両方の<class-scheme>サブ要素を使用して、必要に応じてカスタム動作を指定します。

キャッシュの有効期間も制限できます。<expiry-delay>サブ要素は、前回の更新からエントリが期限切れとしてマークされるまでの、キャッシュでエントリが保持される期間を指定します。期限切れのエントリを読み取るには、構成済のキャッシュ・ストア(<cachestore-scheme>)からエントリをリロードすることになります。期限切れになった値は、フラッシュ遅延に基づいてキャッシュから定期的に破棄されます。

<cachestore-scheme>が指定されていない場合、キャッシュされたデータはメモリー内に存在して、キャッシュに対して実行された操作のみが反映されます。使用可能なすべてのサブ要素の詳細は、<local-scheme>を参照してください。

例16-3は、ニア・キャッシュの構成を示しています。

例16-3 ローカル・キャッシュの構成

<?xml version='1.0'?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>example-local-cache</cache-name>
<scheme-name>example-local</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<local-scheme>
<scheme-name>example-local</scheme-name>
<eviction-policy>LRU</eviction-policy>
<high-units>32000</high-units>
<low-units>10</low-units>
<unit-calculator>FIXED</unit-calculator>
<expiry-delay>10ms</expiry-delay>
<cachestore-scheme>
<class-scheme>
<class-name>ExampleCacheStore</class-name>
</class-scheme>
</cachestore-scheme>
<pre-load>true</pre-load>
</local-scheme>
</caching-schemes>
</cache-config>

16.2.2.2 .NETクライアント用ニア・キャッシュの定義

この項では、Coherence for .NETクライアントに関係するニア・キャッシュについて説明します。ニア・キャッシュの概念、その構成およびバック層との同期を維持する方法の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

Coherence for .NETでのニア・キャッシュは、リードスルー/ライトスルー方式を使用してフロント・キャッシュとバック・キャッシュをラップするINamedCache実装です。バック・キャッシュがIObservableCacheインタフェースを実装している場合、ニア・キャッシュはListen None、Listen Present、Listen All、Listen Autoのいずれかの戦略を使用して、バック・キャッシュで変更された可能性のあるフロント・キャッシュ・エントリを無効化します。

Tangosol.Net.Cache.NearCacheクラスを使用すると、.NETニア・キャッシュ機能をプログラムでインスタンス化して構成できます。ただし、ニア・キャッシュの構成にはキャッシュ構成ディスクリプタを使用することをお薦めします。

一般的なニア・キャッシュは、ローカル・キャッシュ(スレッド・セーフで並行性が高く、かつサイズが制限されていて、場合によっては自動的に失効するもの)をフロント・キャッシュとして使用し、リモート・キャッシュをバック・キャッシュとして使用するように構成されます。ニア・キャッシュの構成には、2つの子要素を持つnear-scheme要素が使用されます。1つはローカル(フロント)キャッシュを構成するためのfront-scheme、もう1つはリモート(バック)キャッシュを定義するためのback-schemeです。

ニア・キャッシュは、coherence-cache-configファイルの<near-scheme>要素を使用して構成します。この要素には、ローカル(フロント層)キャッシュを構成するためのfront-schemeと、リモート(バック層)キャッシュを定義するためのback-schemeの2つのサブ要素が要求されます。フロント層には通常、ローカル・キャッシュ(<local-scheme>)を選択しますが、JVMヒープ・ベース以外のキャッシュ(<external-scheme>または<paged-external-scheme>)またはJavaオブジェクトに基づくスキーム(<class-scheme>)も使用できます。

リモート、すなわちバック層のキャッシュは、<back-scheme>要素を使用して記述します。バック層のキャッシュには、分散キャッシュ(<distributed-scheme>)またはリモート・キャッシュ(<remote-cache-scheme>)を定義できます。<remote-cache-scheme>要素を使用すると、現在のクラスタの外部からクラスタ・キャッシュを使用できます。

<near-scheme>のオプションのサブ要素には、フロント層とバック層のオブジェクトの同期を維持する戦略を指定する<invalidation-strategy>、およびキャッシュで発生したイベントの通知を受け取るリスナーを指定する<listener>などがあります。

例16-4は、ニア・キャッシュの構成を示しています。

例16-4 ニア・キャッシュの構成

<?xml version="1.0"?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-extend-near</cache-name>
<scheme-name>extend-near</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<near-scheme>
<scheme-name>extend-near</scheme-name>
<front-scheme>
<local-scheme>
<high-units>1000</high-units>
</local-scheme>
</front-scheme>
<back-scheme>
<remote-cache-scheme>
<scheme-ref>extend-dist</scheme-ref>
</remote-cache-scheme>
</back-scheme>
<invalidation-strategy>all</invalidation-strategy>
</near-scheme>

<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>10s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>5s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>

16.2.3 接続エラーの検出とフェイルオーバー

ネットワーク、ソフトウェア、ハードウェアなどの障害によってクライアントとクラスタ間の接続が切断されたことをCoherence*Extendのクライアント・サービスが検出すると、このCoherence*Extendのクライアント・サービスの実装(ICacheServiceまたはIInvocationService)によってMemberEventHandlerデリゲートを使用してMemberEventType.Leftイベントが発生し、このクライアント・サービスは停止します。クライアント・アプリケーションがその後もこのサービスを使用しようとする場合には、サービス自体が自動的に再起動してクラスタへの再接続を試行します。このサービスが接続に成功するとMemberEventType.Joinedイベントが発生し、接続に失敗するとクライアント・アプリケーションに修復できないエラーの例外がスローされます。

Coherence*Extendサービスには、接続の切断を検出するためのメカニズムがいくつか用意されています。その中には、(Extend-TCPのTCP/IPのように)基底プロトコルに固有のものもあれば、サービス自体に実装されるものもあります。後者のメカニズムは、<outgoing-message-handler要素を使用して構成されます。この要素の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。特に、<request-timeout値は、リクエストを中止するまでの応答を待機する時間を制御します。<heartbeat-intervalおよび<heartbeat-timeout値は、接続を閉じるまでのpingリクエストへの応答を待機する時間を制御します。

16.3 CoherenceのDefaultCacheServerプロセスの起動

すでに説明したクラスタ側のCoherenceキャッシュ構成を使用するDefaultCacheServerを起動し、TCP/IPを使用してCoherence for .NETクライアントをCoherenceクラスタに接続できるようにするには、次の手順を実行する必要があります。

1. 現在のディレクトリをOracle Coherenceのライブラリ・ディレクトリに変更します(Windowsの場合は%COHERENCE_HOME%\lib、UNIXの場合は$COHERENCE_HOME/lib)。

2. Javaコマンドが実行されるようにパスを構成します。

3. DefaultCacheServerコマンドライン・アプリケーションを起動します。その際に、-Dtangosol.coherence.cacheconfigシステム・プロパティを、すでに説明したクラスタ側Coherenceキャッシュ構成ディスクリプタの場所に設定します。

例16-5にコマンドラインのサンプルを示します。

例16-5 Coherenceのデフォルト・キャッシュ・サーバーを起動するコマンド

java -cp coherence.jar -Dtangosol.coherence.cacheconfig=file://<path to the server-side cache configuration descriptor> com.tangosol.net.DefaultCacheServer

16.4 .NETによるキャッシュ参照の取得

CacheFactoryクラスを使用することによって、構成済キャッシュへの参照を名前によって取得できます。

例16-6 キャッシュへの参照の取得

INamedCache cache = CacheFactory.GetCache("example-local-cache");

16.5 キャッシュに関連付けられたリソースのクリーンアップ

すべてのINamedCache実装のインスタンスは、LocalCacheを含め、不要になった時点でINamedCache.Release()メソッドをコールして明示的に解放し、これらのインスタンスで保持されているリソースをすべて解放する必要があります。

特定のINamedCacheがアプリケーションの継続期間を通して使用される場合、リソースはそのアプリケーションがシャットダウンされたとき、または停止したときにクリーンアップされます。ただし、わずかの間だけ使用される場合は、使い終わった時点でアプリケーションからRelease()メソッドをコールする必要があります。

または、INamedCacheがIDisposableを拡張し、すべてのキャッシュ実装がIDisposable.Dispose()のコールをINamedCache.Release()に委任しているという事実を利用する方法もあります。単一メソッド内でキャッシュ・インスタンスを取得および解放する必要がある場合、次のusingブロックを使用してそれを実現できます。

例16-7 キャッシュへの参照の取得と解放

using (INamedCache cache = CacheFactory.GetCache("my-cache"))
{
// use cache as usual
}

usingブロックが終了すると、INamedCacheインスタンスでIDisposable.Dispose()がコールされ、そのインスタンスに関連付けられているすべてのリソースが解放されます。

16.6 ネットワーク・フィルタの使用方法

ネットワーク・フィルタは、TCP/IPソケットを介して送信されるデータの変換を、プラガブルな階層化された方法で実行できるようにするメカニズムです。Coherence for .NETでは、カスタム・フィルタをサポートして、ユーザーがネットワーク・トラフィックの内容を変更できるようにしています。また一般に、データの圧縮および暗号化にもCoherence for .NETが使用されます。

この項の内容は次のとおりです。

- カスタム・フィルタ

- フィルタの構成

16.6.1 カスタム・フィルタ

フィルタを作成するには、Tangosol.IO.IWrapperStreamFactoryインタフェース、およびオプションでTangosol.Util.IXmlConfigurableインタフェースを実装する.NETクラスを作成します。IWrapperStreamFactoryインタフェースは、次の2つのメソッドを定義します。

例16-8 IWrapperStreamFactoryインタフェースのメソッド

Stream GetInputStream(Stream stream);
Stream GetOutputStream(Stream stream);

この2つのメソッドは、ラップ(フィルタリング)対象のI/Oストリーム(入力では受信メッセージ、出力では送信メッセージ)を提供し、元のストリームをラップするストリームの返送を求めます。このメソッドは、個々の受信メッセージと送信メッセージに対してコールされます。

16.6.2 フィルタの構成

フィルタは2つの手順で構成します。最初に、オペレーション・オーバーライド・ファイルの<filters XML要素でフィルタを宣言します。フィルタの構成方法の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

...
<cluster-config>
<filters>
<filter>
<filter-name>gzip</filter-name>
<filter-class>Tangosol.Net.CompressionFilter, Coherence</filter-class>
</filter>
</filters>
</cluster-config>
...

注意:

GZip圧縮フィルタは、.NETフレームワークのバージョン2.0以上でサポートされています。

2番目の手順では、1つ以上の特定のサービスにフィルタをアタッチします。特定のサービス(ExtendTcpCacheServiceサービスなど)に対してフィルタを指定するには、キャッシュ構成ファイルのサービス宣言で、<use-filters>要素に<filter-name>要素を追加します。

...
<remote-cache-scheme>
<scheme-name>extend-direct</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
...
<use-filters>
<filter-name>gzip</filter-name>
</use-filters>
...
</initiator-config>
</remote-cache-scheme>
...

フィルタがIXmlConfigurableを実装する場合は、フィルタがインスタンス化された後に、CoherenceでConfigプロパティが次のXML要素に設定されます。

<config>
<param1>value1</param1>
<param2>value2</param2>
</config>

17 統合オブジェクトの構築(.NET)

この章では、.NETクライアント作成時にPortable Object Format (POF)シリアライズ形式を使用する手順を説明します。

この章は次の各項で構成されています。

- 統合オブジェクトの構築(.NET)の概要

- IPortableObject実装の作成

- Javaバージョンの.NETオブジェクトの実装

- .NETクライアントでのカスタム型の登録

- クラスタでのカスタム型の登録

- 進化可能な移植性のあるユーザー定義型

- 変更なしで型を移植可能にする

- POFオブジェクト参照の使用方法

- POF注釈を使用したオブジェクトのシリアライズ

17.1 統合オブジェクトの構築(.NET)の概要

Coherenceキャッシュは、値オブジェクトをキャッシュするために使用されます。.NETクライアントがCoherence JVMと正常に通信するためには、プラットフォームに依存しないシリアライズ形式が必要になります。これにより、.NETクライアントとCoherence JVM (Coherence*Extend Javaクライアントを含む)の両方で、Coherenceキャッシュに格納されている値オブジェクトを正しくシリアライズおよびデシリアライズできるようになります。Coherence for .NETクライアント・ライブラリおよびCoherence*Extendクラスタ・サービスでは、Portable Object Format (POF)というシリアライズ形式が使用されます。POFを使用すると、値オブジェクトのプラットフォームおよび元の言語と関係ない方法で、値オブジェクトをバイナリ・ストリームにエンコードできます。POFバイナリ・ストリームの詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

POFでは、共通の.NET型がすべてそのままサポートされます。カスタムの.NETクラスも次の手順でPOFストリームにシリアライズできます

1. IPortableObjectインタフェースを実装する.NETクラスを作成します(「IPortableObject実装の作成」を参照)。

2. 同様に、PortableObjectインタフェースを実装する、対応するJavaクラスを作成します(「PortableObject実装の作成(Java)」を参照)。

3. カスタムの.NETクラスをクライアントに登録します(「.NETクライアントでのカスタム型の登録」を参照)。

4. Coherence*Extendクラスタ・サービスを実行している各サーバーにカスタムのJavaクラスを登録します(「クラスタでのカスタム型の登録」を参照)。

ここまでの手順が完了すると、組込みのデータ型と同じようにカスタムの.NETクラスをCoherenceキャッシュにキャッシュできるようになります。さらに対応するJavaクラスを使用すれば、それらの型をCoherenceまたはCoherence*Extend JVMから取得し、操作して、格納できます。

17.2 IPortableObject実装の作成

IPortableObjectを実装する各クラスは、自身の状態をPOFデータ・ストリームにシリアライズし、POFデータ・ストリームからデシリアライズできます。この処理は、ReadExternalメソッド(デシリアライズ)およびWriteExternalメソッド(シリアライズ)で行われます。概念上は、すべてのユーザー定義型が0個以上の索引付き値(プロパティ)で構成されており、それらが1つずつPOFデータ・ストリームから読み取られ、POFデータ・ストリームに書き込まれます。移植可能なクラスには、IPortableObjectインタフェースの実装が必要であること以外の唯一の要件として、デフォルト・コンストラクタが必要です。これにより、POFデシリアライザで、デシリアライズ時にクラスのインスタンスを作成できるようになります。

例17-1は、移植可能なユーザー定義クラスを示しています。

例17-1 移植可能なユーザー定義クラス

public class ContactInfo : IPortableObject
{
private string name;
private string street;
private string city;
private string state;
private string zip;
public ContactInfo()
{}

public ContactInfo(string name, string street, string city, string state, string zip)
{
Name   = name;
Street = street;
City   = city;
State  = state;
Zip    = zip;
}
public void ReadExternal(IPofReader reader)
{
Name   = reader.ReadString(0);
Street = reader.ReadString(1);
City   = reader.ReadString(2);
State  = reader.ReadString(3);
Zip    = reader.ReadString(4);
}
public void WriteExternal(IPofWriter writer)
{
writer.WriteString(0, Name);
writer.WriteString(1, Street);
writer.WriteString(2, City);
writer.WriteString(3, State);
writer.WriteString(4, Zip);
}
// property definitions ommitted for brevity
}

17.3 Javaバージョンの.NETオブジェクトの実装

POFの使用によって、並列のJava実装を必要とせずに、キーおよび値オブジェクトをクラスタ内に格納できます。これは、基本的なgetとputベースの操作を実行する場合に適しています。さらに、PofExtractorおよびPofUpdater APIでシリアライズされたオブジェクトを直接操作することにより、並列のJava実装が特定の状況で必要なくなります。ただし、高度なデータ・グリッド機能を使用する場合は、データ・オブジェクトのシリアライズ表現を保持するのではなく、Javaベースのキャッシュ・サーバーを使用してデータ・オブジェクトと対話できる必要があります。Java実装は、キャッシュ・サーバーに配置される必要があり、オブジェクトと対話し、そのプロパティにアクセスするために使用します。JavaバージョンのPOFでシリアライズ可能にする方法は前述の例とほぼ同じで、「PortableObject実装の作成(Java)」で説明されています。詳細は、com.tangosol.io.pof.PortableObjectとcom.tangosol.io.pof.PofSerializerのAPIを参照してください。これらのAPIは、.NETの方法と互換性があります。

並列のJava実装の組込みが必要になる状況

基本的なgetとputの操作よりも高度な多くのデータ・グリッド機能では、オブジェクトがクラスタ内に並列のJava実装を持つことを必要とします。これらの機能は、次のとおりです。

- 問合せ

- フィルタ

- 入力プロセッサとアグリゲータ

- データ・ソースの永続性

キーの関連付けチェックの遅延

キー・クラスは、クラスタ側Java実装を必要としません。これはIKeyAssociationインタフェースを使用してデータのアフィニティを指定している場合でも同様です。キー・クラスは、クライアント側でチェックされ、修飾されたバイナリがクラスタによって作成および使用されます。ただし、キーの関連付けをJavaキー・クラスに依存している既存のクライアント実装は、Javaキー・クラスの使用を強制するためにdefer-key-association-checkパラメータを設定する必要があります。キーの関連付けを使用する既存クライアント・アプリケーションで、クライアント側のキー・バイナリを利用する場合は、getAssociatedKey()実装を既存のJavaクラスから対応するクライアント・クラスに移植する必要があります(IKeyAssociation.AssociatedKeyを参照)。

キーの関連付け処理をExtendクライアントによってではなくクラスタ側で実行するには、クライアント側キャッシュの構成で<remote-cache-scheme>要素の<defer-key-association-check>要素をtrueに設定します。例:

<remote-cache-scheme>
...
<defer-key-association-check>true</defer-key-association-check>
</remote-cache-scheme>

注意:

パラメータがtrueに設定されている場合、Javaキー・クラス実装は、キーの関連付けを使用していない場合でも、クラスタに存在する必要があります。

17.3.1 PortableObject実装の作成(Java)

Javaでの移植可能なクラスの実装は、.NETでの実装と非常によく似ています。例17-2は、例17-1の.NETクラスをJavaで実現した場合を示しています。

例17-2 Javaでのユーザー定義クラス

public class ContactInfo implements PortableObject
{    private String m_sName;

private String m_sStreet;
private String m_sCity;
private String m_sState;
private String m_sZip;
public ContactInfo()
{
}
public ContactInfo(String sName, String sStreet, String sCity, String sState, String sZip)
{
setName(sName);
setStreet(sStreet);
setCity(sCity);
setState(sState);
setZip(sZip);
}
public void readExternal(PofReader reader)
throws IOException
{
setName(reader.readString(0));
setStreet(reader.readString(1));
setCity(reader.readString(2));
setState(reader.readString(3));
setZip(reader.readString(4));
}
public void writeExternal(PofWriter writer)
throws IOException
{
writer.writeString(0, getName());
writer.writeString(1, getStreet());
writer.writeString(2, getCity());
writer.writeString(3, getState());
writer.writeString(4, getZip());
}
// accessor methods omitted for brevity
}

17.4 .NETクライアントでのカスタム型の登録

各POFユーザー定義型は、POFストリーム内で整数値として表されます。したがって、POFには、ユーザー定義型をそのエンコードされた型識別子にマップするための外部メカニズムが必要です(また、この逆の場合も同様です)。このメカニズムでは、XML構成ファイルを使用してマッピング情報が格納されます。これを例17-3に示します。POF構成要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

例17-3 POFユーザー定義型構成ファイルへのマッピング情報の格納

<?xml version="1.0"?>
<pof-config xmlns="http://schemas.tangosol.com/pof">
<user-type-list>
<!-- include all "standard" Coherence POF user types -->
<include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml
</include>
<!-- include all application POF user types -->
<user-type>
<type-id>1001</type-id>
<class-name>My.Example.ContactInfo, MyAssembly</class-name>
</user-type>
</user-type-list>
</pof-config>

次の点に注意してください。

- カスタム型の型識別子は1001以上の数値で始まる必要があります。1000より小さい数値は内部使用に予約されています。この例に示すように、<user-type-list>にはcoherence-pof-config.xmlファイルが含まれます。これにはCoherence固有のユーザー型が定義されており、そのユーザー型をすべてのPOF構成ファイルに含める必要があります。

- class-name要素内では完全に修飾された型名を指定する必要はありません。型とアセンブリ名を指定すれば十分です。

型識別子とカスタム型の間のマッピングを構成したら、キャッシュ構成ディスクリプタにserializer要素を追加して、それらのマッピングを使用するようCoherence for .NETを構成する必要があります。たとえば、例17-3に示したユーザー定義型のマッピングがmy-dotnet-pof-config.xmlに保存されている場合は、例17-4に示すようにserializer要素を指定する必要があります。

例17-4 キャッシュ構成ファイルでのserializerの使用

<remote-cache-scheme>
<scheme-name>extend-direct</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
...
<serializer>
<class-name>Tangosol.IO.Pof.ConfigurablePofContext, Coherence
</class-name>
<init-params>
<init-param>
<param-type>string</param-type>
<param-value>my-dotnet-pof-config.xml</param-value>
</init-param>
</init-params>
</serializer>
</initiator-config>
</remote-cache-scheme>

シリアライザを明示的に指定しない場合は、ConfigurablePofContext型がPOFシリアライザとして使用されます。これはpof-config.xmlというデフォルトの構成ファイルを使用します。Coherence .NETアプリケーションでは、アプリケーションのデプロイ先フォルダと、Webアプリケーションの場合はWebアプリケーションのルートの両方で、デフォルトのPOF構成ファイルが検索されます。POF構成ファイルが見つからない場合は、Coherence for .NETアプリケーション構成ファイルのpof-config要素の内容によるファイルの特定が試行されます。例:

例17-5 POF構成ファイルの指定

<?xml version="1.0"?>
<configuration>
<configSections>
<section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence"/>
</configSections>
<coherence>
<pof-config>my-dotnet-pof-config.xml</pof-config>
</coherence>
</configuration>

17.5 クラスタでのカスタム型の登録

TCP/IP Coherence*Extendクラスタ・サービスを実行しているCoherenceノードでカスタム型のオブジェクトを送受信できるようにするには、各ノードに、カスタム型の類似したPOF構成ファイルが必要です。

クラスタ側のPOF構成ファイルは、クライアントで作成された構成ファイルと似ています。唯一の違いは、class-name要素で.NETクラス名のかわりに完全修飾されたJavaクラス名を指定する必要がある点です。

例17-6は、クラスタ側のPOF構成ファイルのサンプル(my-java-pof-config.xml)を示しています。

例17-6 クラスタ側のPOF構成ファイル

<?xml version="1.0"?>

<pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config
coherence-pof-config.xsd">
<user-type-list>
<!-- include all "standard" Coherence POF user types -->
<include>coherence-pof-config.xml</include>
<!-- include all application POF user types -->
<user-type>
<type-id>1001</type-id>
<class-name>com.mycompany.example.ContactInfo</class-name>
</user-type>
</user-type-list>
</pof-config>

カスタム型を追加したら、オブジェクトのシリアライズ時に各自のPOF構成ファイルが使用されるようサーバーを構成する必要があります。これを例17-7に示します。

例17-7 POF構成ファイルを使用するためのサーバーの構成

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
...
<serializer>
<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
<init-params>
<init-param>
<param-type>string</param-type>
<param-value>my-java-pof-config.xml</param-value>
</init-param>
</init-params>
</serializer>
</acceptor-config>
...
</proxy-scheme>

17.6 進化可能な移植性のあるユーザー定義型

PIF-POFは、シリアライズされた形式の移植可能なユーザー定義型の前方互換性および下位互換性をネイティブにサポートします。.NETでは、ユーザー定義型でIPortableObjectインタフェースのかわりにIEvolvablePortableObjectインタフェースを実装することで、このサポートが実現します。IEvolvablePortableObjectインタフェースは、IPortableObjectとIEvolvableの両方のインタフェースを拡張するマーカー・インタフェースです。IEvolvableインタフェースは、型のバージョニングをサポートする3つのプロパティを追加します。IEvolvableクラスには整数のバージョン識別子n (n >= 0)が含まれていますシリアライズされた形式のIEvolvableクラスのコンテンツ、セマンティクス、またはそれら両方が変更されると、このバージョン識別子が引き上げられます。2つのバージョン識別子n1とn2は、n1 == n2であれば同じバージョンを示し、n2 > n1であればn2のバージョンがn1のバージョンより新しいことを示します。

IEvolvableインタフェースは、データの追加による型の進化をサポートするように設計されています。あるデータに前のバージョンの型が依存している場合、そのデータを安全に削除することはできません。同様に、データの前の構造またはセマンティクスに前のバージョンの型が依存している場合、そのデータの構造またはセマンティクスを前のバージョンから安全に変更することはできません。

IEvolvableオブジェクトがデシリアライズされる場合は、新しいバージョンの型に追加された未知のデータ、およびそのデータ形式のバージョン識別子が保持されます。その後、このIEvolvableオブジェクトがシリアライズされると、保持されたバージョン識別子と未知の将来データがオブジェクトに取り込まれます。

古いバージョンを示すバージョン識別子を持つデータ・ストリームからIEvolvableオブジェクトをデシリアライズする場合は、その古いバージョン以降に追加されたデータ・フィールドやプロパティの値をデフォルトに設定し、計算する必要があります。その後、このIEvolvableオブジェクトがシリアライズされると、そのバージョン識別子と全データがオブジェクトに取り込まれます。この場合は未知の将来データがないことに注意してください。将来データは、データ・ストリームのバージョンがIEvolvable型のバージョンよりも新しい場合にのみ存在します。

例17-8は、クラスの進化をサポートするように.NET型のContactInfoを変更する方法を示しています。

例17-8 クラスの進化をサポートするようにクラスを変更する

public class ContactInfo : IEvolvablePortableObject
{
private string name;
private string street;
private string city;
private string state;
private string zip;
// IEvolvable members
private int    version;
private byte[] data;
public ContactInfo()
{}
public ContactInfo(string name, string street, string city, string state, string zip)
{
Name   = name;
Street = street;
City   = city;
State  = state;
Zip    = zip;
}
public void ReadExternal(IPofReader reader)
{
Name   = reader.ReadString(0);
Street = reader.ReadString(1);
City   = reader.ReadString(2);
State  = reader.ReadString(3);
Zip    = reader.ReadString(4);
}
public void WriteExternal(IPofWriter writer)
{
writer.WriteString(0, Name);
writer.WriteString(1, Street);
writer.WriteString(2, City);
writer.WriteString(3, State);
writer.WriteString(4, Zip);
}
public int DataVersion
{
get { return version; }
set { version = value; }
}
public byte[] FutureData
{
get { return data; }
set { data = value; }
}
public int ImplVersion
{
get { return 0; }
}
// property definitions ommitted for brevity
}

同様に、Java型のContactInfoは、EvolvablePortableObjectインタフェースを実装することでクラスの進化をサポートするように変更できます。

例17-9 クラスの進化をサポートするようにJava型のクラスを変更する

public class ContactInfo
implements EvolvablePortableObject
{
private String m_sName;
private String m_sStreet;
private String m_sCity;
private String m_sState;
private String m_sZip;

// Evolvable members
private int    m_nVersion;
private byte[] m_abData;

public ContactInfo()
{}

public ContactInfo(String sName, String sStreet, String sCity,
String sState, String sZip)
{
setName(sName);
setStreet(sStreet);
setCity(sCity);
setState(sState);
setZip(sZip);
}

public void readExternal(PofReader reader)
throws IOException
{
setName(reader.readString(0));
setStreet(reader.readString(1));
setCity(reader.readString(2));
setState(reader.readString(3));
setZip(reader.readString(4));
}

public void writeExternal(PofWriter writer)
throws IOException
{
writer.writeString(0, getName());
writer.writeString(1, getStreet());
writer.writeString(2, getCity());
writer.writeString(3, getState());
writer.writeString(4, getZip());
}

public int getDataVersion()
{
return m_nVersion;
}

public void setDataVersion(int nVersion)        {
m_nVersion = nVersion;
}

public Binary getFutureData()
{
return m_binData;
}

public void setFutureData(Binary binFuture)
{
m_binData = binFuture;
}

public int getImplVersion()
{
return 0;
}

// accessor methods omitted for brevity
}

17.7 変更なしで型を移植可能にする

既存のユーザー定義型を移植可能にする変更が望ましくない場合、または不可能な場合があります。その場合は、IPofSerializerの実装(.NET)、PofSerializerインタフェースの実装(Java)、またはその両方を作成することで、ユーザー定義型の移植可能なシリアライズを外部化できます。

例17-10は、ContactInfoのIPofSerializerインタフェースの実装を示しています。

例17-10 .NET型のIPofSerializerの実装

public class ContactInfoSerializer : IPofSerializer
{
public object Deserialize(IPofReader reader)
{
string name   = reader.ReadString(0);
string street = reader.ReadString(1);
string city   = reader.ReadString(2);
string state  = reader.ReadString(3);
string zip    = reader.ReadString(4);

ContactInfo info = new ContactInfo(name, street, city, state, zip);
info.DataVersion = reader.VersionId;
info.FutureData  = reader.ReadRemainder();

return info;
}

public void Serialize(IPofWriter writer, object o)
{
ContactInfo info = (ContactInfo) o;

writer.VersionId = Math.Max(info.DataVersion, info.ImplVersion);
writer.WriteString(0, info.Name);
writer.WriteString(1, info.Street);
writer.WriteString(2, info.City);
writer.WriteString(3, info.State);
writer.WriteString(4, info.Zip);
writer.WriteRemainder(info.FutureData);
}
}

Java型のContactInfoのPofSerializerインタフェースの実装は次のようになります。

例17-11 Java型クラスのPofSerializerの実装

public class ContactInfoSerializer
implements PofSerializer
{
public Object deserialize(PofReader in)
throws IOException
{
String sName   = in.readString(0);
String sStreet = in.readString(1);
String sCity   = in.readString(2);
String sState  = in.readString(3);
String sZip    = in.readString(4);

ContactInfo info = new ContactInfo(sName, sStreet, sCity, sState, sZip);
info.setDataVersion(in.getVersionId());
info.setFutureData(in.readRemainder());

return info;
}

public void serialize(PofWriter out, Object o)
throws IOException
{
ContactInfo info = (ContactInfo) o;

out.setVersionId(Math.max(info.getDataVersion(), info.getImplVersion()));
out.writeString(0, info.getName());
out.writeString(1, info.getStreet());
out.writeString(2, info.getCity());
out.writeString(3, info.getState());
out.writeString(4, info.getZip());
out.writeRemainder(info.getFutureData());
}
}

.NET型のContactInfoのIPofSerializer実装を登録するには、POF構成ファイルのContactInfoユーザー定義型に関するuser-type要素で、serializer要素内にIPofSerializerのクラス名を指定します。これを例17-12に示します。

例17-12 .NET型のIPofSerializer実装の登録

<?xml version="1.0"?>

<pof-config xmlns="http://schemas.tangosol.com/pof"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/pof
assembly://Coherence/Tangosol.Config/pof-config.xsd">
<user-type-list>
<!-- include all "standard" Coherence POF user types -->
<include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml
</include>
<!-- include all application POF user types -->
<user-type>
<type-id>1001</type-id>
<class-name>My.Example.ContactInfo, MyAssembly</class-name>
<serializer>
<class-name>My.Example.ContactInfoSerializer, MyAssembly</class-name>
</serializer>
</user-type>
</user-type-list>
</pof-config>

同様に、Java型のContactInfoのPofSerializer実装を登録できます。これを例17-13に示します。

例17-13 Java型のPofSerializer実装の登録

<?xml version="1.0"?>

<pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config
coherence-pof-config.xsd">
<user-type-list>
<!-- include all "standard" Coherence POF user types -->
<include>example-pof-config.xml</include>
<!-- include all application POF user types -->
<user-type>
<type-id>1001</type-id>
<class-name>com.mycompany.example.ContactInfo</class-name>
<serializer>
<class-name>com.mycompany.example.ContactInfoSerializer</class-name>
</serializer>
</user-type>
</user-type-list>
</pof-config>

17.8 POFオブジェクト参照の使用方法

POFでは、POFストリーム内で複数回出現するオブジェクトに、オブジェクトのIDや参照の使用がサポートされています。オブジェクトには、IDが付けられ、同じPOFストリーム内で2回目以降に出現するラベルが付いたオブジェクトは、そのIDで参照されます。

参照を使用することで、同じオブジェクトを複数回エンコーディングすることを防ぎ、データサイズを削減できます。一般に、参照を使用するのは、サイズの大きな多数のオブジェクトが複数回生成されるときや、オブジェクトでネストや循環データ構造が使用されるときです。ただし、大量のデータがあり、繰返しが少ないアプリケーションの場合、オブジェクト参照を使用してもオブジェクトのIDや参照の追跡によって生じるオーバーヘッドのために、利点はほとんどありません。

オブジェクト・アイデンティティおよび参照の使用には次の制限があります。

- オブジェクト参照には、ユーザー定義のオブジェクト型のみがサポートされています。

- Evolvableオブジェクトでは、オブジェクト参照はサポートされていません。

- キーでは、オブジェクト参照はサポートされていません。

- 参照をサポートしていないPOFコンテキストによって記述されたオブジェクトは、参照をサポートするPOFコンテキストで読み込むことができません。また、この逆の場合も同様です。

- POFエクストラクタを使用して、オブジェクト・アイデンティティおよび参照を使用するPOFオブジェクトを問い合せることはできません。かわりに、ValueExtractor APIを使用してオブジェクト値を問い合せるか、またはオブジェクト参照を無効にしてください。

この項には、次のトピックが含まれます:

- POFオブジェクト参照の有効化

- 循環構造のオブジェクトやネストされたオブジェクトへのPOFオブジェクトIDの登録

17.8.1 POFオブジェクト参照の有効化

オブジェクト参照は、デフォルトでは無効になっており、SimplePofContextクラスを使用するときにpof-config.xml構成ファイル内か、プログラムによって有効にする必要があります。

POF構成ファイルでオブジェクト参照を有効にするには、<pof-config>要素内に<enable-references>要素を含めて、値をtrueに設定します。例:

<?xml version="1.0"?>

<pof-config xmlns="http://schemas.tangosol.com/pof"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/pof
assembly://Coherence/Tangosol.Config/pof-config.xsd">
...
<enable-references>true</enable-references>
</pof-config>

SimplePofContextクラスの使用時にオブジェクト参照を有効にするには、setReferenceEnabledメソッドをコールして、trueに設定します。例:

SimplePofContext ctx = new SimplePofContext();
ctx.IsReferenceEnabled = true;

17.8.2 循環構造のオブジェクトやネストされたオブジェクトへのPOFオブジェクトIDの登録

循環構造のオブジェクトやネストされたオブジェクトは、オブジェクトの作成時に手動でIDを登録する必要があります。これを行わないと、親を参照する子が、参照マップで親のIDを検出しません。オブジェクトのIDは、Tangosol.IO.Pof.IPofReader.RegisterIdentityメソッドを使用し、デシリアライズ・ルーチンでシリアライザから登録できます。

次の例では、循環参照を含んだ2つのオブジェクト(CustomerおよびProduct)と、CustomerオブジェクトのIDを登録するシリアライザ実装を示しています。

Customerオブジェクトの定義は次のとおりです。

public class Customer
{
String m_name;
Product m_product;

public Customer(String name)
{
m_name = name;
}

public Customer(String name, Product product)
{
m_name = name;
m_product = product;
}

public String getName()
{
return m_name;
}

public Product getProduct()
{
return m_product;
}

public void setProduct(Product product)
{
m_product = product;
}
}

Productオブジェクトの定義は次のとおりです。

public class Product
{
private Customer m_customer;

public Product(Customer customer)
{
m_customer = customer;
}

public Customer getCustomer()
{
return m_customer;
}
}

デシリアライズの間にIDを登録するシリアライザ実装の定義は次のとおりです。

public class CustomerSerializer : IPofSerializer
{
public void Serialize(IPofWriter pofWriter, object o)
{
var c = (Customer) o;
pofWriter.WriteString(0, c.getName());
pofWriter.WriteObject(1, c.getProduct());
pofWriter.WriteRemainder(null);
}

public object Deserialize(IPofReader pofReader)
{
String name = pofReader.ReadString(0);
var customer = new Customer(name);

pofReader.RegisterIdentity(customer);
customer.setProduct((Product) pofReader.ReadObject(1));
pofReader.ReadRemainder();
return customer;
}
}

17.9 POF注釈を使用したオブジェクトのシリアライズ

POF注釈は、オブジェクトにシリアライズやデシリアライズ・ルーチンの実装を自動化する方法を提供します。POF注釈は、IPofSerializerインタフェースの実装であるPofAnnotationSerializerクラスを使用してシリアライズまたはデシリアライズします。注釈は、IPortableObjectおよびIPofSerializerインタフェースのかわりに使用でき、オブジェクトをシリアライズ可能にするために必要な時間やコードの量を削減します。

この項には、次のトピックが含まれます:

- POFシリアライズでのオブジェクトへの注釈付け

- POF注釈付きオブジェクトの登録

- 自動索引付けの有効化

- カスタム・コーデックの提供

17.9.1 POFシリアライズでのオブジェクトへの注釈付け

クラスとクラスのプロパティがPOFシリアライズ可能であることを示すために利用できる注釈は2つあります。

- [Portable] - クラスをPOFシリアライズ可能とマークします。注釈は、クラス・レベルのみに使用でき、メンバーを含みません。

- [PortableProperty] - プロパティ、アクセッサまたはメンバー変数をPOFシリアライズ化されたプロパティとしてマークします。注釈が付けられたメソッドは、アクセッサの表記法(Get、Set、Is)に従っている必要があります。メンバーを、POF索引や、シリアライズまたはデシリアライズの前後で実行するカスタム・コーデックの指定に使用できます。索引の値は省略可能で、自動的に割り当てられます。カスタム・コーデックを入力しない場合は、デフォルトのコーデックが使用されます。

次の例は、クラス、プロパティおよびメンバー変数への注釈付けを示しています。さらに、PortableProperty索引が明示的に指定されています。

[Portable]
public class Person
{
[PortableProperty(0)]
public string GetFirstName()
{
return m_firstName;
}

private String m_firstName;

[PortableProperty(1)]
public string LastName;
{
get; set;
}

[PortableProperty(2)]
private int m_age;
}

17.9.2 POF注釈付きオブジェクトの登録

POF注釈付きオブジェクトは、pof-config.xmlファイルの<user-type要素内で登録する必要があります。POF構成要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。POF注釈付きオブジェクトは、IPortableObjectを実装していない場合はPofAnnotationSerializerシリアライザを使用し、Portableとして注釈が付けられます。ただし、このシリアライザは、オブジェクトが注釈付きかどうかと、ユーザー定義型に含める必要がないことを自動的に仮定します。次の例では、注釈付きPersonオブジェクトのユーザー定義型を登録します。

<?xml version='1.0'?>
<pof-config xmlns="http://schemas.tangosol.com/pof">
<user-type-list>
<!-- include all "standard" Coherence POF user types -->
<include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml
<!-- User types must be above 1000 -->
<user-type>
<type-id>1001</type-id>
<class-name>My.Examples.Person, MyAssembly</class-name>
</user-type>
</user-type-list>
</pof-config>

17.9.3 自動索引付けの有効化

POF注釈では、自動索引付けがサポートされており、明示的な索引値の割当てや管理の必要性を軽減されます。[PortableProperty]注釈を定義している場合は、索引値を省略します。索引の割当てはプロパティ名によって決定されます。明示的に索引値を割り当てるプロパティによって、自動索引値が割り当てられることはありません。次の表は、自動索引アルゴリズムの命令セマンティクスを示しています。自動索引付けは、明示的に定義された索引を維持し(プロパティc参照)、索引が省略されている場合は、索引を割り当てます。

名前

明示的索引

決定された索引

c

1

1

a

省略

0

b

省略

2

注意:

自動索引では、現在、進化可能なクラスがサポートされていません。

自動索引付けを有効にするには、POF構成ファイルでユーザー定義型としてオブジェクトを登録するときにPofAnnotationSerializerシリアライザ・クラスを明示的に定義する必要があります。コンストラクタ内のautoIndexブール・パラメータで自動索引を有効にでき、必ずtrueに設定します。例:

<user-type>
<type-id>1001</type-id>
<class-name>Examples.Person</class-name>
<serializer>
<class-name>Tangosol.IO.Pof.PofAnnotationSerializer, Coherence</class-name>
<init-params>
<init-param>
<param-type>int</param-type>
<param-value>{type-id}</param-value>
</init-param>
<init-param>
<param-type>class</param-type>
<param-value>{class}</param-value>
</init-param>
<init-param>
<param-type>bool</param-type>
<param-value>true</param-value>
</init-param>
</init-params>
</serializer>
</user-type>

17.9.4 カスタム・コーデックの提供

コーデックによって、シリアライズまたはデシリアライズの前後でコードを実行できます。コーデックでは、IPofWriterおよびIPofReaderインタフェースを使用して、移植可能なプロパティをエンコードおよびデコードする方法を定義できます。コーデックは、一般に、デシリアライズ中に消失する可能性がある実用的な実装に使用します。または、オブジェクトをシリアライズする前にIPofWriterインタフェースで特定のメソッドを明示的にコールするために使用します。

コーデックを作成するには、ICodecインタフェースを実装するクラスを作成します。次の例は、リンクされたリスト型の実用的な実装を定義するコーデックを示しています。

public class LinkedListCodec<T> : ICodec
{
public object Decode(IPofReader reader, int index)
{
return reader.ReadCollection(index, (ICollection)new LinkedList<T>());
}

public void Encode(IPofWriter writer, int index, object value)
{
writer.WriteCollection(index, (ICollection)value);
}
}

コーデックをプロパティに割り当てるには、コーデックを[PortableProperty]属性のメンバーとして入力します。コーデックを指定しない場合は、デフォルトのコーデック(DefaultCodec)が使用されます。次の例は、前述のLinkedListCodecコーデックの割当て方法を示しています。

[PortableProperty(typeof(LinkedListCodec<string>))]

18 Coherence .NETクライアント・ライブラリの使用

この章では、Coherence for .NETクライアント・ライブラリをアプリケーションに追加する手順を説明します。さらに、Coherence for C++ APIについて説明します。このAPIを使用すると、C++アプリケーションで、Coherenceクラスタ外部からCoherenceクラスタ・サービスにアクセスできます。

Coherence for .NET APIのドキュメントは2つの場所にあります。1つはOracle Coherence .NET APIリファレンスで、もう1つはCoherence for .NETのdocディレクトリです。

この章には次の項が含まれます:

- Coherence .NETクライアント・ライブラリの設定

- Coherence .NET APIの使用

18.1 Coherence .NETクライアント・ライブラリの設定

.NETアプリケーションでCoherence for .NETライブラリを使用するには、Coherence.dllライブラリへの参照をプロジェクトに追加し、必要な構成ファイルを作成する必要があります。

Coherence.dllへの参照を作成する手順は、次のとおりです。

1. プロジェクトで「プロジェクト」→「参照の追加」を選択するか、または「ソリューション エクスプローラ」の「参照設定」を右クリックして「参照の追加」を選択します。「参照の追加」ウィンドウが表示されます。

2. 「参照の追加」ウィンドウから、「参照」タブを選択し、ファイル・システム上のCoherence.dllライブラリを探します(図18-1を参照)。

図18-1 「参照の追加」ウィンドウ

「図18-1 「参照の追加」ウィンドウ」の説明

3. 「OK」をクリックします。

次に、必要な構成ファイルを作成し、そのパスをアプリケーション構成設定で指定する必要があります。そのためには、アプリケーション構成ファイルをプロジェクトに追加し(存在しない場合)、Coherence for .NETの構成セクション(<coherence/>)をそのファイルに追加します。

注意:

app.config/web.configでこれらの構成ファイルが指定されていない場合、Coherenceでは、アプリケーションのデプロイ先フォルダか、Webアプリケーションの場合はWebアプリケーションのルートで、構成ファイルが検索されます。

例18-1 アプリケーション構成ファイルのサンプル

<?xml version="1.0"?>
<configuration>
<configSections>
<section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence"/>
</configSections>
<coherence>
<cache-factory-config>my-coherence.xml</cache-factory-config>
<cache-config>my-cache-config.xml</cache-config>
<pof-config>my-pof-config.xml</pof-config>
</coherence>
</configuration>

Coherence for .NETの構成セクションの要素は次のとおりです。

- cache-factory-config: IConfigurableCacheFactoryおよびLoggerを構成するためにCacheFactoryで使用されるオペレーション構成・ディスクリプタのパスを記述します。

- cache-config: キャッシュ構成(「Coherence*Extendの構成」を参照)を含むキャッシュ構成ファイルのパスを記述します。このキャッシュ構成ディスクリプタは、DefaultConfigurableCacheFactoryで使用されます。

- pof-config: アプリケーションで使用するカスタム型を登録するために、ConfigurablePofContextで使用される構成ディスクリプタのパスを記述します。POFの使用手順の詳細は、第18章「Coherence .NETクライアント・ライブラリの使用」を参照してください。

図18-2は、構成ファイルを追加した後のソリューションを示しています。

図18-2 構成ファイルを表示しているファイル・システム

「図18-2 構成ファイルを表示しているファイル・システム」の説明

18.2 Coherence .NET APIの使用

この項では、.NETアプリケーション内でCoherenceのキャッシュと相互作用するために使用するプライマリCoherence .NET APIについて重点的に説明します。この項には、次のトピックが含まれます:

- CacheFactory

- IConfigurableCacheFactory

- DefaultConfigurableCacheFactory

- Logger

- Common.Loggingライブラリの使用

- INamedCache

- IQueryCache

- QueryRecorder

- IObservableCache

- IInvocableCache

- フィルタ

- 値エクストラクタ

- 入力プロセッサ

- エントリ・アグリゲータ

18.2.1 CacheFactory

CacheFactoryは、Coherence for .NETクライアント・アプリケーションのエントリ・ポイントです。CacheFactoryはINamedCacheインスタンスのファクトリであり、ロギングのための様々なメソッドを提供します。それは、明示的に構成されていない場合、アセンブリが埋め込まれたリソースであるデフォルトの構成ファイルcoherence.xmlを使用します。このデフォルトの構成ファイルは無効にできます。そのためには、アプリケーション構成ファイルのCoherence for .NET構成セクションにcache-factory-config要素を追加し、その値を目的の構成ファイルのパスに設定します。

例18-2 INamedCacheインスタンスのファクトリの構成

<?xml version="1.0"?>

<configuration>
<configSections>
<section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence"/>
</configSections>
<coherence>
<cache-factory-config>my-coherence.xml</cache-factory-config>
...
</coherence>
</configuration>

このファイルには、CacheFactoryで静的なプロパティを使用して公開される次の2つのコンポーネントが構成されています。

- CacheFactory.ConfigurableCacheFactory: CacheFactoryでINamedCacheインスタンスの取得、解放および破棄に使用されるIConfigurableCacheFactory実装

- CacheFactory.Logger: メッセージと例外を記録するために使用されるLoggerインスタンス

CacheFactoryの使用が終了したら(アプリケーションをシャットダウンする場合など)、Shutdown()メソッドを使用してCacheFactoryをシャットダウンする必要があります。このメソッドによって、すべてのサービスとLoggerインスタンスが終了します。

18.2.2 IConfigurableCacheFactory

IConfigurableCacheFactory実装は、<configurable-cache-factory-config>要素の内容で指定されます。

- class-name: 実装タイプをそのアセンブリ修飾名で指定します。

- init-params: IConfigurableCacheFactoryのインスタンス化に使用されるパラメータを定義します。各パラメータは、対応する子要素param-typeおよびparam-valueで指定されます。

例18-3 ConfigurableCacheFactory実装の構成

<coherence>
<configurable-cache-factory-config>
<class-name>Tangosol.Net.DefaultConfigurableCacheFactory, Coherence</class-name>
<init-params>
<init-param>
<param-type>string</param-type>
<param-value>simple-cache-config.xml</param-value>
</init-param>
</init-params>
</configurable-cache-factory-config>
</coherence>

IConfigurableCacheFactory実装が構成に定義されていない場合は、デフォルトの実装(DefaultConfigurableCacheFactory)が使用されます。

18.2.3 DefaultConfigurableCacheFactory

DefaultConfigurableCacheFactoryは、前述のキャッシュ構成ディスクリプタ(「クライアント側のキャッシュ構成ディスクリプタ」を参照)で宣言されているキャッシュにアクセスするための機能を提供します。DefaultConfigurableCacheFactoryで使用されるデフォルトの構成ファイルは$AppRoot/coherence-cache-config.xmlです。$AppRootは、作業ディレクトリ(Windowsフォーム・アプリケーションの場合)またはアプリケーションのルート(Webアプリケーションの場合)です。

別のキャッシュ構成ディスクリプタ・ファイルを指定する場合は、アプリケーション構成ファイルのCoherence for .NET構成セクションにcache-config要素を追加して、その値を構成ファイルのパスに設定します。

例18-4 別のキャッシュ構成ディスクリプタ・ファイルの指定

<?xml version="1.0"?>
<configuration>
<configSections>
<section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence"/>
</configSections>
<coherence>
<cache-config>my-cache-config.xml</cache-config>
...
</coherence>
</configuration>

18.2.4 Logger

Loggerは次のlogging-config要素を使用して構成します。

- destination: Loggerで使用するLogOutputのタイプを指定します。有効な値は次のとおりです。

- common-logger(Common.Loggingの場合)

- stderr(Console.Errorの場合)

- stdout(Console.Outの場合)

- ファイル・パス(メッセージをファイルに送信する必要がある場合)

- severity-level: メッセージをログに記録するために満たすか、または超過する必要のあるログ・レベルを決定します。

- message-format: ログ・メッセージの書式を決定します。

- character-limit: ログ出力デーモンがメッセージ・キューから処理する文字の最大数を決定します。この数を超過すると、キューに残っているメッセージがすべて破棄されます。

例18-5 Loggerの構成

...
<logging-config>
<destination>common-logger</destination>
<severity-level>5</severity-level>
<message-format>(thread={thread}): {text}</message-format>
<character-limit>8192</character-limit>
</logging-config>
...

CacheFactoryは、INamedCacheのインスタンスを取得および解放する、次の静的メソッドを提供します。

- GetCache(String cacheName): リモートのCoherenceクラスタ内で稼働する、指定されたcacheNameのNamedCacheに対応するINamedCache実装を取得します。

- ReleaseCache(INamedCache cache): キャッシュの指定のインスタンスに関連付けられているローカル・リソースをすべて解放します。解放したキャッシュは使用できなくなります。

- DestroyCache(INamedCache cache): 指定されたキャッシュをCoherenceクラスタ全体で破棄します。

メッセージと例外を記録するためのメソッドは次のとおりです。

- IsLogEnabled(int level): 指定された重大度のメッセージをLoggerで記録するかどうかを決定します。

- Log(Exception e, int severity): 指定された重大度の例外を記録します。

- Log(String message, int severity): 指定された重大度のテキスト・メッセージを記録します。

- Log(String message, Exception e, int severity): 指定された重大度のテキスト・メッセージと例外を記録します。

ロギング・レベルはCacheFactory.LogLevelのenumの値で定義されます(昇順)。

- Always

- Error

- Warn

- Info

- Debug(デフォルトのログ・レベル)

- Quiet

- Max

18.2.5 Common.Loggingライブラリの使用

Common.Loggingは、明確に定義された一連のインタフェースの背後で、各種の一般的なオープンソース・ロギング・ライブラリをプラグインできるようにするオープンソース・ライブラリです。現在サポートされているライブラリは、Log4Net(バージョン1.2.9と1.2.10)およびNLogです。Common.Loggingは、現在Spring.NETフレームワークで使用されており、IBatis.NETおよびNHibernateの今後のリリースでも使用される可能性があります。このため、これらのフレームワークをCoherence for .NETと組み合せて使用している場合は、アプリケーション・レイヤー全体で一貫してロギングを構成できることから、Common.Loggingの使用を検討してください。

Coherence for .NETにはCommon.Loggingライブラリが含まれていません。Logger構成にcommon-loggerを使用するには、Common.Loggingアセンブリをダウンロードし、そのアセンブリへの参照をプロジェクトに組み込みます。.NET用のCommon.Loggingアセンブリは、次の場所からダウンロードできます。

http://netcommon.sourceforge.net/

Coherence for .NETのCommon.Logging Logger実装は、これらのアセンブリの署名付きリリース・バージョンに対してコンパイルされています。

18.2.6 INamedCache

INamedCacheインタフェースはIDictionaryを拡張するため、ディクショナリと同様に操作できます。取得したINamedCacheインスタンスでは、いくつかのプロパティが公開されます。

- CacheName: キャッシュ名

- Count: キャッシュ・サイズ

- IsActive: キャッシュがアクティブ(つまり解放も破棄もされていない)かどうかを判定します。

- Keys: キャッシュ・マッピング内のすべてのキーのコレクション

- Values: キャッシュ・マッピング内のすべての値のコレクション

指定されたキーの値は、cache[key]を使用して取得できます。同様に、新しい値を追加したり、プロパティを新しい値に設定することで古い値を変更したりできます(cache[key] = value)。

キャッシュ・エントリのコレクションにアクセスするには、キャッシュ内のマッピングを反復処理するGetEnumerator()を使用します。

INamedCacheインタフェースは、キャッシュの内容を操作するための複数のメソッドを提供します。

- Clear(): キャッシュからすべてのマッピングを削除します。

- Contains(Object key): 指定されたキーのマッピングがキャッシュにあるかどうかを判定します。

- GetAll(ICollection keys): 指定されたキー・コレクションにマップされているすべての値を返します。

- Insert(Object key, Object value): キャッシュに新しいマッピングを挿入します。指定されたキーのマッピングが存在する場合は、その値が指定された値で上書きされ、古い値が返されます。

- Insert(Object key, Object value, long millis): キャッシュに新しいマッピングを挿入しますが、有効期限がミリ秒単位で指定されます。

- InsertAll(IDictionary dictionary): 指定されたディクショナリのすべてのマッピングをキャッシュにコピーします。

- Remove(Object key): 指定されたキーのマッピングが存在する場合はそれを削除し、そのキーがマップされていた値を返します。

INamedCacheインタフェースは、この他にIQueryCache、IObservableCacheおよびIInvocableCacheの3つのインタフェースを拡張します。

18.2.7 IQueryCache

IQueryCacheインタフェースは、様々なフィルタを使用してキャッシュを問い合せる機能を備えています。

- GetKeys(IFilter filter): 対象のキャッシュに格納されているキーのうち、フィルタで表された基準を満たすエントリのキーのコレクションを返します。

- GetEntries(IFilter filter): 対象のキャッシュに格納されているエントリのうち、フィルタで表された基準を満たすエントリのコレクションを返します。

- GetEntries(IFilter filter, IComparer comparer): 対象のキャッシュに格納されているエントリのうち、フィルタで表された基準を満たすエントリのコレクションを返します。この場合、列挙子は必ずコレクションをエントリ値の昇順で横断します。エントリ値は指定されたcomparerでソートされているか、またはcomparerがnullの場合は自然な順序でソートされています。

さらにIQueryCacheインタフェースには、索引を追加または削除する機能があります。索引はキャッシュに格納されている値を対応するキーに関連付けるために使用され、GetKeysメソッドとGetEntriesメソッドのパフォーマンスを大幅に向上します。

- AddIndex(IValueExtractor extractor, bool isOrdered, IComparer comparator): 指定されたIValueExtractorによって抽出された値を対応するエントリに対するキーに関連付ける索引を、対象のキャッシュに追加します。索引情報は順序付けることもできます。

- RemoveIndex(IValueExtractor extractor): 対象のキャッシュから索引を削除します。

例18-6は、年齢プロパティの値が55以上であるすべてのエントリのキーを効率よく問い合せるコードを示しています。

例18-6 特定の値に関するキーの問合せ

IValueExtractor extractor = new ReflectionExtractor("getAge");

cache.AddIndex(extractor, true, null);
ICollection keys = cache.GetKeys(new GreaterEqualsFilter(extractor, 55));

18.2.8 QueryRecorder

QueryRecorderクラスは指定されたフィルタの説明またはトレース・レコードを生成します。このクラスは、クラスタ内のすべてのノードを問い合せ、結果を集約する機能を持つ並列アグリゲータの実装です。このクラスでは2種類のレコードがサポートされています。その1つはExplainレコードで、問合せ処理の間に実行されたフィルタの評価の見積りコストを提供します。もう1つはTraceレコードで、問合せ処理の間に実行されたフィルタの評価の実際のコストを提供します。両方の問合せレコードでは、フィルタで索引が使用可能かどうかが考慮されます。EXPLAIN PLANレコードおよびトレース・レコードで提供されるデータの詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

問合せレコードを作成するには、RecordTypeパラメータを指定する新しいQueryRecorderインスタンスを作成します。テストするインスタンスとフィルタをAggregateメソッドのパラメータとして含めます。次の例では、説明レコードを作成しています。

INamedCache cache = CacheFactory.GetCache(MyCache);

IFilter filter = new OrFilter(
new GreaterFilter(IdentityExtractor.Instance, 100),
new LessFilter(IdentityExtractor.Instance, 30));

QueryRecorder aggregator = new QueryRecorder(QueryRecorder.RecordType.Explain);
IQueryRecord record = (IQueryRecord) cache.Aggregate(filter, aggregator);

Console.WriteLine(record.ToString());

トレース・レコードを作成するには、RecordTypeパラメータをTraceに変更します。

QueryRecorder aggregator = new QueryRecorder(QueryRecorder.RecordType.Trace);

18.2.9 IObservableCache

IObservableCacheインタフェースは、キャッシュの内容が変更されたときにアプリケーションがイベントを受信できるようにします。変更イベントに関心があることを登録するには、そのキャッシュに対するListener実装をアプリケーションで追加します。対象キャッシュでは、イベント・タイプ(挿入、更新、削除)、変更されたエントリのキー、およびエントリの古い値と新しい値などに関する情報を含むイベントが受信されます。

- AddCacheListener(ICacheListener listener): キャッシュから発行されたすべてのイベント(挿入、更新、削除)を、そのキー、古い値および新しい値を含めて受信する標準のキャッシュ・リスナーを追加します。

- RemoveCacheListener(ICacheListener listener): 以前に登録した標準のキャッシュ・リスナーを削除します。

- AddCacheListener(ICacheListener listener, object key, bool isLite): 特定のキーに関するキャッシュ・リスナーを追加します。isLiteがtrueである場合は、イベントに古い値と新しい値が含まれないことがあります。

- RemoveCacheListener(ICacheListener listener, object key): 指定されたキーを使用して以前に登録されたキャッシュ・リスナーを削除します。

- AddCacheListener(ICacheListener listener, IFilter filter, bool isLite): フィルタの評価に基づいてイベントを受信するキャッシュ・リスナーを追加します。isLiteがtrueである場合は、イベントに古い値と新しい値が含まれないことがあります。

- RemoveCacheListener(ICacheListener listener, IFilter filter): 指定されたフィルタを使用して以前に登録されたキャッシュ・リスナーを削除します。

フィルタベースのメソッドを使用して登録されたListenerは、すべてのイベント・タイプ(挿入、更新、削除)を受信します。イベントをさらにフィルタリングするには、CacheEventFilter内にフィルタをラップし、CacheEventMask列挙値を使用して監視対象とするイベントのタイプを指定します。

図18-2では、IsMarriedプロパティ値がtrueに設定されたEmployeeオブジェクトがキャッシュに挿入されると、フィルタがtrueに評価されます。

例18-7 挿入されたオブジェクトに対するフィルタリング

new CacheEventFilter(CacheEventMask.Inserted, new EqualsFilter("IsMarried", true));

例18-8では、キャッシュからオブジェクトが1つでも削除されると、フィルタがtrueに評価されます。

例18-8 削除されたオブジェクトに対するフィルタリング

new CacheEventFilter(CacheEventMask.Deleted);

例18-9では、EmployeeオブジェクトのLastNameプロパティがSmithから変更されると、フィルタthatがtrueになります。

例18-9 変更されたオブジェクトに対するフィルタリング

new CacheEventFilter(CacheEventMask.UpdatedLeft, new EqualsFilter("LastName", "Smith"));

18.2.9.1 キャッシュ・イベントへの応答

INamedCacheインタフェースには、キャッシュ・コンテンツの変更時に発行されるイベントを受信する、キャッシュ・リスナーを追加する機能があります。このイベントはサーバーから送信され、バックグラウンド・スレッドによって登録済のリスナーにディスパッチされます。

.NETのシングルスレッド・アパートメント・モデルでは、あるスレッドで作成されたWindowsフォームのコントロールを別のスレッドで更新することが禁止されています。イベント通知によって1つ以上のコントロールを更新する場合は、キャッシュ・イベントへの応答として実行する必要のあるイベント処理コードをUIスレッド上で実行する必要があります。WindowsFormsCacheListenerヘルパー・クラスを使用すれば、エンド・ユーザーはこの事実を意識することなく、Coherenceキャッシュ・イベント(発生元はつねにバックグラウンド・スレッド)をUIスレッドで発生したイベントと同様に処理できます。このクラスにより、コールがUIスレッド上で適切にマーシャリングされて実行されるようになります。

このクラスの使用例を次に示します。

例18-10 UIスレッドでのコールのマーシャリングと実行

public partial class ContactInfoForm : Form
{
...
listener = new WindowsFormsCacheListener(this);
listener.EntryInserted += new CacheEventHandler(AddRow);
listener.EntryUpdated  += new CacheEventHandler(UpdateRow);
listener.EntryDeleted  += new CacheEventHandler(DeleteRow);
...
cache.AddCacheListener(listener);
...
}

AddRow、UpdateRowおよびDeleteRowの各メソッドは、キャッシュ・イベントに応じてコールされます。

例18-11 キャッシュ・イベントに応じたメソッドのコール

private void AddRow(object sender, CacheEventArgs args)
{
...
}

private void UpdateRow(object sender, CacheEventArgs args)
{
...
}

private void DeleteRow(object sender, CacheEventArgs args)
{
...
}

CacheEventArgsパラメータは、キャッシュ・イベントを発生させたIObservableCacheインスタンス、発生したCacheEventType、およびキャッシュされたエントリのKey、NewValue、OldValueをカプセル化します。

18.2.10 IInvocableCache

IInvocableCacheは、エントリ別処理と集計操作の両方を起動できるキャッシュです。キャッシュの内容に対する操作は、キャッシュによって(したがって、特定の領域に制限されたキャッシュの内容の中で)実行できます。この機能は特に分散環境で役立ちます。これは、処理対象のエントリが管理されている場所に処理を移すことで、処理を局所化して効率を高めることができるためです。

- Invoke(object key, IEntryProcessor agent): 渡されたキーで指定されるエントリに対して渡されたプロセッサを起動し、その起動の結果を返します。

- InvokeAll(ICollection keys, IEntryProcessor agent): 渡されたキーで指定されるエントリに対して渡されたプロセッサを起動し、それぞれの起動の結果を返します。

- InvokeAll(IFilter filter, IEntryProcessor agent): 指定されたフィルタで選択されるエントリに対して渡されたプロセッサを起動し、それぞれの起動の結果を返します。

- Aggregate(ICollection keys, IEntryAggregator agent): 渡されたキーで指定されるエントリに対して集約操作を実行します。

- Aggregate(IFilter filter, IEntryAggregator agent): 指定されたフィルタで選択されるエントリに対して集約操作を実行します。

18.2.11 フィルタ

IQueryCacheインタフェースは、IFilter実装を使用して表される、所定の基準を満たすキャッシュ・エントリを検索する機能を提供します。

すべてのフィルタはIFilterインタフェースを実装する必要があります。

- Evaluate(object o): 指定されたオブジェクトにテストを適用し、テストに合格した場合はtrue、そうでない場合はfalseを返します。

Coherence for .NETでは、Tangosol.Util.FilterネームスペースにいくつかのIFilter実装が含まれています。

例18-12のコードでは、値が5であるすべてのエントリのキーが取得されます。

例18-12 ある数値と等しいキーの取得

EqualsFilter equalsFilter = new EqualsFilter(IdentityExtractor.Instance, 5);
ICollection  keys         = cache.GetKeys(equalsFilter);

例18-13のコードでは、値が55以上であるすべてのキーが取得されます。

例18-13 ある数値より大きいか、それと等しいキーの取得

GreaterEqualsFilter greaterEquals = new GreaterEqualsFilter(IdentityExtractor.Instance, 55);
ICollection         keys          = cache.GetKeys(greaterEquals);

例18-14のコードでは、値がBelgで始まるすべてのキャッシュ・エントリが取得されます。

例18-14 ある文字列値に基づいたキーの取得

LikeFilter  likeFilter = new LikeFilter(IdentityExtractor.Instance, "Belg%", '\\', true);
ICollection entries    = cache.GetEntries(likeFilter);

例18-15のコードでは、値がan(大文字と小文字を区別)で終わるか、またはAn(大文字と小文字の区別なし)で始まるすべてのキャッシュ・エントリを取得します。

例18-15 大文字と小文字を区別する文字列値に基づいたキーの取得

OrFilter    orFilter = new OrFilter(new LikeFilter(IdentityExtractor.Instance, "%an", '\\', false), new LikeFilter(IdentityExtractor.Instance, "An%", '\\', true));
ICollection entries  = cache.GetEntries(orFilter);

18.2.12 値エクストラクタ

エクストラクタは、オブジェクトから値を抽出するために使用されます。すべてのエクストラクタはIValueExtractorインタフェースを実装する必要があります。

- Extract(object target): 渡されたオブジェクトから値を抽出します。

Coherence for .NETには次のエクストラクタがあります。

- IdentityExtractor: 渡された値から何も抽出せず、その値そのものを返す単純な実装です。

- KeyExtractor: 値ではなく主要なオブジェクトに対して問合せを実行する必要があることを示す、特殊な目的の実装です。

- ReflectionExtractor: 指定したオブジェクトのプロパティから値を抽出します。

- MultiExtractor: エクストラクタの配列に基づく複合的なIValueExtractor実装です。配列内のエクストラタはすべて同じターゲット・オブジェクトに適用され、抽出した値のIListが抽出結果となります。

- ChainedExtractor: エクストラクタの配列に基づく複合的なIValueExtractor実装です。配列内のエクストラクタは左から右に順次適用され、前のエクストラクタの結果が次のエクストラクタのターゲット・オブジェクトとなります。

例18-16のコードでは、キーの値が5より大きいすべてのキャッシュ・エントリが取得されます。

例18-16 ある数値より大きいキャッシュ・エントリの取得

IValueExtractor extractor = new KeyExtractor(IdentityExtractor.Instance);
IFilter         filter    = new GreaterFilter(extractor, 5);
ICollection     entries   = cache.GetEntries(filter);

例18-17のコードでは、値のCityプロパティがcity1と等しいすべてのキャッシュ・エントリが取得されます。

例18-17 ある文字列値に基づいたキャッシュ・エントリの取得

IValueExtractor extractor = new ReflectionExtractor("City");
IFilter         filter    = new EqualsFilter(extractor, "city1");
ICollection     entries   = cache.GetEntries(filter);

18.2.13 入力プロセッサ

入力プロセッサは、キャッシュ内のエントリ・オブジェクトに対して作動するエージェントです。

すべての入力プロセッサはIEntryProcessorインタフェースを実装する必要があります。

- Process(IInvocableCacheEntryエントリ): 指定されたエントリを処理します。

- ProcessAll(ICollectionエントリ): エントリのコレクションを処理します。

Coherence for .NETでは、Tangosol.Util.ProcessorネームスペースにいくつかのIEntryProcessor実装が含まれています。

例18-18のコードは、条件付き設定を示しています。key1に現在マップされている値が600より大きい場合にのみ、この値が680に設定されます。

例18-18 ある数値に基づいたキー値の条件付き設定

IFilter         greaterThen600 = new GreaterFilter(IdentityExtractor.Instance, 600);
IEntryProcessor processor      = new ConditionalPut(greaterThen600, 680);
cache.Invoke("key1", processor);

例18-19のコードでは、キーがBGDであるTemperatureオブジェクトに対し、UpdaterProcessorを使用してそのオブジェクトのDegreeプロパティを新しい値26に更新します。

例18-19 ある数値に基づいたキー値の設定

cache.Insert("BGD", new Temperature(25, 'c', 12));
IValueUpdater   updater   = new ReflectionUpdater("setDegree");
IEntryProcessor processor = new UpdaterProcessor(updater, 26);
object          result    = cache.Invoke("BGD", processor);

18.2.14 エントリ・アグリゲータ

エントリ・アグリゲータは、IInvocableCacheにあるエントリの一部のサブセットに対して実行し、集計結果を得るように指定できる処理を表します。集計の一般的な例として、最小、最大、合計、平均などの関数があります。ただし、集計の概念は、エントリのグループを評価して1つの答えを算出する必要のある任意のプロセスに適用されます。集計は、分散環境などで並列に実行する機能を明示的に備えています。

すべてのアグリゲータはIEntryAggregatorインタフェースを実装する必要があります。

- Aggregate(ICollectionエントリ): エントリのコレクションを処理して集約結果を生成します。

Coherence for .NETでは、Tangosol.Util.AggregatorネームスペースにいくつかのIEntryAggregator実装が含まれています。

例18-20のコードでは、キャッシュのサイズが返されます。

例18-20 キャッシュのサイズを返す

IEntryAggregator aggregator = new Count();
object           result     = cache.Aggregate(cache.Keys, aggregator);

例18-21のコードでは、キャッシュ内の一意の値と等しいキーを持ち、かつキャッシュ内の対応する値のインスタンス数と等しい値を持つIDictionaryが返されます。

例18-21 IDictionaryを返す

IEntryAggregator aggregator = GroupAggregator.CreateInstance(IdentityExtractor.Instance, new Count());
object           result     = cache.Aggregate(cache.Keys, aggregator);

注意:

例18-20および例18-21は簡単な例にすぎず、大量のキーやサイズがきわめて大きいキーを渡す用途には実用的ではありません。そのような用途では、GroupAggregator.CreateInstance(String, IEntryAggregator, IFilter)メソッドを使用してAlwaysFilterオブジェクトを渡します。

キャッシュした値オブジェクト同様、IFilter、IExtractor、IProcessorおよびIAggregatorのすべてのカスタム実装クラスは、.NETアプリケーションのPOFコンテキストおよびクライアントが接続されているクラスタ側ノードのPOFコンテキストに正しく登録する必要があります。したがって、カスタムの.NET型の対応するJava実装を、クラスタ側ノードで作成、コンパイルおよびデプロイする必要があります。このようなカスタム型を実際に実行するのは、.NETの実装ではなくJavaの実装であることに注意してください。

詳細は、第17章「統合オブジェクトの構築(.NET)」を参照してください。

19 連続問合せの実行(.NET)

この章では、.NETクライアントで連続問合せキャッシュを使用して、常に問合せがキャッシュからリアルタイムに最新の結果を取得する手順を説明します。

この章には次の項が含まれます:

- 連続問合せの実行の概要(.NET)

- 連続問合せキャッシュの実装の理解

- 連続問合せキャッシュの構成

- 連続問合せキャッシュ・リソースのクリーンアップ

- キーのみのキャッシングと、キーおよび値のキャッシング

- 連続問合せキャッシュのリスニング

- 連続問合せキャッシュを読取り専用にする

19.1 連続問合せの実行の概要(.NET)

問合せは、Coherenceキャッシュから特定の時点の問合せ結果を取得でき、さらに問合せの結果が変更された場合のイベントを受信できます。また、連続問合せ機能では問合せ結果を関連するイベントの連続的なストリームと結合し、リアルタイムに最新の問合せ結果を維持することが可能です。目的の問合せの待機時間が0である場合と同じ効果を持ち、問合せが1ミリ秒ごとに数回繰り返されるため、この機能は連続問合せと呼ばれています。

Coherence for .NETでは、問合せ結果をマテリアライズして連続問合せキャッシュに格納し、問合せに対するイベント・リスナーを使用してそのキャッシュをリアルタイムに最新の状態に維持することで、連続問合せ機能を実装します。つまり、Coherence for .NETの連続問合せでは、キャッシュされた問合せ結果が古くなることはありません。

19.1.1 連続問合せキャッシュのユース・ケースの理解

連続問合せキャッシュには、いくつかの異なる一般的な用途があります。

- これは、複合イベント処理(CEP: Complex Event Processing)システムやイベント相関エンジンにおける有用な構成要素です。

- これは、アプリケーションが特定の問合せを繰り返し実行し、その問合せの最新の結果に常に即座にアクセスできることが有益である状況では、効果的です。

- 連続問合せキャッシュはマテリアライズド・ビューに類似しており、標準のINamedCache APIを使用して問合せの結果にアクセスして操作する場合、およびその問合せに関連するイベントの現行ストリームを受信する場合に役立ちます。

- 連続問合せキャッシュは、最新のデータセットを使用場所(特定のサーバー・ノードやクライアント・デスクトップなど)でローカルに保持できるため、ニア・キャッシュと同様の方法で使用できます。ニア・キャッシュは無効化ベースですが、連続問合せキャッシュでは実際にデータが最新の状態で保持されます。

使用例の1つにトレーディング・システム・デスクトップがあります。このデスクトップには、トレーダーの未処理の注文とすべての関連情報が常に最新の状態で保持されている必要があります。Coherence*Extend機能を連続問合せキャッシュと組み合せることにより、アプリケーションで文字どおり何万もの同時ユーザーをサポートできます。

注意:

連続問合せキャッシュは、分散される可能性のあるより大きなキャッシュ・データセットの特定のサブセットについて、その最新のローカル・コピーを非常に簡単かつ効果的に維持する機能を提供します。そのため、クライアントベースおよびサーバーベースのアプリケーションを含め、ほとんどすべてのタイプのアプリケーションに有用です。

19.2 連続問合せキャッシュの実装の理解

Coherence for .NETの連続問合せの実装には、Tangosol.Net.Cache.ContinuousQueryCacheクラスを使用します。このクラスは、Coherence for .NETのすべてのキャッシュ同様、次の機能を備えた標準のINamedCacheインタフェースを実装します。

- IDictionaryインタフェースを使用したキャッシュのアクセスと操作: INamedCacheは、.NETコレクション・フレームワークの標準のIDictionaryインタフェース(.NET Hashtableクラスで実装されるインタフェースと同じ)を拡張します。

- キャッシュ内で発生するすべてのオブジェクト変更に対するイベント発行: INamedCacheはIObservableCacheインタフェースを拡張します。

- キャッシュ内オブジェクトの問合せ: INamedCacheはIQueryCacheインタフェースを拡張します。

- キャッシュ内オブジェクトの分散パラレル処理および集約: INamedCacheはIInvocableCacheインタフェースを拡張します。

ContinuousQueryCacheクラスは、Coherence for .NETのすべてのキャッシュで提供されるAPIであるINamedCacheインタフェースを実装しているため、非常に使いやすく、その機能が必要になった場合に別のキャッシュと簡単に置き換えることができます。

19.3 連続問合せキャッシュの構成

連続問合せキャッシュは、次の2つの項目で定義されます。

- 基礎となるキャッシュ

- その基礎となるキャッシュの問合せ(連続問合せキャッシュにキャッシュされるサブセットを生成)

基礎となるキャッシュには、別の連続問合せキャッシュを含めた任意のCoherence for .NETキャッシュを使用できます。キャッシュは一般にCacheFactoryで取得されます。これにより開発者は、次の例に示すように、キャッシュの名前を指定するだけでアプリケーションのキャッシュ構成情報に基づいて自動的にキャッシュを構成できます。

INamedCache cache = CacheFactory.GetCache("orders");

この問合せは、他のキャッシュの問合せに使用される問合せと同じタイプです。例:

Filter filter = new AndFilter(new EqualsFilter("getTrader", traderid),
new EqualsFilter("getStatus", Status.OPEN));

通常、キャッシュを問い合せるには、IQueryCacheのメソッドを使用します。たとえば、このトレーダーの未決済ポジションすべてのスナップショットを取得するには、次のコードを使用します。

ICollection setOpenTrades = cache.GetEntries(filter);

同様に、連続問合せキャッシュは、次に示す同じ2つの要素で構成されます。

ContinuousQueryCache cacheOpenTrades = new ContinuousQueryCache(cache, filter);

19.4 連続問合せキャッシュ・リソースのクリーンアップ

すべてのINamedCache実装のインスタンスは、ContinuousQueryCacheを含め、不要になった時点でINamedCache.Release()メソッドをコールして明示的に解放し、これらのインスタンスで保持されているリソースをすべて解放する必要があります。

特定のINamedCacheがアプリケーションの継続期間を通して使用される場合、リソースはそのアプリケーションがシャットダウンされたとき、または停止したときにクリーンアップされます。ただし、わずかの間だけ使用される場合は、使い終わった時点でアプリケーションからRelease()メソッドをコールする必要があります。

または、INamedCacheがIDisposableを拡張し、すべてのキャッシュ実装がIDisposable.Dispose()のコールをINamedCache.Release()に委任しているという事実を利用する方法もあります。単一メソッド内でキャッシュ・インスタンスを取得および解放する必要がある場合、次のusingブロックを使用してそれを実現できます。

例19-1 連続問合せキャッシュへの参照の取得と解放

using (INamedCache cache = CacheFactory.GetCache("my-cache"))
{
// use cache as usual
}

usingブロックが終了すると、INamedCacheインスタンスでIDisposable.Dispose()がコールされ、そのインスタンスに関連付けられているすべてのリソースが解放されます。

19.5 キーのみのキャッシングと、キーおよび値のキャッシング

連続問合せキャッシュを構成する際、問合せで取得されたキーだけをキャッシュで追跡し、要求された場合にのみ、その値を基礎となるキャッシュから取得するように指定することができます。この機能は、問合せの結果セットが非常に膨大になる連続問合せキャッシュを作成する場合、または値をリクエストされることがないか、ほとんどない場合に役立ちます。キーのみをキャッシュするように指定するには、次の例に示すように、IsCacheValuesプロパティを構成できるコンストラクタを使用します。

例19-2 連続問合せキャッシュへのキーのみのキャッシュ

ContinuousQueryCache cacheOpenTrades = new ContinuousQueryCache(cache, filter, false);

次の例に示すように、必要に応じて、キャッシュがインスタンス化された後にIsCacheValuesプロパティを変更することもできます。

cacheOpenTrades.IsCacheValues = true;

IsCacheValuesプロパティとイベント・リスナー

連続問合せキャッシュに標準の(非Lite)イベント・リスナーがある場合、またはイベント・リスナーのいずれかがフィルタリングされる場合は、IsCacheValuesプロパティが自動的にtrueに設定されます。これは、イベントをフィルタリングする際、および発生させたイベントに古い値と新しい値を提供する際に、ローカルにキャッシュされた値を連続問合せキャッシュが使用するためです。

19.6 連続問合せキャッシュのリスニング

連続問合せキャッシュ自体は監視可能であるため、クライアントが連続問合せキャッシュに1つ以上のイベント・リスナーを配置することが可能です。例:

例19-3 連続問合せキャッシュでのリスナーの配置

ContinuousQueryCache cacheOpenTrades = new ContinuousQueryCache(cache, filter);
cacheOpenTrades.AddCacheListener(listener);

キャッシュに格納されているすべてのアイテムとキャッシュに追加されるすべてのアイテムに対してなんらかの処理を実行する必要がある場合、その方法は2つあります。1つは、処理を実行した後、以降の追加に対処するリスナーを追加する方法です。

例19-4 データを処理してからリスナーを配置する場合

ContinuousQueryCache cacheOpenTrades = new ContinuousQueryCache(cache, filter);
foreach (ICacheEntry entry in cacheOpenTrades.Entries)
{
// .. process the cache entry
}
cacheOpenTrades.AddCacheListener(listener);

ただし、このコードは正しくありません。これでは、反復処理が終了してリスナーが追加されるまでのわずかの時間に発生したイベントを見逃すことになります。別の方法では、イベントを見逃さないように、まずリスナーを追加し、その後で処理を実行します。

例19-5 リスナーを配置してからデータを処理する場合

ContinuousQueryCache cacheOpenTrades = new ContinuousQueryCache(cache, filter);
cacheOpenTrades.AddCacheListener(listener);
foreach (ICacheEntry entry in cacheOpenTrades.Entries)
{
// .. process the cache entry
}

ただし、イベントとIEnumeratorの両方に同じエントリが出現する可能性があります。また、イベントは非同期の可能性があるため、操作の順序は保証されません。

これを解決するには、構成時にリスナーを提供します。これで、連続問合せキャッシュ内のアイテムが(問合せに含まれていたため)最初から存在していたか、キャッシュの作成中または作成後に追加されたかに関係なく、連続問合せキャッシュはアイテムごとに1つのイベントを受信します。

例19-6 連続問合せキャッシュの構成時にリスナーを提供する場合

ContinuousQueryCache cacheOpenTrades = new ContinuousQueryCache(cache, filter, listener);

19.6.1 安定したマテリアライズド・ビューの実現

連続問合せキャッシュの実装にも同じ課題がありました。同じキャッシュから変更イベントのストリームを受信しながら、基礎となるキャッシュの正確なポイント・イン・タイム・スナップショットをいかにアセンブルするかということです。その解決法は、いくつかの部分に分かれています。第1に、Coherence for .NETでは同期イベントのオプションがサポートされ、それによって一連の順序保証が実現します。第2に、連続問合せキャッシュでは、その初期移入の実装が2つのフェーズに分かれているため、まず基礎となるキャッシュに対して問合せを実行し、その後、最初のフェーズ中に発生したイベントをすべて解決できます。このようにイベントを見逃したり重複させたりすることなくデータの可視性を保証する操作はかなり複雑であるため、連続問合せキャッシュでは、アプリケーション開発者が作成時にリスナーを渡すことで、この複雑さに対処しなくても済むようにしています。

19.6.2 同期および非同期リスナーのサポート

デフォルトでは、連続問合せキャッシュに対するリスナーによって、リスナーのイベントが非同期に配信されます。ただし連続問合せキャッシュでは、CacheListenerSupport.ISynchronousListenerインタフェースで規定されているとおり、同期イベントのオプションが考慮されます。

19.7 連続問合せキャッシュを読取り専用にする

連続問合せキャッシュは、次の例のように、読取り専用キャッシュにすることができます。

例19-7 連続問合せキャッシュを読取り専用にする

cacheOpenTrades.IsReadOnly = true;

読取り専用の連続問合せキャッシュでは、オブジェクトの追加、変更、削除またはロックができません。

連続問合せキャッシュを読取り専用に設定した後は、読取り/書込みに戻すことはできません。

20 リモート起動の実行(.NET)

この章では、.NETクライアントからCoherenceキャッシュでリモート起動を実行する手順を示します。

この章は次の各項で構成されています。

- リモート起動の実行の概要

- リモート起動サービスの構成と使用

20.1 リモート起動の実行の概要

Coherence for .NETでは、クライアントが接続されているクラスタ側JVM内でのIInvocableオブジェクトと呼ばれる単一パス・エージェントの実行を可能にするリモート起動サービスを提供しています。エージェントは、IInvocableインタフェースを実装する単純な実行可能アプリケーション・クラスです。エージェントは任意のアクションを実行でき、作業を行うために必要な任意のクラスタ側サービス(キャッシュ・サービスやグリッド・サービスなど)を使用できます。エージェントの操作はステートフルにすることもできます。つまり、その状態がシリアライズされ、エージェントが実行されるグリッド・ノードに転送されます。

20.2 リモート起動サービスの構成と使用

リモート起動サービスは、キャッシュ構成ディスクリプタの<remote-invocation-scheme>要素を使用して構成します。例:

例20-1 リモート起動サービスの構成

...
<remote-invocation-scheme>
<scheme-name>example-invocation</scheme-name>
<service-name>ExtendTcpInvocationService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>30s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-invocation-scheme>
...

CacheFactoryクラスを使用することによって、構成済リモート起動サービスへの参照を名前によって取得できます。

例20-2 リモート起動サービスへの参照の取得

IInvocationService service = (IInvocationService) CacheFactory.GetService("ExtendTcpInvocationService");

クライアントが接続されているグリッド・ノードでエージェントを実行するために必要なコードは、次の1行のみです。

例20-3 グリッド・ノードでのエージェントの実行

IDictionary result = service.Query(new MyTask(), null);

単一の実行結果には、CacheFactory.ConfigurableCacheFactory.LocalMemberをコールして取得されるローカルのMemberがキー設定されます。

注意:

キャッシュされた値オブジェクト同様、すべてのIInvocable実装クラスは、.NETアプリケーションのPOFコンテキストおよびクライアントが接続されているクラスタ側ノードのPOFコンテキストに正しく登録する必要があります。したがって、IInvocableタスクのJava実装(com.tangosol.net.Invocable実装)は、クラスタ側ノードで作成、コンパイルおよびデプロイする必要があります。タスクを実際に実行するのは、.NETのIInvocable実装ではなく、JavaのInvocable実装であることに注意してください。

詳細は、第16章「.NETクライアントの構成と使用」を参照してください。

21 トランザクションの実行(.NET)

この章では、トランザクション・フレームワークAPIを使用して、.NETクライアント使用時にトランザクション内でキャッシュ操作が実行されるようにする手順について説明します。この手順では、トランザクションAPIの詳細な使用方法は説明しません。トランザクションAPIの使用方法の詳細は、『Oracle Coherenceでのアプリケーションの開発』のトランザクション・フレームワークAPIに関する項を参照してください。

この章は、トランザクションの実行に必要な次の各項で構成されています。

- 入力プロセッサ内でのトランザクションAPIの使用方法

- トランザクション入力プロセッサ用のスタブ・クラスの作成

- トランザクション入力プロセッサのユーザー・タイプの登録

- クラスタ側のトランザクション・キャッシュの構成

- クライアント側のリモート・キャッシュの構成

- .NETクライアントからのトランザクション入力プロセッサの使用方法

21.1 入力プロセッサ内でのトランザクションAPIの使用方法

.NETクライアントは、トランザクション・フレームワークAPIを利用することによって、トランザクション内でキャッシュ操作を実行します。トランザクションAPIは、.NETでネイティブではサポートされていないため、入力プロセッサ内で使用する必要があります。入力プロセッサはJavaでクラスタ上に実装され、入力プロセッサのスタブ・クラスはC#でクライアント上に実装されます。いずれのクラスでも、POFを使用して、JavaとC#の間でシリアライズを行います。

例21-1は、トランザクションAPIを使用してトランザクション内で単純なupdate操作を実行する入力プロセッサを示しています。実行時には、Coherenceプロキシ・サーバーのクラスパス上にクラスを配置する必要があります。

例21-1 Extendクライアント・トランザクション用の入力プロセッサ

package coherence.tests;

import com.tangosol.coherence.transaction.Connection;
import com.tangosol.coherence.transaction.ConnectionFactory;
import com.tangosol.coherence.transaction.DefaultConnectionFactory;
import com.tangosol.coherence.transaction.OptimisticNamedCache;
import
com.tangosol.coherence.transaction.exception.PredicateFailedException;
import com.tangosol.coherence.transaction.exception.RollbackException;
import
com.tangosol.coherence.transaction.exception.UnableToAcquireLockException;
import com.tangosol.util.Filter;
import com.tangosol.util.InvocableMap;
import com.tangosol.util.extractor.IdentityExtractor;
import com.tangosol.util.filter.EqualsFilter;
import com.tangosol.util.processor.AbstractProcessor;

public class MyTxProcessor extends AbstractProcessor implements PortableObject
{
public Object process(InvocableMap.Entry entry)
{
// obtain a connection and transaction cache
ConnectionFactory connFactory = new DefaultConnectionFactory();
Connection conn = connFactory.createConnection("TransactionalCache");
OptimisticNamedCache cache = conn.getNamedCache("MyTxCache");

conn.setAutoCommit(false);

// get a value for an existing entry
String sValue = (String) cache.get("existingEntry");

// create predicate filter
Filter predicate = new EqualsFilter(IdentityExtractor.INSTANCE, sValue);

try
{
// update the previously obtained value
cache.update("existingEntry", "newValue", predicate);
}
catch (PredicateFailedException e)
{
// value was updated after it was read
conn.rollback();
return false;
}
catch (UnableToAcquireLockException e)
{
// row is being updated by another tranaction
conn.rollback();
return false;
}
try
{
conn.commit();
}
catch (RollbackException e)
{
// transaction was rolled back
return false;
}
return true;
}

public void readExternal(PofReader in)
throws IOException
{
}

public void writeExternal(PofWriter out)
throws IOException
{
}
}

21.2 トランザクション入力プロセッサ用のスタブ・クラスの作成

入力プロセッサのスタブ・クラスを使用すると、クライアントはクラスタ上でトランザクション入力プロセッサを利用できます。スタブ・クラスはC#で実装され、POFを使用してシリアライズを行います。POFを使用することにより、C#とJavaの間で入力プロセッサをシリアライズできます。入力プロセッサのスタブ・クラスにはトランザクション・ロジックは必要ありません。これはトランザクション入力プロセッサのスケルトンです。.NETでPOFを使用する際の詳細は、第17章「.NETクライアントの統合オブジェクトの構築」を参照してください。

例21-2は、例21-1で作成したトランザクション入力プロセッサの入力プロセッサ・スタブ・クラスを示しています。

例21-2 トランザクション入力プロセッサの.NETスタブ・クラス

using Tangosol.IO.Pof;
using Tangosol.Net.Cache;
using Tangosol.Util.Processor;

namespace Coherence.Tests{
public class MyTxProcessor : AbstractProcessor, IPortableObject
{
public MyTxProcessor()
{
}

public override object Process(IInvocableCacheEntry entry)
{
return null;
}

public void ReadExternal(IPofReader reader)
{
}

public void WriteExternal(IPofWriter writer)
{
}
}
}

21.3 トランザクション入力プロセッサのユーザー・タイプの登録

カスタム・ユーザー・タイプは、Javaトランザクション入力プロセッサに関してはクラスタ側のPOF構成ファイルで、クライアント・スタブに関してはクライアント側のPOF構成ファイルで登録する必要があります。両方の登録で、同じタイプIDを使用する必要があります。次の例は、例21-1で作成したMyTxProcessorクラスと、例21-2で作成したクライアント・スタブ・クラスのそれぞれの登録方法を示しています。

クラスタ側のPOF構成:

<?xml version="1.0"?>

<pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config
coherence-pof-config.xsd">
<user-type-list>
<include>coherence-pof-config.xml</include>
<include>txn-pof-config.xml</include>
<user-type>
<type-id>1599</type-id>
<class-name>coherence.tests.MyTxProcessor</class-name>
</user-type>
</user-type-list>
</pof-config>

クライアント側のPOF構成:

<?xml version="1.0"?>

<pof-config xmlns="http://schemas.tangosol.com/pof"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/pof
assembly://Coherence/Tangosol.Config/pof-config.xsd">
<user-type-list>
<include>coherence-pof-config.xml</include>
<user-type>
<type-id>1599</type-id>
<class-name>Coherence.Tests.MyTxProcessor</class-name>
</user-type>
</user-type-list>
</pof-config>

21.4 クラスタ側のトランザクション・キャッシュの構成

トランザクションを実行するには、クラスタ側のキャッシュ構成ファイルでトランザクション・キャッシュを定義する必要があります。トランザクション・キャッシュは、トランザクション・フレームワークでトランザクション保証を行うために使用します。トランザクション・キャッシュの詳細は、『Oracle Coherenceでのアプリケーションの開発』のトランザクション・キャッシュの定義に関する項を参照してください。

次の例では、MyTxCacheという名前のトランザクション・キャッシュを作成します。これは、例21-1で入力プロセッサによって使用されていたキャッシュ名です。この構成には、リモート・クライアントから入力プロセッサを実行する際に必要なプロキシ・スキームと分散キャッシュ・スキームも含まれています。プロキシは、ポート9099のlocalhostでクライアントのTCP/IP接続を受け入れるように構成します。Coherence*Extend使用時にクラスタ側のキャッシュを構成する方法の詳細は、第4章「Coherence*Extendの設定」を参照してください。

<?xml version='1.0'?>

<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>MyTxCache</cache-name>
<scheme-name>example-transactional</scheme-name>
</cache-mapping>
<cache-mapping>
<cache-name>dist-example</cache-name>
<scheme-name>example-distributed</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<transactional-scheme>
<scheme-name>example-transactional</scheme-name>
<service-name>TransactionalCache</service-name>
<thread-count>7</thread-count>
<high-units>15M</high-units>
<task-timeout>0</task-timeout>
<autostart>true</autostart>
</transactional-scheme>

<distributed-scheme>
<scheme-name>example-distributed</scheme-name>
<service-name>DistributedCache</service-name>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>localhost</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>

21.5 クライアント側のリモート・キャッシュの構成

クラスタのプロキシに接続してトランザクション入力プロセッサを実行するには、リモート・クライアントにリモート・キャッシュが必要です。リモート・キャッシュは、クライアント側のキャッシュ構成ファイルで定義します。クライアント側のキャッシュを構成する方法の詳細は、第4章「Coherence*Extendの設定」を参照してください。

次の例では、リモート・キャッシュをポート9099のlocalhostに配置されているプロキシに接続するように構成します。また、リモート・キャッシュの名前(dist-example)はトランザクション入力プロセッサの開始時に使用されるクラスタ側のキャッシュの名前と一致している必要があります。

<?xml version='1.0'?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-example</cache-name>
<scheme-name>extend</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
<connect-timeout>30s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>30s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>

21.6 .NETクライアントからのトランザクション入力プロセッサの使用方法

クライアントで入力プロセッサのスタブ・クラスを起動する方法は、入力プロセッサを起動する方法と同じです。ただし、実行時に、クラスタ側の入力プロセッサがクラスタ上で起動されます。起動がJavaクラスに委任されたことは、クライアント側では認識されません。次の例は、入力プロセッサのスタブ・クラスを使用して、結果的に例21-1で作成したトランザクション入力プロセッサを起動するクライアントを示しています。

INamedCache cache  = CacheFactory.GetCache("dist-example");
object      result = cache.Invoke( "AnyKey", new MyTxProcessor());

Console.Out.WriteLine("Result of extend transaction execution: " + result );

22 ASP.NETセッション状態の管理

この章では、CoherenceクラスタでASP.NETセッション状態を管理する手順について説明します。手順には、Coherenceセッション・プロバイダを有効にして構成する方法が含まれます。

この章には次の項が含まれます:

- 概要

- Coherenceセッション管理の設定

- セッション・モデルの選択

- シリアライザの指定

- アプリケーション間でのセッション状態の共有

22.1 概要

Coherence for .NETを使用すると、CoherenceクラスタでASP.NETセッション状態を管理できます。これには、Microsoftが提供するデフォルトのオプションと比較して、次のようないくつかの利点があります。

- 可用性の高いCoherenceクラスタにセッション状態が格納されるため、Webサーバーの障害に対するセッションの回復力が高まります。

- セッションがメモリーに格納されるため、SQL Serverセッション・プロバイダを使用してディスクに対してシリアライズする場合よりもアクセスが大幅に高速になります。

- リレーショナル・データベースとは異なり、Coherenceクラスタは簡単にスケール・アウトして負荷の増加に対応できます。

- 場合によっては、Coherenceのニア・キャッシュ機能を利用することにより、インプロセス速度でセッション・データにアクセスできます。

ASP.NETアプリケーションは、web.configファイルを変更し、カスタムのセッション状態プロバイダを構成することにより、Coherenceを使用してセッション状態を管理するように構成されます。また、Coherenceセッション・プロバイダに含まれている構成オプションを使用すると、アプリケーションのパフォーマンスおよびスケーラビリティを大幅に向上できます。

22.2 Coherenceセッション管理の設定

Coherenceを使用してASP.NETセッションを管理するには、次の手順が必要です。

- オペレーション構成、キャッシュ構成およびPOF構成ファイル(POFを使用してセッションをシリアライズする場合)を指定することにより、Coherence for .NETクライアント・ライブラリを構成します。詳細は、「Coherence .NETクライアント・ライブラリの設定」を参照してください。

- Coherenceセッション・プロバイダの有効化

- クラスタ側のASPセッション・キャッシュの構成

- クライアント側のASPセッション・リモート・キャッシュの構成

- デフォルトのセッション・キャッシュ名のオーバーライド

ASP.NETアプリケーションおよびクラスタを適切に構成したら、アプリケーションで使用するクラスタ・サーバーとプロキシ・サーバーを起動して、ASP.NET Webアプリケーションを起動します。セッションはCoherenceクラスタ内に自動的に格納されます。

22.2.1 Coherenceセッション・プロバイダの有効化

ASP.NETでは、プロバイダ・モデルを使用して、カスタムのセッション状態管理を実装できます。Coherence for .NETは、Microsoftが定義している規定を満たすカスタム・プロバイダを実装します。Coherenceプロバイダを使用するには、アプリケーションのweb.configファイルに次のプロバイダ構成を追加します。

<system.web>
<sessionState mode="Custom"
customProvider="CoherenceSessionProvider"
cookieless="false"
timeout="20">
<providers>
<add name="CoherenceSessionProvider"
type="Tangosol.Web.CoherenceSessionStore, Coherence"/>
</providers>
</sessionState>
...
</system.web>

前述の例では、CoherenceSessionStoreプロバイダをデフォルト設定で使用するように、ASP.NETアプリケーションを構成します。Coherenceセッション・プロバイダは、組み込まれた機能をフル活用するために、この章で説明するようにカスタマイズできます。

22.2.2 クラスタ側のASPセッション・キャッシュの構成

Coherenceセッション・プロバイダでは、記憶域キャッシュとオーバーフロー・キャッシュの2つのキャッシュ・スキーム定義がクラスタのキャッシュ構成ファイル内に必要です。記憶域キャッシュはセッション・データの保存に使用し、オーバーフロー・キャッシュはセッションのサイズがWeb.configファイルで定義されているCoherenceSessionProviderのexternalAttributeSize属性で指定されている制限を超えた場合に使用されます。

セッションの記憶域キャッシュとセッション・オーバーフロー・キャッシュを定義するときは、サービス名はAspNetSessionCache、キャッシュ名はそれぞれaspnet-session-storageおよびaspnet-session-overflowとする必要があります。また、記憶域キャッシュは、ConfigurablePofContextクラスをシリアライザとして使用するように構成する必要があります。スキーム名とバッキング・マップ構成は、必要に応じて構成できます。

次のキャッシュ・スキーム定義では、セッション・プロバイダで使用する2つの分散キャッシュ(1つはセッションの記憶域用、1つはセッション・オーバーフロー用)を作成します。

<?xml version='1.0'?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>aspnet-session-storage</cache-name>
<scheme-name>aspnet-session-scheme</scheme-name>
</cache-mapping>
<cache-mapping>
<cache-name>aspnet-session-overflow</cache-name>
<scheme-name>aspnet-session-overflow-scheme</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<distributed-scheme>
<scheme-name>aspnet-session-scheme</scheme-name>
<service-name>AspNetSessionCache</service-name>
<serializer>
<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
<init-params>
<init-param>
<param-type>string</param-type>
<param-value>coherence-pof-config.xml</param-value>
</init-param>
</init-params>
</serializer>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

<distributed-scheme>
<scheme-name>aspnet-session-overflow-scheme</scheme-name>
<scheme-ref>dist-default</scheme-ref>
<service-name>AspNetSessionCache</service-name>
<autostart>true</autostart>
</distributed-scheme>
</caching-schemes>
</cache-config>

22.2.3 クライアント側のASPセッション・リモート・キャッシュの構成

Coherenceセッション・プロバイダでは、Extendクライアントのキャッシュ構成ファイルに、セッション記憶域キャッシュ用とセッション・オーバーフロー・キャッシュ用のリモート・キャッシュ・スキームを含める必要があります。他のリモート・キャッシュと同様に、クラスタ上のキャッシュとクライアント上のキャッシュでは同じ名前を使用する必要があります。詳細は、「リモート・キャッシュの定義」を参照してください。

次の例では、Coherenceセッション・プロバイダでクラスタにセッション・データを格納する際に使用する、クライアント側のASPセッション・リモート・キャッシュ・スキームを構成します。

<?xml version='1.0'?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>aspnet-session-storage</cache-name>
<scheme-name>extend-direct</scheme-name>
</cache-mapping>
<cache-mapping>
<cache-name>aspnet-session-overflow</cache-name>
<scheme-name>extend-direct</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend-direct</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>localhost</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>30s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>

22.2.4 デフォルトのセッション・キャッシュ名のオーバーライド

Coherenceセッション・プロバイダのデフォルトの動作では、aspnet-session-storageという名前のリモート・セッション・キャッシュが使用されます。「クライアント側のASPセッション・リモート・キャッシュの構成」のリモート・キャッシュの例は、デフォルト名でリモート・キャッシュを作成しています。また、セッション・プロバイダは、デフォルト以外の名前のリモート・キャッシュを使用するように構成できます。

デフォルトのセッション・キャッシュ名をオーバーライドするには、プロバイダの構成内にcacheName属性を追加します。次の例では、my-session-cacheという名前のキャッシュを指定しています。

<system.web>
<sessionState mode="Custom"
customProvider="CoherenceSessionProvider"
cookieless="false"
timeout="20">
<providers>
<add name="CoherenceSessionProvider"
type="Tangosol.Web.CoherenceSessionStore, Coherence"/>
cacheName="my-session-cache"
</providers>
</sessionState>
...
</system.web>

22.3 セッション・モデルの選択

セッション・モデルは、クラスタ内のセッション状態をCoherenceセッション・プロバイダでどのように物理的に表現し、保存するかを記述します。プロバイダは、次の3つのすぐに使用できる様々なセッション・モデル実装を備えています。

- トラディショナル・モデル - すべてのセッション状態を単一のエンティティとして保存しますが、属性は個別にシリアライズおよびデシリアライズします。

- モノリシック・モデル - すべてのセッション状態を単一のエンティティとして保存し、すべての属性を単一の操作でシリアライズおよびデシリアライズします。

- スプリット・モデル - トラディショナル・モデルを拡張したモデルですが、大きなセッション属性は独立した複数の物理エンティティに分離します。

トラディショナル・モデルがデフォルトの設定です。これはASP.NETのSessionStateItemCollectionに類似しています。アクセスされない項目のデシリアライズの問題を回避するために、時間をかけてセッション項目をデシリアライズします。ただし、モノリシック・モデルまたはスプリット・モデルを選択したほうがよい場合もあります。

各モデルの利点と不利な点については、Oracle Coherence*WebでのHTTPセッション・マネージメントの管理のセッション・モデルに関する項を参照してください。そこでの説明は、特定のアプリケーションに最適なモデルを決定する際に役立つ場合があります。Coherence*Webを中心に説明されていますが、一般的な概念はASP.NETセッションと同じです。

22.3.1 セッション・モデルの指定

スプリット・モデルは、ほとんどのアプリケーションにお薦めできるセッション・モデルです。ただし、HTTPセッション・オブジェクトが小型であることがわかっているアプリケーションには、トラディショナル・モデルのほうが適してる場合があります。

モノリシック・モデルは、複数のセッション属性で1つの共有オブジェクトを参照し、そのオブジェクトを共有オブジェクトとして維持する必要がある場合、それら複数のセッション属性に関連する特定のクラスの問題を解決することを目的としています。ASP.NET InProcプロバイダからCoherenceセッション・プロバイダに移行する場合には、モノリシック・モデルを使用すると、すべての共有オブジェクトが適切にシリアライズおよびデシリアライズされます。

Coherenceセッション・プロバイダのセッション・モデルを指定するには、プロバイダの構成内にmodel属性を追加します。次の例ではsplitモデルを指定します。

<system.web>
<sessionState mode="Custom"
customProvider="CoherenceSessionProvider"
cookieless="false"
timeout="20">
<providers>
<add name="CoherenceSessionProvider"
type="Tangosol.Web.CoherenceSessionStore, Coherence"
model="split"
externalAttributeSize="512"/>
</providers>
</sessionState>
...
</system.web>

model属性の有効な値は、traditional、monolithic、split、またはTangosol.Web.ISessionModelManagerインタフェースを実装し、単一のTangosol.IO.ISerializer引数を受け入れるコンストラクタを提供するクラスの完全修飾名です。このインタフェースでは、必要に応じてカスタム・モデル実装を作成できます。

前述の例では、セッション・プロバイダはsplitモデルを使用するように構成されます。スプリット・モデルはexternalAttributeSize属性をサポートしています。この属性では、個々に保存する必要のある属性の最小サイズ(バイト数)を指定します。externalAttributeSize属性の指定を省略すると、デフォルト値である1024バイトが使用されます。

22.3.1.1 バッキング・マップ・リスナーの登録

スプリット・セッション・モデルを使用すると、セッションの属性は2つのリージョンにパーティション化されます。セッションID、作成時刻、最終アクセスなどの主要なHTTPセッション属性は一方のパーティション内で管理され、大型の属性はもう一方のパーティションに分割されます。これにより、小型の属性に頻繁にアクセスすることによってオーバーヘッドが生じることなく、非常に大型のHTTPセッション・オブジェクトをサポートできます。

.NETセッション・プロバイダの実装では、主要な属性と大型の属性は別々のキャッシュに格納されます。したがって、両方のキャッシュの同期を維持するために、バッキング・マップ・リスナー(AspNetSessionStoreProvider$SessionCleanupListenerクラス)をお薦めします。これにより、セッションがユーザーによって明示的に終了された場合およびエビクションまたは失効によって削除された場合、セッションの主要セグメントと大型セグメントの両方が、2つのキャッシュから一貫して削除されます。

次の例は、クラスタ側のASP .NETセッション・キャッシュでAspNetSessionStoreProvider$SessionCleanupListenerバッキング・マップ・リスナーを登録する方法を示しています。

<caching-schemes>
<distributed-scheme>
<scheme-name>aspnet-session-scheme</scheme-name>
<service-name>AspNetSessionCache</service-name>
<serializer>
<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
<init-params>
<init-param>
<param-type>string</param-type>
<param-value>coherence-pof-config.xml</param-value>
</init-param>
</init-params>
</serializer>
<backing-map-scheme>
<local-scheme>
<class-name>com.tangosol.net.cache.LocalCache</class-name>
<listener>
<class-scheme>
<class-name>
com.tangosol.net.internal.AspNetSessionStoreProvider$SessionCleanupListener
</class-name>
<init-params>
<init-param>
<param-type>
com.tangosol.net.BackingMapManagerContext
</param-type>
<param-value>{manager-context}</param-value>
</init-param>
</init-params>
</class-scheme>
</listener>
</local-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

22.4 シリアライザの指定

Coherenceセッション・プロバイダは、特定のシリアライザを使用してセッション項目をシリアライズするように構成できます。シリアライザを指定するには、プロバイダの定義内にserializer属性を追加します。次の例では、binaryシリアライザを指定します。

<system.web>
<sessionState mode="Custom"
customProvider="CoherenceSessionProvider"
cookieless="false"
timeout="20">
<providers>
<add name="CoherenceSessionProvider"
type="Tangosol.Web.CoherenceSessionStore, Coherence"
model="split"
externalAttributeSize="512"
serializer="binary"/>
</providers>
</sessionState>
...
</system.web>

serializer属性の有効な値は、binary(デフォルト)、pof、または、Tangosol.IO.ISerializerインタフェースを実装するクラスの完全修飾名です。必要に応じて、このインタフェースを使用してカスタム・シリアライザを作成します。ただし、多くの場合は、既存のシリアライザで十分です。

22.4.1 POFを使用したセッションのシリアライズ

Portable Object Format (POF)は、Coherenceを使用してASP.NETセッションを管理する場合に推奨されるシリアライズ形式であり、標準の.NETバイナリ・シリアライズと比べて多くの利点があります。特に、POFシリアライズのほうが高速で、圧縮率の高い形式です。圧縮形式は、通常、標準のバイナリ・シリアライザの3分の1から5分の1のバイナリになります。このことは、クラスタ内のメモリーのフットプリントを小さくすることに直結し、コストを大幅に削減できます。

POFを使用するには、セッション内に直接または間接的に格納されているすべてのカスタム・クラスがPOFコンテキスト内で登録されていることを確認し、IPortableObjectインタフェースを実装するか、外部のIPofSerializerを構成します。POFの使用手順の詳細は、第17章「統合オブジェクトの構築(.NET)」を参照してください。

次の説明では、POFを使用する際に考慮する必要のある実装の詳細をいくつかまとめます。POF形式の詳細は、『Oracle Coherenceでのアプリケーションの開発』の付録のPIF-POFバイナリ形式に関する項を参照してください。

セッション項目がPOFシリアライザによってデシリアライズされた場合、生成されるオブジェクトの型が元の値の型と同じになるという保証はありません。たとえば、-1から22の整数値は、元の型とは関係なくInt32の値として返されるため、適切な型へのキャストが必要になる場合があります。

コレクションも別の型にデシリアライズされる場合があります。たとえば、ArrayListがセッション内に格納されているものの、オブジェクトを読み戻した後で不変オブジェクト配列が受信される場合があります。これは必要な動作であり、POFストリームからコレクションを読み取るすべてのメソッドに対して、IPofReaderインタフェースが値を読み取るテンプレートを引数として提供する理由でもあります。

セッション項目は型指定されないため、デシリアライズ方法を指定する方法はありません。したがって、デフォルトのコレクション型がつねに受信されます。これは、コレクションから読み取る場合は通常受入れ可能です。ただし、コレクションを変更する必要がある場合は、次の2つのうちいずれかのオプションを使用できます。

- 必要な型の可変コレクションのインスタンスを作成し、デシリアライズしたコレクションから要素を追加します。このオプションを使用する場合は、忘れずに、対応するセッション項目を新しいコレクションで更新してください。そうしないと、変更は保存されません。

- ベア・コレクションを直接格納するかわりに、必要なシリアライズ・ロジックを実装してPOFコンテキスト内で登録するラッパー・クラスを作成します。これにより、コレクションのシリアライズを完全に制御でき、前述の問題を回避できます。

この手順には追加の作業が必要ですが、パフォーマンスが向上し、メモリー・フットプリントを削減できるため、手間をかける価値はあります。

22.5 アプリケーション間でのセッション状態の共有

複数のASP.NETアプリケーション間でセッションを共有できると有益な場合があります。デフォルトでは、セッション・キーは、アプリケーションID(HostingEnvironment.ApplicationIDプロパティによって返される)とセッションIDを結合することによって特定されます。これにより、セッション共有を効果的に防止できます。

Coherenceセッション・プロバイダは、特定のアプリケーションIDを使用するように構成できます。アプリケーションIDを指定するには、プロバイダ定義内にapplicationId属性を追加します。次の例では、MyApplicationをアプリケーションIDとして指定します。

<system.web>
<sessionState mode="Custom"
customProvider="CoherenceSessionProvider"
cookieless="false"
timeout="20">
<providers>
<add name="CoherenceSessionProvider"
type="Tangosol.Web.CoherenceSessionStore, Coherence"
applicationId="MyApplication"
model="split"
externalAttributeSize="512"
serializer="pof"/>
</providers>
</sessionState>
...
</system.web>

アプリケーション間でセッション共有を有効にするには、同じapplicationIdで複数のアプリケーションを構成し、これらがセッションIDを含むCookieを確実に共有するようにします。

第V部

Coherence RESTの使用方法

第V部の内容は次のとおりです。

- 第23章「Coherence Restについて」

- 第24章「最初のCoherence RESTアプリケーションの作成」

- 第25章「RESTによるグリッド操作の実行」

- 第26章「Coherence RESTのデプロイ」

- 第27章「デフォルトのREST実装の変更」

23 Coherence RESTについて

この章では、Coherence RESTのサポートの概要について説明します。ユーザーは、Coherence RESTを使用するために、WebサービスおよびJAX-RSに精通する必要があります。

この章には次の項が含まれます:

- Coherence RESTの概要

- Coherence RESTの依存性

- Coherence RESTの構成の概要

- データ・フォーマットのサポートの理解

- Coherence RESTクライアントの認証と認可

23.1 Coherence RESTの概要

Coherence RESTは、HTTPプロトコルを介したCoherenceキャッシュおよびキャッシュ・エントリへの容易なアクセスを提供します。これは、Coherence*Extendに似ています。リモート・クライアントは、クラスタ自体のメンバーになることなく、Coherenceに保存されたデータにアクセスできます。ただし、独自のプロトコルのCoherence*Extendと異なり、Coherence RESTでは、基本プロトコルとしてHTTPを使用して、JSONやXMLなどの複数の表現形式でデータをマーシャリングできます。Coherence RESTの利点は、RubyやPythonなど(Coherenceでネイティブにサポートされていない)別の言語で記述されたアプリケーションがキャッシュ・データと相互作用できるということです。

23.2 Coherence RESTの依存性

Coherence RESTは、次の表示23-1に示されているライブラリに依存します。JerseyおよびJackson JARSは、ORACLE_HOME/oracle_common/modulesディレクトリに含まれます。Grizzly JARSは、Grizzlyプロジェクト・ページからダウンロードできます。

http://grizzly.java.net/

表23-1 Coherence RESTの依存性

名前

説明

ライセンス・タイプ

JARファイル

Jersey 1.17.1

JAX-RSのリファレンス実装(JSR 311: RESTful Webサービス用Java API)

- CDDL v1.1

- GPL v2

- jersey-core-1.17.1.jar

- jersey-multipart-1.17.1.jar

- jersey-json-1.17.1.jar

- jersey-server-1.17.1.jar

- jersey-servlet-1.17.1.jar

- jersey-grizzly2-1.12.jar: Jersey Projectページからダウンロードする必要があります。
http://jersey.java.net/

Grizzly 2.2.1

Jerseyと最適に統合される埋込みWebサーバー(Glassfishの一部)。

- CDDL v1.1

- GPL v2

- grizzly-framework-2.2.1.jar

- grizzly-http-2.2.1.jar

- grizzly-http-server-2.2.1.jar

Jackson 1.9.2

JSONシリアライザ

Apache 2.0

- jackson-core-asl-1.9.2.jar

- jackson-jaxrs-1.9.2.jar

- jackson-mapper-asl-1.9.2.jar

- jackson-xc-1.9.2.jar

23.3 Coherence RESTの構成の概要

Coherence RESTは、2つの構成ファイルを使用して構成されます。該当するファイルは次のとおりです。

注意:

Coherence RESTをJavaEEサーバーにデプロイする場合、web.xmlファイルの構成も必要です。詳細は、「Java EEサーバー(一般)へのデプロイ」を参照してください。

- キャッシュ構成デプロイメント・ディスクリプタ: このファイルは、クライアント側のキャッシュ・サービスおよびHTTPアクセプタを定義するために使用します。HTTPアクセプタはHTTPを介してリモートRESTからの接続を受け入れます。アクセプタには、クライアントが接続するクラスタ側のHTTPサーバーのアドレスおよびポートが含まれます。このファイルのスキーマは、coherence-cache-config.xsdファイルです。<http-acceptor要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。
実行時には、クラスパスで最初に検出されたキャッシュ構成ファイルが使用されます。tangosol.coherence.cacheconfigシステム・プロパティを使用して、キャッシュ構成ファイルを明示的に指定することもできます。このファイルは、プログラムによっても設定できます。キャッシュ構成デプロイメント・ディスクリプタの一般的な情報は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

- REST構成デプロイメント・ディスクリプタ - このファイルは、Jerseyリソース構成クラスおよびカスタム・アグリゲータおよびカスタム・エントリ・プロセッサを構成するために使用されます。ディスクリプタのデフォルト名はcoherence-rest-config.xmlで、スキーマはcoherence-rest-config.xsdファイルで定義されます。ファイルはクラスパス上に存在する必要があります。その名前はtangosol.coherence.rest.configシステム・プロパティを使用して上書きできます。REST構成デプロイメント・ディスクリプタの詳細なリファレンスは、付録A「RESTの構成要素」を参照してください。

23.4 データ・フォーマットのサポートの理解

Coherence RESTは、入力および出力としてXMLおよびJSONフォーマットをサポートします。これらのフォーマットを使用するには、ユーザー・タイプを作成するときに正しいバインディングが必要になります。この項では、この両方のフォーマットについて説明します。

この項には、次のトピックが含まれます:

- データ・フォーマットとしてのXMLの使用方法

- データ・フォーマットとしてのJSONの使用方法

23.4.1 データ・フォーマットとしてのXMLの使用方法

XMLで参照されるオブジェクトは、キャッシュに保存されるために適切なJAXBバインディングを定義する必要があります。次の例では、JAXBバインディングを追加する注釈を使用するオブジェクトを作成します。

@XmlRootElement(name="Address")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Address {
private String street;
private String city;
private String country;

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}
}

@XmlRootElement(name="Person")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Person {
private Long id;
private String name;
private Address address;
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@XmlElement(name = "address")
public AddressXml getAddr() {
return address;
}

public void setAddr(AddressXml addr) {
this.addr = addr;
}
}

23.4.2 データ・フォーマットとしてのJSONの使用方法

JSONで参照されるオブジェクトは、キャッシュに保存されるために適切なJacksonバインディングまたはJAXBバインディングを定義する必要があります。デフォルトのCoherence REST JSONマーシャリング処理ではJacksonバインディングが優先されます。Jacksonバインディングが検出されない場合、JAXBバインディングがかわりに使用されます。Jackson注釈を使用することで、出力JSONフォーマットの制御性が向上します。ただし、XMLおよびJSONフォーマットの両方が必要な場合、JAXB注釈は両方のフォーマットに対して十分に使用できます。

次の例では、注釈を使用するオブジェクトを作成して、Jacksonバインディングを追加しています。

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include= JsonTypeInfo.As.PROPERTY,
property="@type")
public class Address {
private String street;
private String city;
private String country;

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}
}

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include= JsonTypeInfo.As.PROPERTY,
property="@type")
public class Person {
private Long id;
private String name;
private Address address;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@JsonProperty("address")
public AddressJson getAddr() {
return address;
}

public void setAddr(AddressJson addr) {
this.addr = addr;
}
}

23.5 Coherence RESTクライアントの認証と認可

Coherence RESTは、クラスタリソースへのアクセスを制限する認証と認可の両方を提供します。認証サポートは、HTTP基本認証およびSSL認証の両方に対応します。認可はCoherence*Extend方式の認可を使用して実装されます。この認証は、名前付けクラスと起動サービスの操作への詳細なアクセスを提供するインターセプタ・クラスに依存しています。Coherence RESTのセキュリティの詳細手順は、『Oracle Coherenceの保護』を参照してください。

24 最初のCoherence RESTアプリケーションの作成

この章では、Coherence RESTアプリケーションを構築および実行するために必要な、基本的なタスクについて説明します。この章で説明されている多くの概念は、後の章で詳細に説明します。

この章には次の項が含まれます:

- Coherence RESTの例の概要

- ステップ1: クラスタ側の構成

- ステップ2: ユーザー・タイプの作成

- ステップ3: RESTサービスの構成

- ステップ4: キャッシュ・サーバー・プロセスの開始

- ステップ5: クライアントからRESTサービスへのアクセス

24.1 Coherence RESTの例の概要

この章では、一連の手順を使用して、基本的なCoherence RESTアプリケーションを構成および実行します。各手順では、HTTPリクエストの処理、リモート・キャッシュの構成、Coherence REST APIの使用を管理するプロキシ・サーバーの構成など、基本的な概念について説明します。この章の例では、アプリケーション・サーバーが不要なスタンドアロンのアプリケーションをデプロイするために、埋込みHTTPサーバーを使用します。WebLogicやGlassFishなどのアプリケーション・サーバーに関するデプロイメント・オプションの詳細は、第26章「Coherence RESTのデプロイ」を参照してください。

この章の手順を完了するには、Coherence for Javaをインストールする必要があります。またこの例では、次のユーザー定義の変数を使用します。

- DEV_ROOT - リストされているすべての手順を実行する場所となるルート・フォルダのパス。つまり、その後のすべてのフォルダはDEV_ROOTに対する相対フォルダになります。

- COHERENCE_HOME - Coherence JARを含むフォルダのパス (coherence.jarおよびcoherence-rest.jar)

24.2 ステップ1: クラスタ側の構成

Coherence RESTには、キャッシュおよびプロキシ・スキームの両方が必要です。プロキシ・スキームでは、受信するHTTPリクエストを処理するHTTPアクセプタを定義する必要があります。キャッシュおよびプロキシは、クラスタ側のキャッシュ構成デプロイメント・ディスクリプタ内に構成されます。この例では、プロキシはlocalhostおよびポート8080上でクライアントHTTPリクエストを受け入れるように構成されます。dist-http-exampleという名前の分散キャッシュを定義し、これを使用してクライアント・データをクラスタに格納します。

クラスタ側を構成する手順は、次のとおりです。

1. example-server-config.xmlという名前のXMLファイルをDEV_ROOT\configフォルダに作成します。

2. このファイルに次のXMLをコピーします。

<?xml version="1.0"?>
<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
coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>dist-http-example</cache-name>
<scheme-name>dist-http</scheme-name>
</cache-mapping>
</caching-scheme-mapping>

<caching-schemes>
<distributed-scheme>
<scheme-name>dist-http</scheme-name>
<backing-map-scheme>
<local-scheme/>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>

<proxy-scheme>
<service-name>ExtendHttpProxyService</service-name>
<acceptor-config>
<http-acceptor>
<local-address>
<address>localhost</address>
<port>8080</port>
</local-address>
</http-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>
</caching-schemes>
</cache-config>

3. ファイルを保存して閉じます。

24.3 ステップ2: ユーザー・タイプの作成

Personユーザー・タイプを作成します。これはキャッシュに保存され、基本的なREST操作を説明するために使用します。

Personオブジェクトを作成するには:

1. DEV_ROOT\exampleフォルダにテキスト・ファイルを作成します。

2. このファイルに次のJavaコードをコピーします。

package example;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="person")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Person implements Serializable {

public Person() {}

public Person(String name, int age)
{
m_name = name;
m_age  = age;
}

public String getName() { return m_name; }

public void setName(String name) { m_name = name; }

public int getAge() { return m_age; }

public void setAge(int age) {  m_age = age; }

protected String m_name;
protected int    m_age;
}

3. Person.javaという名前でファイルを保存して閉じます。

4. Person.javaをコンパイルします。

javac example\Person.java

24.4 ステップ3: RESTサービスの構成

Coherence RESTサービスには、公開されるキャッシュに関するメタデータが必要です。メタデータには、キャッシュ・エントリのキーと値のタイプ、およびキー・コンバータおよび値マーシャリング処理が含まれます。キーおよび値のタイプは、Coherenceが組込みのコンバータおよびマーシャリング処理を使用できるようにするために必要です(XMLとJSONがサポートされます)。

RESTサービスを構成するには:

1. coherence-rest-config.xmlという名前のXMLファイルをDEV_ROOT\configフォルダに作成します。

2. このファイルに次のXMLをコピーします。

<?xml version="1.0"?>
<rest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-rest-config"
xsi:schemaLocation=
"http://xmlns.oracle.com/coherence/coherence-rest-config
coherence-rest-config.xsd">
<resources>
<resource>
<cache-name>dist-http-example</cache-name>
<key-class>java.lang.String</key-class>
<value-class>example.Person</value-class>
</resource>
</resources>
</rest>

3. ファイルを保存し、閉じます。

24.5 ステップ4: キャッシュ・サーバー・プロセスの開始

RESTサービスは、キャッシュ・サービス・プロセス(DefaultCacheServer)の一環として公開されます。キャッシュ・サーバーのクラスパスは、前述の手順で作成したすべての構成ファイルおよびPerson.classを検索できるように構成する必要があります。クラスパスには、必要な依存性ライブラリも含める必要があります(「Coherence RESTの依存性」を参照)。簡潔にするために、前述のすべてのファイルはDEV_ROOT\libsフォルダに配置します。

DEV_ROOTフォルダは、次のような構成になります。

\
\config
\config\example-server-config.xml
\config\coherence-rest-config.xml
\example
\example\Person.class
\libs
\libs\jersey-server-1.17.1.jar
\libs\jersey-servlet-1.17.1.jar
\libs\jersey-core-1.17.1.jar
\libs\jersey-json-1.17.1.jar
\libs\jersey-multipart-1.17.1.jar
\libs\jersey-grizzly2-1.12.jar
\libs\jackson-core-asl-1.9.2.jar
\libs\jackson-jaxrs-1.9.2.jar
\libs\jackson-mapper-asl-1.9.2.jar
\libs\jackson-xc-1.9.2.jar

次のコマンドラインでは、キャッシュ・サーバー・プロセスが開始され、tangosol.coherence.cacheconfigシステム・プロパティを使用して、ステップ1で作成したキャッシュ構成ファイルに明示的に名前が付けられます。また、必要なライブラリおよび構成ファイルをすべてクラスパス変数に設定します。

java -cp DEV_ROOT\config;DEV_ROOT;DEV_ROOT\libs\jersey-server-1.17.1.jar;
DEV_ROOT\libs\jersey-servlet-1.17.1.jar;DEV_ROOT\libs\jersey-core-1.17.1.jar;
DEV_ROOT\libs\jersey-json-1.17.1.jar;DEV_ROOT\libs\jersey-multipart-1.17.1.jar;
DEV_ROOT\libs\jersey-grizzly2-1.12.jar;DEV_ROOT\libs\jackson-core-asl-1.9.2.jar;
DEV_ROOT\libs\jackson-jaxrs-1.9.2.jar;DEV_ROOT\libs\jackson-mapper-asl-1.9.2.jar;
DEV_ROOT\libs\jackson-xc-1.9.2.jar;COHERENCE_HOME\coherence.jar;
COHERENCE_HOME\coherence-rest.jar -Dtangosol.coherence.clusterport=8080
-Dtangosol.coherence.ttl=0
-Dtangosol.coherence.cacheconfig=DEV_ROOT\config\example-server-config.xml
com.tangosol.net.DefaultCacheServer

UNIXベース・システム用のスクリプトの例は次のとおりです

#!/bin/bash

export CLASSPATH=${DEV_ROOT}/config:${DEV_ROOT}:
${DEVROOT}/lib/jackson-core-asl-1.9.2.jar:${DEVROOT}/lib/jackson-jaxrs-1.9.2.jar:
${DEVROOT}/lib/jackson-mapper-asl-1.9.2.jar:${DEVROOT}/lib/jackson-xc-1.9.2.jar:
${DEV_ROOT}/lib/jersey-core-1.17.1.jar:${DEV_ROOT}/lib/jersey-json-1.17.1.jar:
${DEV_ROOT}/lib/jersey-multipart-1.17.1.jar:${DEV_ROOT}/lib/jersey-server-1.17.1.jar:
${DEV_ROOT}/lib/jersey-servlet-1.17.1.jar:${DEV_ROOT}/lib/jersey-grizzly2-1.12.jar:
${COHERENCE_HOME}/lib/coherence.jar:${COHERENCE_HOME}/lib/coherence-rest.jar

java -cp ${CLASSPATH} -Dtangosol.coherence.clusterport=8080
-Dtangosol.coherence.ttl=0 -Dtangosol.coherence.cacheconfig=
${DEV_ROOT}/config/example-server-config.xml com.tangosol.net.DefaultCacheServer

コンソール出力をチェックして、プロキシ・サービスが開始されていることを確認します。出力メッセージは次のようになります。

(thread=Proxy:ExtendHttpProxyService:HttpAcceptor, member=1): Started: HttpAcceptor{Name=Proxy:ExtendHttpProxyService:HttpAcceptor, State=(SERVICE_STARTED), HttpServer=com.tangosol.coherence.rest.server.DefaultHttpServer, LocalAddress=localhost, LocalPort=8080, ResourceConfig=com.tangosol.coherence.rest.server.DefaultResourceConfig, RootResource=com.tangosol.coherence.rest.DefaultRootResource}

24.6 ステップ5: クライアントからRESTサービスへのアクセス

クライアント・アプリケーションでは、キャッシュの操作を行うためにCoherence RESTサービスを使用します。HTTPベース・クライアントを構築するためのクライアント・ライブラリを提供するアプリケーション・プラットフォームは数多くあります。たとえば、Jersey Projectでは、HTTPベースのREST Webサービスによるクライアント側通信にJavaがサポートされます。クライアントでdist-http-exampleキャッシュにアクセスするために使用するPUT、GETおよびPost操作のセマンティクスを次に示します。Jerseyを使用して構築されたJavaクライアントの例は、Jersey-client-1.17.1.jarライブラリに従っており、このライブラリが必要です。Coherence REST APIの詳細は、第25章「RESTを使用したグリッド操作の実行」を参照してください。

Put操作

PUT http://localhost:8080/dist-http-example/1
Content-Type=application/json
Request Body: {"name":"chris","age":30}

PUT http://localhost:8080/dist-http-example/2
Content-Type=application/json
Request Body: {"name":"adam","age":26}

GET操作

GET http://localhost:8080/dist-http-example/1.json

GET http://localhost:8080/dist-http-example/1.xml

GET http://localhost:8080/dist-http-example?q=name is 'adam'

GET http://localhost:8080/dist-http-example;p=name

GET http://localhost:8080/dist-http-example/count()

GET http://localhost:8080/dist-http-example/double-average(age)

Post操作

POST http://localhost:8080/dist-http-example/increment(age,1)

サンプルJersey RESTクライアント

package example;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import javax.ws.rs.core.MediaType;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

public class RestExample {
public static void PUT(String url, MediaType mediaType,String data) {
process(url,"put",mediaType,data);
}
public static void GET(String url, MediaType mediaType) {
process(url,"get",mediaType,null);
}
public static void POST(String url, MediaType mediaType,String data) {
process(url,"post",mediaType,data);
}
public static void DELETE(String url, MediaType mediaType) {
process(url,"delete",mediaType,null);
}

public static void process(String sUrl, String action, MediaType mediaType,
String data) {
Client client = Client.create();
ClientResponse response = null;
WebResource webResource = client.resource(sUrl);      if (action.equalsIgnoreCase("get")) {
response = webResource.type(mediaType).get(ClientResponse.class);
} else if (action.equalsIgnoreCase("post")) {
response = webResource.type(mediaType).post(ClientResponse.class, data);
} else if (action.equalsIgnoreCase("put")) {
response = webResource.type(mediaType).put(ClientResponse.class, data);
} else if (action.equalsIgnoreCase("delete")) {
response = webResource.type(mediaType).delete(ClientResponse.class,data);
}
int status = response.getStatus();
System.out.println("status:" + status + "Result: "
+ response.getEntity(String.class));
}

public static void main(String[] args) throws URISyntaxException,
MalformedURLException, IOException {
PUT("http://localhost:8080/dist-http-example/1",
MediaType.APPLICATION_JSON_TYPE,"{\"name\":\"chris\",\"age\":32}");
PUT("http://localhost:8080/dist-http-example/2",
MediaType.APPLICATION_JSON_TYPE,
"{\"name\":\"\ufeff\u30b8\u30e7\u30f3A\",\"age\":66}");
PUT("http://localhost:8080/dist-http-example/3",
MediaType.APPLICATION_JSON_TYPE,"{\"name\":\"adm\",\"age\":88}");
POST("http://localhost:8080/dist-http-example/increment(age,1)",
MediaType.APPLICATION_JSON_TYPE,null);
GET("http://localhost:8080/dist-http-example/3",
MediaType.APPLICATION_JSON_TYPE);
GET("http://localhost:8080/dist-http-example/count()",
MediaType.APPLICATION_XML_TYPE);
}
}

25 RESTによるグリッド操作の実行

この章では、Coherence REST APIを使用したグリッド操作の実行手順を示します。Coherence REST APIでは、キャッシュとの相互作用に使用できる多数の操作を事前定義しています。さらに、必要に応じてアグリゲータやエントリ・プロセッサなどのカスタム操作を作成できます。

この章には次の項が含まれます:

- キーおよび値のタイプの指定

- 単一オブジェクトのREST操作の実行

- 複数オブジェクトのREST操作の実行

- 部分オブジェクトのREST操作の実行

- RESTによる問合せの実行

- RESTによる集計の実行

- RESTによるエントリ処理の実行

- 並列処理制御の理解

- キャッシュの別名の指定

25.1キーおよび値のタイプの指定

Coherence RESTサービスでは、公開されるキャッシュに関するメタデータが必要です。メタデータには、キャッシュ・エントリのキーと値のタイプ、およびキー・コンバータおよび値マーシャリング処理が含まれます。キーおよび値のタイプは、Coherenceが組込みのコンバータおよびマーシャリング処理を使用できるようにするために必要です(XMLとJSONがサポートされます)。

coherence-rest-config.xmlファイルを編集して、<key-class>および<value-class>要素を<resource>要素の中に含め、それぞれにキーと値のタイプを設定します。<resource>要素の詳細なリファレンスは、「resource」を参照してください。

次の例では、Stringキー・クラスおよびPersonユーザー・タイプの値クラスを定義します。

<resources>
<resource>
<cache-name>person</cache-name>
<key-class>java.lang.String</key-class>
<value-class>example.Person</value-class>
</resource>
</resources>

25.2 単一オブジェクトのREST操作の実行

REST APIには、キャッシュ内の単一オブジェクト上での、GET、PUTおよびDELETE操作の実行のサポートが含まれます。

GET操作

GET http://host:port/cacheName/key

キーに基づいて、キャッシュから単一オブジェクトを返します。指定されたキーのオブジェクトが存在しない場合、404 (Not Found)のステータス・コードが返されます。get操作は、部分的な結果をサポートします(詳細は、「部分オブジェクトのREST操作」を参照してください)。オブジェクトにcom.tangosol.util.Versionsableインタフェースが実装されている場合、条件付きのGET操作がサポートされます。応答にバージョンが付加され、クライアントのオブジェクトが最新バージョンかどうか判定するために使用されます。クライアントにオブジェクトの最新バージョンがすでにある場合は、304 (Not Modified)のステータス・コードが返されます。

次のサンプル出力は、GET操作の応答を示しています。

* Client out-bound request
> GET http://127.0.0.1:8080/dist-http-example/1
> Accept: application/xml

* Client in-bound response
< 200
< Content-Length: 212
< Content-Type: application/xml
<
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Person><id>1</id><name>
Mark</name><address><street>500 Oracle Parkway</street><city>Redwood Shores</city>
<country>United States</country></address></Person>

* Client out-bound request
> GET http://127.0.0.1:8080/dist-http-example/1
> Accept: application/json

* Client in-bound response
< 200
< Content-Type: application/json
<
{"@type":"rest.Person","address":{"@type":"rest.Address","city":"Redwood Shores",
"country":"United States","street":"500 Oracle Parkway"},"id":1,"name":"Mark"}

PUT操作

PUT http://host:port/cacheName/key

キャッシュで単一オブジェクトを作成または更新します。オブジェクトが更新された場合は、200 (OK)のステータス・コードが返されます。オプティミスティック同時実行性チェックが失敗すると、409 (Conflict)のステータス・コードと、エンティティとして現在のオブジェクトが返されます。詳細は、「並列処理制御の理解」を参照してください。

次のサンプル出力は、PUT操作の応答を示しています。

* Client out-bound request
> PUT http://127.0.0.1:8080/dist-test-sepx/1
> Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Person><id>1</id><name>
Mark</name><address><street>500 Oracle Parkway</street><city>Redwood Shores</city>
<country>United States</country></address></Person>

* Client in-bound response
< 200
< Content-Length: 0
<

* Client out-bound request
> PUT http://127.0.0.1:8080/dist-test-sepj/1
> Content-Type: application/json
{"@type":"rest.Person","id":1,"name":"Mark","address":{"@type":"rest.Address","str
eet":"500 Oracle Parkway","city":"Redwood Shores","country":"United States"}}

* Client in-bound response
< 200
< Content-Length: 0
<

削除操作

DELETE http://host:port/cacheName/key

キーに基づいて、キャッシュから単一オブジェクトを削除します。オブジェクトが正常に削除された場合は200 (OK)のステータス・コードが返され、指定されたキーのオブジェクトが存在しない場合は、404 (Not Found)のステータス・コードが返されます。

25.3 複数オブジェクトのREST操作の実行

複数オブジェクトの操作により、ユーザーは単一のネットワーク・リクエストで複数のオブジェクトを取得または削除できるため、ネットワークの使用量を著しく削減でき、ネットワークのパフォーマンスが向上します。

注意:

PUT操作は、大量の破損データが生成される場合があるので、サポートされていません。特には、エンティティ・ボディ内の(シリアライズされた形式の)個々のオブジェクトを、対応するキーと同じ順序でURLに配置されることが求められます。また、更新により置換を行うため、オブジェクト全体のシリアライズされた形式を提供する必要があり、さらにオーバーヘッドが発生する場合があります。

GET操作

GET http://host:port/cacheName/(key1, key2, ...)

指定されたキーに基づいて、キャッシュからオブジェクトのセットを返します。返されるオブジェクトの順序は定義されず、URLのキー順序と一致する必要もありません。欠落したオブジェクトは、警告なしで結果から省略されます。200 (OK)のステータス・コードが常に返されます。結果セットにオブジェクトがないと、空の結果セットが返されます。get操作は、部分的な結果をサポートします(詳細は、「部分オブジェクトのREST操作」を参照してください)。

DELETE操作

DELETE http://host:port/cacheName/(key1, key2, ...)

指定されたキーに基づいて、キャッシュから複数のオブジェクトを削除します。指定されたオブジェクトがキャッシュに存在しなくても、常に200 (OK)のステータス・コードが返されます。

25.4 部分オブジェクトのREST操作の実行

アプリケーションでオブジェクト全体を取得したくない(または取得する必要がない)場合があります。たとえば、アプリケーションでドロップダウンにオプションのリストを入力するために、場合によっては多数のプロパティを持つ巨大なオブジェクトから2つのプロパティしか必要ない場合があります。このような使用ケースをサポートするために、それぞれの読取り処理で、ユーザーが必要なオブジェクト・プロパティのリストをマトリックス・パラメータpとして受け取ります。

次の例では、個人のidおよびname属性のみを取得するget操作を実行します。

GET http://localhost:8080/people/123;p=id,name

住所のcountry属性も含める場合、リクエストURLは次のようになります。

GET http://localhost:8080/people/123;p=id,name,address:(country)

この方法では、URLに対応した単純な表記を使用して、アプリケーションで必要なプロパティのみを選択的に取得できます。

次のサンプル出力は、GET操作の応答を示しています。

* Client out-bound request
> GET http://127.0.0.1:8080/dist-test-sepj/1;p=name
> Accept: application/json

* Client in-bound response
< 200
< Transfer-Encoding: chunked
< Content-Type: application/json
<
{"name":"Mark"}

25.5 RESTによる問合せの実行

Coherence RESTによって、ユーザーはキャッシュへの問合せが可能です。CohQLがデフォルトの問合せ構文です。また、必要時に追加の問合せ構文を作成および使用できます。

この項の内容は、次のとおりです。

- 直接問合せの使用

- 名前付き問合せの使用

- 問合せのソート順の指定

- 問合せのサイズの制限

- キーのみの取出し

- カスタム問合せエンジンの使用

25.5.1 直接問合せの使用

直接問合せは、REST URLでパラメータqの値として送信できる問合せ式です。デフォルトで、問合せ式はURLエンコードのCohQL式として指定する必要があります(CohQLの述語句)。CohQL構文の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。直接問合せの構文は次のとおりです。

GET http://host:port/cacheName?q=query

たとえば、ageが18未満のPersonオブジェクトのpersonキャッシュを問い合せるとします。

GET http://host:port/person?q=age%3C18

デフォルトで直接問合せは無効です。直接問合せを有効にするには、coherence-rest-config.xmlファイルを編集し、問合せ先のリソースごとに<direct-query>要素を追加して、enabled属性をtrueに設定します。例:

<resource>
<cache-name>persons</cache-name>
<key-class>java.lang.Integer</key-class>
<value-class>example.Person</value-class>
<direct-query enabled="true"/>
</resource>

問合せが、直接問合せに対応していないリソースで実行された場合、403 (Forbidden)の応答コードが返されます。

25.5.2 名前付き問合せの使用

名前付き問合せは、coherence-rest-config.xmlファイル内のリソースに対して構成する問合せ式です。デフォルトで、問合せ式はCohQL式として指定する必要があります(CohQLの述語句)。式をXMLファイル内で構成するため、特殊記号(<およびなど)を対応するエンティティでエスケープする必要があります。CohQL構文の詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。さらに、名前付き問合せには必要に応じてコンテキスト値を含めることができます。名前付き問合せの構文は次のとおりです。

GET http://host:port/cacheName/namedQuery?param1=value1,param2=value2...

名前付き問合せを指定するには、任意の数の<query>要素を<resource>要素内に追加します。それぞれの要素には、問合せ式と名前バインディングがあります。<query>要素の詳細は、queryを参照してください。例:

<resource>
<cache-name>persons</cache-name>
<key-class>java.lang.Integer</key-class>
<value-class>example.Person</value-class>
<query>
<name>minors</name>
<expression>age &lt; 18</expression>
</query>
<query>
<name>first-name</name>
<expression>name is :name</expression>
</query>
</resource>

名前付き問合せを使用するには、REST URL内に問合せの名前を入力します。この例では、前述の例で定義されたminors名前付き問合せを使用しています。

GET http://host:port/persons/minors

パラメータには、コンテキスト値を問合せ式で置換えることができる柔軟性があります。次の例は、前述のfirst-name問合せ式で定義された:nameパラメータを使用して、nameプロパティがMarkのエントリのみを問い合せます。

http://host:port/persons/first-name?name=Mark

パラメータ名の前にはコロン記号を付ける必要があります(:paramName)。パラメータ・バインディングは型情報にアクセスできないため、比較演算子でTrueが予期される状況でFalseになる可能性があります。この動作を回避するために、問合せパラメータで型のヒントを指定します(:paramName;int)。表25-1は、サポートされる型のヒントを示しています。

表25-1 パラメータ型のヒント

ヒント

タイプ

i、int

java.lang.Integer

s、short

java.lang.Short

l、long

java.lang.Long

f、float

java.lang.Float

d、double

java.lang.Double

I

java.math.BigInteger

D

java.math.BigDecimal

date

java.util.Date

uuid

com.tagosol.util.UUID

uid

com.tangosol.util.UID

package.MyClass

package.MyClass

名前付き問合せは、集計およびエントリ処理とともに使用することもできます。集計およびエントリ処理の詳細は、「RESTによる集計の実行」および「RESTによるエントリ処理の実行」をそれぞれ参照してください。例:

http://host:port/persons/first-name?name=Mark/long-max(age)

http://host:port/persons/first-name?name=Mark/increment(age,1)

25.5.3 問合せのソート順の指定

sortマトリックス・パラメータは、REST URL内で使用されるオプションのパラメータです。これにより問合せから返された結果の順序を指定できます。sortパラメータは、直接問合せと名前付け問合せの両方で使用できます。sortパラメータの値は、ソートするプロパティのカンマ区切りリストを表し、それぞれにソート順を決定するオプションの:asc(デフォルト)または:desc修飾子を指定できます。たとえば、個人データのリストを名前の性でソートし、家族のメンバーは年齢の大きい順にソートする場合、sortパラメータは次のように定義します。

GET http://host:port/persons/minors;sort=lastName,age:desc

次の例は、直接問合せ内でsortパラメータを使用します。

GET http://host:port/persons;sort=lastName,age:desc?q=age%3C18

25.5.4 問合せのサイズの制限

大きなキャッシュに対して制限が解除された問合せ、または実行される問合せは、クライアントの利用可能メモリーを消費する大きな結果セットを返す可能性があります。問合せのサイズを制限する方法は、startおよびcountマトリックス・パラメータを使用するか、max-results属性を使用する方法の2つがあります。両方の方法が直接および名前付け問合せでサポートされます。

startおよびcountパラメータは、返す結果のサブセットを決定するオプションの整数の引数です。次の例は、名前付け問合せでパラメータを使用し、名前によってソートされた最初の10のエントリを返します。

http://host:port/persons/minors;start=0;count=10;order=name:asc

次の例は、直接問合せ内でパラメータを使用しています。

GET http://host:port/persons;start=0;count=10?q=age%3C18

max-results属性はcoherence-rest-config.xmlファイル内で使用され、クライアントによるリクエストの数に関係なく、問合せまたはリソースを結果の最大数で明示的に制限します。例:

<resource max-results="50">
<cache-name>persons</cache-name>
<key-class>java.lang.Integer</key-class>
<value-class>example.Person</value-class>
<direct-query enabled="true" max-results="25">
<query max-results="25">
<name>minors</name>
<expression>age &lt; 18</expression>
</query>
</resource>

両方が指定された場合、直接または名前付け問合せに対するmax-results値は、リソースのmax-results値を無視します。問合せがcountパラメータを含んでおり、max-results要素も指定されている場合、低い値の方が使用されます。

25.5.5 キーのみの取出し

キャッシュに格納されたエントリのキーのみを検索することは可能です。キーの操作ではページングとソートはサポートされません。したがって、それらの問合せパラメータが送信された場合、無視されます。次のキーの取出し操作がサポートされています。

GET http://host:port/cacheName/keys

キャッシュ中のすべてのエントリのキーを返します。

GET http://host:port/cacheName/keys?q=query

直接問合せの基準を満たす、すべてのエントリのキーを返します。

GET http://host:port/cacheName/namedQuery/keys

名前付け問合せの基準を満たす、すべてのエントリのキーを返します。

25.5.6 カスタム問合せエンジンの使用

問合せエンジンは、直接と名前付け問合せの両方に対して問合せを実行します。デフォルト問合せエンジンは、CohQL構文(CohQLの述語部分)を使用して表現された問合せを実行します。カスタム問合せエンジンの実装によって、異なる問合せ表現構文を使用することや、Coherence以外のデータ・ソースに問合せを実行できます(たとえば、キャッシュ内にないエントリについてデータベースに問合せを実行するなど)。

この項の内容は次のとおりです。

- カスタム問合せエンジンの実装

- カスタム問合せエンジンの有効化

25.5.6.1 カスタム問合せエンジンの実装

カスタム問合せエンジンには、com.tangosol.coherence.rest.query.QueryEngineとcom.tangosol.coherence.rest.query.Queryインタフェースを実装する必要があります。カスタム実装は、com.tangosol.coherence.rest.query.AbstractQueryEngineベース・クラスも拡張します。これにより、問合せ式の分析やパラメータ・バインドの処理を実行する有用なメソッドが提供されます。ベース・クラスでは、実行時のパラメータ置換と、問合せパラメータ値の一部として送信される型のヒントもサポートされます。パラメータ名および型のヒントはCohQL使用に従い、他の問合せエンジンの実装に使用できます。パラメータおよび型ヒントの指定の詳細は、「名前付き問合せの使用」を参照してください。

APIの詳細は、Oracle Coherence Java APIリファレンスのAbstractQueryEngine.ParsedQueryクラスおよびAbstractQueryEngine.parseQueryString(String)およびAbstractQueryEngine.createBindings(Map, Map)を参照してください。

次の例は、データベースに対してSQL問合せを直接実行し、キャッシュ・リードスルーを強制する簡単問合せエンジンの実装です。実際には、問合せエンジンの実装でランタイム・パラメータ・バインディングがサポートされる場合が多いでますが、この例にはありません。

public class SqlQueryEngine
extends AbstractQueryEngine
{
protected Connection m_con;
private static final String DB_DRIVER = "oracle.jdbc.OracleDriver";
private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:orcl";
private static final String DB_USERNAME = "username";
private static final String DB_PASSWORD = "password";

public SqlQueryEngine()
{
configureConnection();
}

@Override
public Query prepareQuery(String sQuery, Map<String, Object> mapParams)
{
ParsedQuery parsedQuery = parseQueryString(sQuery);
String  sSQL            = createSelectPKQuery(parsedQuery.getQuery());
return new SqlQuery(sSQL);
}

protected void configureConnection()
{
try
{
Class.forName(DB_DRIVER);
m_con = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
m_con.setAutoCommit(true);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}

protected String createSelectPKQuery(String sSQL)
{
return "SELECT id,name,age FROM " +
sSQL.substring(sSQL.toUpperCase().indexOf("FROM") + 4);
}

private class SqlQuery
implements Query
{
protected String m_sql;

public SqlQuery(String sql)
{
m_sql = sql;
}

@Override
public Collection values(NamedCache cache, String sOrder, int nStart,
int cResults)
{
// force read through
Set setKeys = keySet(cache);
return cache.getAll(setKeys).values();
}

@Override
public Set keySet(NamedCache cache)
{
Set setKeys = new HashSet();
try
{
PreparedStatement stmt   = m_con.prepareStatement(m_sql);
ResultSet         result = stmt.executeQuery();
while (result.next())
{
Object oKey = result.getLong(1);
setKeys.add(oKey);
Person person = new Person(result.getString("name"),
result.getInt("age"));
cache.put(oKey, person);
}
stmt.close();
}
catch (SQLException e)
{
throw new RuntimeException(e);
}
return setKeys;
}
}
}

25.5.6.2 カスタム問合せエンジンの有効化

カスタム問合せエンジンはcoherence-rest-config.xmlファイルで有効化します。カスタム問合せエンジンを有効にするには、最初に<query-engines>要素内に<engine>を追加して実装を登録します。この要素には、問合せエンジンの名前と、実装クラスの完全修飾名が含まれています。<engine>要素の詳細は、engineを参照してください。例:

<query-engines>
<engine>
<name>SQL-ENGINE</name>
<class-name>package.SqlQueryEngine</class-name>
</engine>
</query-engines>

名前付け問合せまたは直接問合せのためのカスタム問合せエンジンを明示的に指定するには、<direct-query>要素または<query>要素内に、カスタム問合せエンジンの登録名を参照するengine属性を追加します。例:

<resource>
<cache-name>persons</cache-name>
<key-class>java.lang.Integer</key-class>
<value-class>example.Person</value-class>
<query engine="SQL-ENGINE">
<name>less-than-1000</name>
<expression>select * from PERSONS where id &lt; 1000</expression>
</query>
<direct-query enabled="true" engine="SQL-ENGINE"/>
</resource>

カスタム問合せエンジンをデフォルトの問合せエンジンにするには、登録済の名前としてDEFAULT(大文字が必須)を使用してください。次の定義はデフォルトCohQLベースの問合せエンジンを上書きし、engine属性を指定していない場合には自動的に使用されます。

<query-engines>
<engine>
<name>DEFAULT</name>
<class-name>package.SqlQueryEngine</class-name>
</engine>
</query-engines>

25.6 RESTによる集計の実行

キャッシュ内のデータの集計を実行できます。Coherence RESTには事前定義のアグリゲータのセットが含まれ、必要に応じてカスタムのアグリゲータも作成できます。

この項には、次のトピックが含まれます:

- RESTの集計の構文

- 事前定義のアグリゲータのリスト

- カスタム・アグリゲータの作成

25.6.1 RESTの集計の構文

次の例は、RESTを使用して集計を実行する方法を示します。集計に成功すると、200 (OK)のステータス・コードがエンティティとして集約の結果とともに返されます。

- キャッシュ内のすべてのエントリを集計します。

GET http://host:port/cacheName/aggregator(args, ...)

- 問合せ結果を集計します。問合せはURLエンコードのCohQL式として指定する必要があります(CohQLの述語句)。

GET http://host:port/cacheName/aggregator(args, ...)?q=query

GET http://host:port/cacheName/namedQuery?param1=value1/aggregator(args, ...)

- 指定されたエントリを集計します。

GET http://host:port/cacheName/(key1, key2, ...)/aggregator(args, ...)

Coherence RESTは、(アグリゲータ関連のURLセグメントから)アグリゲータを作成するための簡単な戦略を提供します。出荷時の状態のCoherence RESTでは、単一のタイプcom.tangosol.util.ValueExtractor (LongMax、DoubleMaxなど)のパラメータを受け入れるコンストラクタにより、任意の登録された(組込みまたはユーザー登録の)アグリゲータを解決できます。URL内のアグリゲータのコールにパラメータが含まれない場合、com.tangosol.util.extractor.IdentityExtractorを使用してアグリゲータが作成されます。

URL内のアグリゲータ・セグメントにパラメータが含まれない場合、または単一のValueExtractorを受け入れるコンストラクタが存在しない場合、Coherence RESTはデフォルトのコンストラクタを使用してアグリゲータのインスタンス化を試行します。これは、一部の組込みのアグリゲータ(Countなど)に最適な動作です。

次の例では、キャッシュ内で最も高齢な人を取得します。

GET http://host:port/people/long-max(age)

次の例では、数字のみを含むキャッシュで最大数を計算します。

GET http://host:port/numbers/comparable-max()

次の例では、個人データのキャッシュのサイズを計算します。

GET http://host:port/people/count()

25.6.2 事前定義のアグリゲータのリスト

次の事前定義のアグリゲータがサポートされます。

アグリゲータ名

アグリゲータ

big-decimal-average

BigDecimalAverage.class

big-decimal-max

BigDecimalMax.class

big-decimal-min

BigDecimalMin.class

big-decimal-sum

BigDecimalSum.class

double-average

DoubleAverage.class

double-max

DoubleMax.class

double-min

DoubleMin.class

double-sum

DoubleSum.class

long-max

LongMax.class

long-min

LongMin.class

long-sum

LongSum.class

comparable-max

ComparableMax.class

comparable-min

ComparableMin.class

distinct-values

DistinctValues.class

Count

Count.class

25.6.3 カスタム・アグリゲータの作成

カスタム・アグリゲータ・タイプを定義するには、REST URLで使用する名前と、com.tangosol.util.InvocableMap.EntryAggregatorインタフェースまたはcom.tangosol.coherence.rest.util.aggregator.AggregatorFactoryインタフェースを実装するクラスを指定します。

(ほとんどの事前定義のアグリゲータのように)集計が単一のプロパティまたはキャッシュ値自身で実行される場合、EntryAggregator実装は単純なシナリオで使用されます。

より複雑な戦略が必要な場合、AggregatorFactoryインタフェースが使用されます。この実装で、アグリゲータ・パラメータを含むURLセグメントを解決し、それらのパラメータを使用して適切なアグリゲータを作成できる必要があります。

カスタム・アグリゲータは、coherence-rest-config.xmlファイルの<aggregators>要素で構成されます。詳細なリファレンスは、「aggregator」を参照してください。次の例では、EntryAggregatorのカスタム実装とAggregatorFactoryのカスタム実装を構成しています。

<aggregators>
<aggregator>
<name>my-simple-aggr</name>
<class-name>com.foo.MySimpleAggregator</class-name>
</aggregator>
<aggregator>
<name>my-complex-aggr</name>
<class-name>com.foo.MyAggreagatorFactory</class-name>
</aggregator>
</aggregators>

25.7 RESTによるエントリ処理の実行

キャッシュ内の1つ以上のオブジェクト上でエントリ・プロセッサを呼び出せます。Coherence RESTには事前定義のエントリ・プロセッサのセットが含まれ、必要に応じてカスタムのエントリ・プロセッサも作成できます。

この項には、次のトピックが含まれます:

- RESTのエントリ・プロセッサの構文

- 事前定義のエントリ・プロセッサのリスト

- カスタム・エントリ・プロセッサの作成

25.7.1 RESTのエントリ・プロセッサの構文

次の例は、RESTを使用してエントリ処理を実行する方法を示します。処理に成功すると、200 (OK)のステータス・コードがエンティティとして処理の結果とともに返されます。

- キャッシュ内のすべてのエントリを処理します。

POST http://host:port/cacheName/processor(args, ...)

- 問合せ結果を処理します。

POST http://host:port/cacheName/processor(args, ...)?q=query

POST http://host:port/cacheName/namedQuery?param1=value1/processor(args, ...)

- 指定されたエントリを処理します。

POST http://host:port/cacheName/(key1, key2, ...)/processor (args, ...)

アグリゲータと異なり、プロセッサ(事前定義のプロセッサも含む)には、多彩な作成パターンがあるため、Coherence RESTではプロセッサの作成について何の想定もしていません。そのかわり、それぞれのエントリ・プロセッサ実装に対して、com.tangosol.coherence.rest.util.processor.ProcessorFactoryインタフェースの実装が存在する必要があります。これにより、URLセクションからの文字列の入力を処理して、プロセッサ・インスタンスをインスタンス化できます。Coherence RESTは、出荷時にはNumberIncrementorおよびNumberMultiplierの2つのファクトリを備えています。

次の例では、キャッシュ内の各個人の年齢を5つ増加させます。

GET http://localhost:8080/people/increment(age, 5)

次の例では、数字のみを含むキャッシュ内の各数字を10倍します。

GET http://localhost:8080/numbers/multiply(10)

25.7.2 事前定義のエントリ・プロセッサのリスト

次の事前定義のプロセッサがサポートされます。

プロセッサ名

プロセッサ

increment

常に新しい(増加された)値を返すNumberIncrementorインスタンス

post-increment

常に古い(増加されない)値を返すNumberIncrementorインスタンス

multiply

常に新しい(乗算された)値を返すNumberMultiplierインスタンス

post-multiply

常に古い(乗算されない)値を返すNumberMultiplierインスタンス

25.7.3 カスタム・エントリ・プロセッサの作成

カスタム・エントリ・プロセッサを定義するには、REST URLで使用される名前とcom.tangosol.coherence.rest.util.processor.ProcessorFactoryインタフェースを実装するクラスを指定します。

カスタム・エントリ・プロセッサは、coherence-rest-config.xmlファイルの<processors>要素内で構成されます。詳細なリファレンスは、「processors」を参照してください。次の例では、ProcesorFactoryのカスタム実装を構成します。

<processors>
<processor>
<name>my-processor</name>
<class-name>com.foo.MyProcessorFactory</class-name>
</processor>
</processors>

25.8 並列処理制御の理解

Coherence RESTでは、HTTPプロトコルに明確にマップされる場合のみ、オプティミスティック同時実行性をサポートします。アプリケーションがcom.tangosol.util.Versionableを実装するオブジェクトのGETリクエストを送信する場合、現在のバージョン識別子がHTTP ETagで返されます(オブジェクトの表現と同様に、バージョン識別子がJSON/XMLのシリアライズ形式に含まれると仮定されます)。アプリケーションが同じGETリクエストをリソースに送信するとき、今回はIf-None-Matchヘッダーに同じETag値を使用する場合、Coherence RESTは、アプリケーションにはリソースの最新のバージョンがあることを示す304のステータスを返します。

同様に、アプリケーションがPUTリクエストを送信してオブジェクトを更新する際に、キャッシュ・オブジェクトでcom.tangosol.util.Versionableインタフェースを実装していると、Coherence RESTは既存オブジェクトのバージョンと新規オブジェクトのバージョンが一致する場合のみ更新を実行します。それ以外の場合は、クライアントが変更を再度適用して再試行できるように、現在のオブジェクトとともに409 Conflictステータスが返されます。

次の例は、これらの概念について説明しています。

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import javax.ws.rs.core.MediaType;
import org.codehaus.jettison.json.JSONObject;

public class ConcurrencyTests
{
public static void main(String[] asArg)
throws Exception
{
Client      client      = Client.create();
String      url         = "http://localhost:" + getPort() + "/dist-test1/2";
WebResource webResource = client.resource(url);

// perform a GET of a server-side resource that implements Versionable
ClientResponse response = webResource
.accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
assert 200 == response.getStatus(); /* OK */

// verify that the current version of the resource is 1
JSONObject json    = new JSONObject(response.getEntity(String.class));
String     version = json.getString("versionIndicator");
assert "1".equals(version);
assert new EntityTag("1").equals(response.getEntityTag());

// perform a conditional GET of the same resource and verify that we
// get a response status of 304: Not Modified
response = webResource
.accept(MediaType.APPLICATION_JSON)
.header ("If-None-Match", '"' + version + '"').get(ClientResponse.class);
assert 304 == response.getStatus(); /* Not Modified */

// simulate a version change on the server-side by rolling back the
// version indicator on our representation of the resource
json.put("versionIndicator", String.valueOf(0));

// perform a conditional PUT of the same resource and verify that we
// get a response status of 409: Conflict
response = webResource
.accept(MediaType.APPLICATION_JSON)
.put(ClientResponse.class, json);
assert 409 == response.getStatus(); /* Conflict */

// retry again with the returned value and verify that we now get a
// response status of 200: OK
json = new JSONObject(response.getEntity(String.class));
response = webResource
.accept(MediaType.APPLICATION_JSON)
.put(ClientResponse.class, json);
assert 200 == response.getStatus(); /* OK */
}
}

25.9 キャッシュの別名の指定

キャッシュの別名は、単純化されたキャッシュ名を指定するために使用されます。別名は、キャッシュ名がREST URLパス・セグメントに最適でない場合に使用されます。単純化された名前は、実際のキャッシュ名にマップされます。

キャッシュの別名を定義するには、coherence-rest-config.xmlファイルを編集して、<name>要素を<resource>要素内に含め、その値を単純化されたキャッシュ名に設定します。

次の例では、dist-extend-not-ideal-name-for-a-cache*という名前のキャッシュに、peopleという名前のキャッシュの別名を作成します。

<resources>
<resource name="people">
<cache-name>dist-extend-not-ideal-name-for-a-cache*</cache-name>
...
</resource>
</resources>

26 Coherence RESTのデプロイ

この章では、Coherence RESTを埋込みHTTPサーバー、WebLogicサーバーおよびGlassFishサーバーにデプロイする方法について説明します。一般的なサーブレット・コンテナの使用方法についても説明します。Coherence RESTの保護の詳細は、『Oracle Coherenceの保護』を参照してください。

この章には次の項が含まれます:

- 埋込みHTTPサーバーによるデプロイ

- WebLogicサーバーへのデプロイ

- Java EEサーバー(一般)へのデプロイ

26.1 埋込みHTTPサーバーによるデプロイ

Coherenceでは、REST Webサービスをホストするために使用できる2つの埋込みHTTPサーバーを提供しています。com.tangosol.coherence.rest.server.DefaultHttpServer(Oracleの軽量HTTPサーバーでバッキング)とcom.tangosol.coherence.rest.server.GrizzlyHttpServer(Grizzlyでバッキング)です。デフォルトのHTTPサーバーの変更の詳細は、「埋込みHTTPサーバーの変更」を参照してください。

HTTPサーバーは、Coherenceプロキシ・サーバー上で有効である必要があります。HTTPサーバーを有効にするには、プロキシのキャッシュ構成ファイルを編集して、<http-acceptor>要素を<proxy-scheme>要素の中に追加し、HTTPサーバーのホストおよびポートを指定します。

次の例では、ローカルホスト127.0.0.1およびポート8080でリクエストを受け入れるようにHTTPサーバーを構成します。例では、HTTPサーバー・クラスおよびJerseyリソース構成クラスを明示的に定義し、Coherence RESTアプリケーションのコンテキスト・パスとして/を使用しています。ただし、デフォルト値があるので含める必要はありません。コンテキスト・パスは必要に応じて変更でき、別のコンテキス・パスとともに追加のCoherence RESTアプリケーションを定義できます。すべての<http-acceptorサブ要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

<proxy-scheme>
<service-name>ExtendHttpProxyService</service-name>
<acceptor-config>
<http-acceptor>
<class-name>
com.tangosol.coherence.rest.server.DefaultHttpServer</class-name>
<local-address>
<address>127.0.0.1</address>
<port>8080</port>
</local-address>
<resource-config>
<context-path>/</context-path>
<instance>
<class-name>
com.tangosol.coherence.rest.server.DefaultResourceConfig
</class-name>
</instance>
</resource-config>
</http-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>

26.2 WebLogicサーバーへのデプロイ

WebLogic Serverには、WebLogicサーバー・ドメイン内にCoherenceアプリケーションをパッケージ化、デプロイおよび管理する方法を標準化するCoherence統合機能が含まれています。Coherence RESTは統合標準に準拠する必要があります。WebLogicサーバー・ドメインのクラスタの構成に関する詳細は、『Oracle WebLogic Serverクラスタの管理』を参照してください。さらに、Coherenceアプリケーションは、グリッド・アーカイブ(GAR)としてパッケージ化する必要があります。GARの作成に関する詳細は、『Oracle WebLogic ServerのためのOracle Coherenceアプリケーションの開発』を参照してください。

この項の内容は次のとおりです。

- タスク1: Coherence RESTのWebLogicサーバー・ドメインの構成

- タスク2: Coherence REST Webアプリケーションのパッケージ化

- タスク3: Coherenceアプリケーションのパッケージ化

- タスク4: エンタープライズ・アプリケーションのパッケージ化

- タスク5: エンタープライズ・アプリケーションのデプロイ

26.2.1 タスク1: Coherence RESTのWebLogicサーバー・ドメインの構成

Coherence RESTのドメインの構成:

1. Coherence RESTをホストするWebLogicサーバー・ドメインに、管理Coherenceサーバーを作成します。サーバーは、Coherenceクラスタのストレージが無効なメンバーとして構成する必要があります。Coherence RESTソリューションに複数の管理Coherenceサーバーが必要な場合、サーバーはWebLogicサーバー・クラスタの層として管理される必要があります。管理Coherenceサーバーに関する詳細は『Oracle WebLogic Serverクラスタの管理』を参照してください。

2. COHERENCE_HOME/lib/coherence-rest.jarを管理Coherenceサーバーを対象とする共有ライブラリとしてデプロイします。

注意:

coherence-rest.jarをシステムのクラスパスとして追加するか、GARファイルの/libディレクトリに含めることもできます。

3. Coherence RESTは、GlassFish参照実装からのJAXBプロバイダを要求します。WebLogicサーバーはデフォルトでEclipse MOXy JAXBプロバイダを使用します。GlassFish JAXBプロバイダを使用するようにWebLogicサーバーを構成するには、WebLogicサーバーの起動時に、次のシステム・プロパティを設定します。

-Dcom.sun.xml.ws.spi.db.BindingContextFactory=com.sun.xml.ws.db.
glassfish.JAXBRIContextFactory

-Djavax.xml.bind.JAXBContext=com.sun.xml.bind.v2.ContextFactory

WebLogic Server用のGlassFish JAXBプロバイダの構成の詳細は、『Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービス・スタート・ガイド』を参照してください。

26.2.2 タスク2: Coherence REST Webアプリケーションのパッケージ化

Coherence REST Webアプリケーションをパッケージ化するには:

1. 次のようにWebアプリケーション・ディレクトリ構造を作成します。

/
/WEB-INF/
/WEB-INF/classes/
/WEB-INF/lib/

2. 次のJARファイルをORACLE_HOME/oracle_common/modules/ディレクトリから/WEB-INF/libディレクトリにコピーします。

- jackson-core-asl-1.9.2.jar

- jackson-jaxrs-1.9.2.jar

- jackson-mapper-asl-1.9.2.jar

- jackson-xc-1.9.2.jar

- jersey-core-1.17.1.jar

- jersey-json-1.17.1.jar

- jersey-multipart-1.17.1.jar

- jersey-server-1.17.1.jar

- jersey-servlet-1.17.1.jar

3. Webアプリケーション・デプロイメント・ディスクリプタ(web.xml)を作成し、次のようにRESTアプリケーションのサーブレットの定義を含めます。

注意:

デフォルトのサーブレット・コンテキスト・リスナーは、RESTアプリケーションのシャットダウン中にクラスタ・メンバーをシャットダウンするcoherence-rest.jarに含まれています。このリスナーは次に示すように登録されています。クラスタ・メンバーがシャットダウンされない場合、シャットダウン後に様々な例外がスローされます。

<web-app>
...
<listener>
<listener-class>
com.tangosol.coherence.rest.servlet.DefaultServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>Coherence REST</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass
</param-name>
<param-value>
com.tangosol.coherence.rest.server.ContainerResourceConfig
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Coherence REST</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
...
</web-app>

4. web.xmlファイルを/WEB-INF/ディレクトリに保存します。

5. jarユーティリティを使用して、WARファイルを作成します。たとえば、Webアプリケーション・ディレクトリのルートでコマンド・プロンプトから次のコマンドを発行します。

jar -cvf coherence_rest.war *

26.2.3 タスク3: Coherenceアプリケーションのパッケージ化

Coherenceアプリケーションをパッケージ化するには:

1. coherence-rest-config.xmlファイルをCoherenceアプリケーションのルートにコピーします。構造は次のとおりにする必要があります。

/
/com/myco/MyClass.class
/lib/
/META-INF/
/META-INF/coherence-application.xml
/META-INF/coherence-cache-config.xml
/META-INF/pof-config.xml
coherence-rest-config.xml

2. pof-config.xmlファイルを編集し、Coherence RESTデフォルト・ユーザー・タイプを含むcoherence-rest-pof-config.xml POF構成ファイルをインクルードします。例:

<pof-config>
<user-type-list>
<include>coherence-pof-config.xml</include>
<include>coherence-rest-pof-config.xml</include>
...
</user-type-list>
</pof-config>

coherence-rest-pof-config.xmlファイルがcoherence-rest.jarライブラリに配置され、実行時に自動的にロードされます。

3. jarユーティリティを使用して、GARファイルを作成します。たとえば、コマンド・プロンプトからGARディレクトリのルートで次のコマンドを発行します。

jar -cvf MyCohApp.gar *

26.2.4 タスク4: エンタープライズ・アプリケーションのパッケージ化

エンタープライズ・アプリケーションをパッケージ化するには

1. エンタープライズ・アプリケーション・ディレクトリ構造を作成し、Coherence REST WARファイルおよびCoherenceアプリケーションGARファイルをEARのルートにコピーします。例:

/
/META-INF/
/META-INF/application.xml
/META-INF/weblogic-application.xml
/coherence_rest.war
/MyCohApp.gar

2. application.xmlファイルを編集し、Coherence REST Webアプリケーションのモジュール定義を追加します。例:

<application>
<module>
<web>
<web-uri>coherence_rest.war</web-uri>
<context-root>/</context-root>
</web>
</module>
</application>

3. weblogic-application.xmlファイルを編集し、coherence-rest.jar共有ライブラリのライブラリ参照およびCoherenceアプリケーションGARファイルのモジュール参照を追加します。例:

<weblogic-application>
<module>
<name>person</name>
<type>GAR</type>
<path>MyCohApp.gar</path>
</module>
<library-ref>
<library-name>coherence-rest</library-name>
</library-ref>
</weblogic-application>

4. jarユーティリティを使用して、EARファイルを作成します。たとえば、コマンド・プロンプトでEARディレクトリのルートから次のコマンドを発行します。

jar -cvf MyCohRestApp.ear *

26.2.5 タスク5: エンタープライズ・アプリケーションのデプロイ

エンタープライズ・アプリケーションをデプロイするには

1. WebLogicサーバー・管理コンソールまたはWLSTツールを使用して、タスク1で作成した管理CoherenceサーバーにEARをデプロイします、

2. ブラウザから、管理Coherenceサーバーのリスニング・ポートに移動しURLの一部にキャッシュ名を含めることにより、デプロイメントを検証します。例: http://host:port/rest/{cacheName}

26.3 Java EEサーバー(一般)へのデプロイ

この項では、Coherence RestをJava EE環境にデプロイする方法について説明します。

この項には、次のトピックが含まれます:

- デプロイメント用のCoherence RESTのパッケージ化

- GlassFishへのデプロイ

- サーブレット・コンテナへのデプロイ

26.3.1 デプロイメント用のCoherence RESTのパッケージ化

Coherence RESTアプリケーションをパッケージ化するには:

1. 次のように基本のWebアプリケーション・ディレクトリ構造を作成します。

/
/WEB-INF
/WEB-INF/classes
/WEB-INF/lib

2. 次のJARファイルをCOHERENCE_HOME/libディレクトリおよびORACLE_HOME/oracle_common/modules/ディレクトリから/WEB-INF/libディレクトリへコピーします:

- coherence.jar

- coherence-rest.jar

- jackson-core-asl-1.9.2.jar

- jackson-jaxrs-1.9.2.jar

- jackson-mapper-asl-1.9.2.jar

- jackson-xc-1.9.2.jar

- jersey-core-1.17.1.jar

- jersey-json-1.17.1.jar

- jersey-multipart-1.17.1.jar

- jersey-server-1.17.1.jar

- jersey-servlet-1.17.1.jar

3. Webアプリケーション・デプロイメント・ディスクリプタ(web.xml)を作成し、次のようにRESTアプリケーションのサーブレットの定義を含めます。

注意:

デフォルトのサーブレット・コンテキスト・リスナーは、RESTアプリケーションのシャットダウン中にクラスタ・メンバーをシャットダウンするcoherence-rest.jarに含まれています。このリスナーは次に示すように登録されています。クラスタ・メンバーがシャットダウンされない場合、シャットダウン後に様々な例外がスローされます。

<web-app>
...
<listener>
<listener-class>
com.tangosol.coherence.rest.servlet.DefaultServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>Coherence REST</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass
</param-name>
<param-value>
com.tangosol.coherence.rest.server.ContainerResourceConfig
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Coherence REST</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
...
</web-app>

4. web.xmlファイルを/WEB-INF/ディレクトリに保存します。

5. coherence-rest-config.xmlファイルを/WEB-INF/classesディレクトリにコピーします。

6. coherence-cache-config.xmlファイルおよびtangosol-coherence-override.xmlファイルをWEB-INF/classesディレクトリにコピーします。

7. jarユーティリティを使用して、Web ARchive (WAR)ファイルを作成します。たとえば、Webアプリケーション・ディレクトリのルートでコマンド・プロンプトから次のコマンドを発行します。

jar -cvf coherence_rest.war *

アーカイブには次のファイルが含まれます。

/WEB-INF/web.xml
/WEB-INF/classes/coherence-rest-config.xml
/WEB-INF/classes/tangosol-coherence-override.xml
/WEB-INF/classes/coherence-cache-config.xml
/WEB-INF/lib/coherence.jar
/WEB-INF/lib/coherence-rest.jar
/WEB-INF/lib/jersey-server-1.17.1.jar
/WEB-INF/lib/jersey-servlet-1.17.1.jar
/WEB-INF/lib/jersey-core-1.17.1.jar
/WEB-INF/lib/jersey-json-1.17.1.jar
/WEB-INF/lib/jersey-multipart-1.17.1.jar
/WEB-INF/lib/jersey-grizzly2-1.12.jar
/WEB-INF/lib/jackson-core-asl-1.9.2.jar
/WEB-INF/lib/jackson-jaxrs-1.9.2.jar
/WEB-INF/lib/jackson-mapper-asl-1.9.2.jar
/WEB-INF/lib/jackson-xc-1.9.2.jar

26.3.2 GlassFishへのデプロイ

Coherence RESTをGlassFishサーバーにデプロイするには:

1. GlassFish管理コンソール(http://localhost:4848/)から「構成」→JVM設定とクリックします。

2. 「JVMオプション」オプション・タブをクリックして、次のオプションを追加します。
-Dcom.sun.enterprise.overrideablejavaxpackages=javax.ws.rs,javax.ws.rs.core,javax.ws.rs.ext

3. 「デプロイメント用のCoherence RESTのパッケージ化」で説明されているように、Coherence RESTをWARファイルとしてパッケージ化します。また、WEB-INF/sun-web.xmlまたはWEB-INF/glassfish-web.xmlでクラス・ローダー委任をfalseに設定することで、GlassFishで配信されるJerseyのバージョンをCoherence RESTで配信されるJerseyのバージョンにオーバーライドします。例:

<sun-web-app error-url="">
<class-loader delegate="false"/>
</sun-web-app>

4. GlassFish管理コンソールを使用してWARをデプロイします。

5. ブラウザから、http://localhost:8080/coherence_rest/{cacheName}に移動して、デプロイメントを検証します。

26.3.3 サーブレット・コンテナへのデプロイ

Coherence RESTをWARファイルとしてパッケージ化することで、Coherence RESTを任意のサーブレット・コンテナにデプロイできます。詳細は、「デプロイ用のCoherence RESTのパッケージ化」を参照してください。WARファイルのデプロイの詳細は、ベンダーのドキュメントを参照してください。また、追加のサーブレット・コンテナ・デプロイメントのオプションについては、Jerseyユーザー・ガイドを参照してください。

http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e194

27 デフォルトのREST実装の変更

この章ではCoherence REST実装のデフォルト動作を変更する方法について説明します。

この章には次の項が含まれます:

- カスタム・プロバイダおよびリソースの使用方法

- 埋込みHTTPサーバーの変更

27.1 カスタム・プロバイダおよびリソースの使用方法

必要に応じて、カスタム・プロバイダおよびリソースを作成できます。このセクションでは、カスタム・プロバイダを登録する方法、およびCoherenceのデフォルト・ルート・リソースをオーバーライドする方法について説明します。

com.tangosol.coherence.rest.server.DefaultResourceConfigクラスでは、カスタム・プロバイダまたはリソースの登録に使用できるパッケージ・スキャンをサポートします。次の例では、パッケージ・スキャンを使用して、カスタム・プロバイダおよびリソースを登録しています。

public class MyResourceConfig  extends DefaultResourceConfig
{
public MyResourceConfig()
{
super("com.my.providers;com.my.resources");
}
}

また次の例では、DefaultResourceConfigクラスに定義されている1つ以上のregisterメソッドをオーバーライドして、カスタム・プロバイダ、カスタム・ルート・リソースを使用したり、フィルタおよびフィルタ・ファクトリを追加する方法を示します。

注意:

Coherenceのデフォルト・プロバイダをオーバーライドする場合は必ずルート・リソース・クラスもオーバーライド(登録解除)してください(DefaultRootResourceクラスは、デフォルト・プロバイダに依存して、必要な依存性および構成を提供します)。

public class MyResourceConfig  extends DefaultResourceConfig
{
protected void registerRootResource()
{
// remove if you don't want Coherence defaults to be registered
super.registerRootResource();
getClasses().add(MyRootResource.class);
}

protected void registerProviders()
{
// remove if you don't want Coherence defaults to be registered
super.registerProviders();
getSingletons().add(new MyProvider());
}

protected void registerContainerRequestFilters()
{
// remove if you don't want Coherencedefaults to be registered
super.registerContainerRequestFilters();
getContainerRequestFilters().add(new MyRequestFilter());
}

protected void registerContainerResponseFilters()
{
// remove if you don't want Coherence defaults to be registered
super.registerContainerResponseFilters();
getContainerResponseFilters().add(new MyResponseFilter());
}

protected void registerResourceFilterFactories()
{
// remove if you don't want Coherence defaults to be registered
super.registerResourceFilterFactories();
getResourceFilterFactories().add(new MyResourceFilterFactory());
}
}

キャッシュ構成ファイルでカスタム・リソース構成クラスを有効にするには、HTTPアクセプタ構成内の<resource-config>要素を使用して、クラスの完全修飾名を追加します。クラスは特定のコンテキスト・パスにマップされます。例:

<proxy-scheme>
<service-name>ExtendHttpProxyService</service-name>
<acceptor-config>
<http-acceptor>
...
<resource-config>
<context-path>/MyApplicationContext</context-path>
<instance>
<class-name>package.MyResourceConfig</class-name>
</instance>
</resource-config>
</http-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>

コンテキスト・パスが指定されない場合、デフォルト・コンテキスト・パス(/)が使用されます。複数のリソース構成クラス定義を別のコンテキスト・パスに追加、マップできます。

27.2 埋込みHTTPサーバーの変更

Coherence RESTでは、リクエストの処理にデフォルトでOracleの軽量HTTPサーバーを使用します。ただし、この実装は本番環境には適切でなく、一般的には開発またはテスト時に使用されます。そのかわりに、CoherenceにはGrizzly HTTPサーバー実装が含まれ、Simple HTTPサーバーも使用できます。追加のHTTPサーバーの統合する方法については、このドキュメントでは述べません。Jerseyのドキュメントを参照してください。

http://jersey.java.net/

この項には、次のトピックが含まれます:

- Grizzly HTTPサーバーの使用方法

- Simple HTTPサーバーの使用方法

27.2.1 Grizzly HTTPサーバーの使用方法

Coherence RESTは、Grizzly 2 HTTPサーバー実装(com.tangosol.coherence.rest.server.GrizzlyHttpServer)を備えており、デフォルトのHTTPサーバーのかわりに使用できます。Grizzly HTTPサーバーの詳細は、次を参照してください。

http://grizzly.java.net/

キャッシュ構成ファイルでGrizzlyサーバーを有効にするには、HTTPアクセプタ構成内の<class-name>要素の値として実装の完全修飾名を追加します。例:

<proxy-scheme>
<service-name>ExtendHttpProxyService</service-name>
<acceptor-config>
<http-acceptor>
<class-name>com.tangosol.coherence.rest.server.GrizzlyHttpServer
</class-name>
...
</http-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>

27.2.2 Simple HTTPサーバーの使用方法

SimpleフレームワークはJersey内でサポートされているため、埋込みHTTPサーバーとして使用できます。Simpleフレームワークの詳細は、次を参照してください。

http://www.simpleframework.org/

埋込みHTTPサーバーとしてSimpleフレームワークを使用するには、com.tangosol.coherence.rest.server.AbstractHttpServerクラスを拡張して、そのクラスをキャッシュ構成ファイルで有効にします。

次の例では、SimpleHttpServerクラスを作成します。

public class SimpleHttpServer extends AbstractHttpServer
{
public void start()
{
Closeable connection = m_connection;
if (connection == null)
{            try
{
connection = SimpleServerFactory.create("http://" +
getLocalAddress() + ":" + getLocalPort(),getResourceConfig());
}
catch (IOException e)
{
throw new WrapperException(e);
}
m_connection = connection;
}
}

public void stop()
{
Closeable connection = m_connection;
if (connection != null)
{
try
{
connection.close();
}
catch (IOException e)
{
throw new WrapperException(e);
}
finally
{
m_connection = null;
}
}
}

protected Closeable m_connection;
}

キャッシュ構成ファイルでSimpleHttpServerクラスを有効にするには、HTTPアクセプタ構成内の<class-name>要素の値として完全修飾名を追加します。例:

<proxy-scheme>
<service-name>ExtendHttpProxyService</service-name>
<acceptor-config>
<http-acceptor>
<class-name>package.SimpleHttpServer</class-name>
...
</http-acceptor>
</acceptor-config>
<autostart>true</autostart>
</proxy-scheme>

A RESTの構成要素

この付録では、REST構成デプロイメント・ディスクリプタに関する詳細リファレンスと、ディスクリプタの簡単な概要を示します。

この付録では次の項について説明します。

- REST構成ファイル

- 要素リファレンス

A.1 REST構成ファイル

REST構成デプロイメント・ディスクリプタにより、REST実装の構成を指定します。ディスクリプタのデフォルト名はcoherence-rest-config.xmlで、クラスパス上で見つかる必要があります。tangosol.coherence.rest.configシステム・プロパティを使用して、名前をオーバーライドできます。例:

-Dtangosol.coherence.rest.config=MyConfig.xml

REST構成デプロイメント・ディスクリプタのスキーマは、coherence-rest-config.xsdファイルに定義されます。XSDファイルはcoherence.jarライブラリのルートにおいて次のWeb URLにあります。

http://xmlns.oracle.com/coherence/coherence-rest-config/1.1/coherence-rest-config.xsd

<rest>要素は構成ファイルのルート要素で、一般的にXSDとCoherenceのネームスペース参照およびcoherence-rest-config.xsdファイルの場所が含まれています。例:

<?xml version='1.0'?>

<rest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-rest-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-rest-config
coherence-rest-config.xsd">

注意:

- xsi:schemaLocation属性でWeb URLを参照した場合でも、coherence.jarライブラリにあるスキーマは必ず実行時に使用されます。

- xsi:schemaLocation属性を省略してスキーマ検証を無効にできます。

- デフォルトのキャラクタ・セットがASCIIではなくEBCDICである環境にCoherenceをデプロイする場合、このデプロイメント・ディスクリプタ・ファイルがASCII形式であり、ランタイム環境にバイナリ形式でデプロイされることを確認してください。

要素リファレンス

表A-1に、非終端REST構成要素のすべてを示します。

表A-1 RESTの構成要素

要素

使用場所

aggregator

aggregators

aggregators

rest

engine

query-engines

marshaller

resource

processor

processors

processors

rest

query

resource

query-engines

rest

resource

resources

resources

rest

rest

root element

aggregator

使用場所: aggregators

説明

aggregator要素は、キャッシュにあるデータの集計に使用するカスタム・アグリゲータの定義に使用されます。各aggregator要素には、アグリゲータ・クラスまたはアグリゲータのファクトリ・クラスと名前との間における単一バインディングが含まれている必要があります。

要素

表A-2でaggregator要素の下位要素を説明します。

表A-2 aggregatorの下位要素

要素

必須/
オプション

説明

<name>

必須

アグリゲータ・クラスまたはアグリゲータのファクトリ・クラスにバインドされるREST用URLで使用する名前を指定します。

<class>

必須

名前にバインドされるカスタム・アグリゲータ・クラスまたはカスタム・アグリゲータのファクトリ・クラスの完全修飾名を指定します。このクラスはcom.tangosol.util.EntryAggregatorまたはcom.tangosol.coherence.rest.util.aggregator.AggregatorFactoryインタフェースをそれぞれ実装する必要があります。

aggregators

使用場所: rest

説明

aggregators要素には、任意の数のカスタム・アグリゲータ定義が格納されます。

要素

表A-3でaggregators要素の下位要素を説明します。

表A-3 aggregatorsの下位要素

要素

必須/
オプション

説明

<aggregator>

必須

アグリゲータ・クラスまたはアグリゲータのファクトリ・クラスと名前との間における単一バインディングを指定します。

engine

使用場所: query-engines

説明

engines要素は、名前と問合せエンジン実装クラスとの間の単一バインディングを含みます。カスタム問合せエンジンには、com.tangosol.coherence.rest.query.QueryEngineとcom.tangosol.coherence.rest.query.Queryインタフェースを実装する必要があります。カスタム実装は、com.tangosol.coherence.rest.query.AbstractQueryEngineベース・クラスも拡張します。これにより、問合せ式の分析やパラメータ・バインドの処理を実行する有用なメソッドが提供されます。

要素

表A-4で、engine要素のサブ要素を説明します。

表A-4 engineの下位要素

要素

必須/
オプション

説明

<name>

必須

問合せエンジンの名前を指定します。

<class-name>

必須

問合せエンジン実装クラスの完全修飾名を指定します。

marshaller

使用場所: resource

説明

キャッシュ・エントリのキーと値のクラスとマーシャリング処理クラス(それらのクラスのインスタンスでマーシャリングとアンマーシャリングに使用)との間におけるバインドがマーシャリング要素にはあります。

要素

表A-5でmarshaller要素の下位要素を説明します。

表A-5 marshallerの下位要素

要素

必須/
オプション

説明

<media-type>

必須

マーシャリング用に使用するメディアの名前を指定します。CoherenceではXMLとJSONのデータ出力のデフォルト実装が用意されています。

<class-name>

必須

com.tangosol.coherence.rest.io.Marshallerインタフェースを実装するカスタム・クラスの完全修飾名を指定します。キャッシュに格納されるキャッシュ・エントリ値のマーシャリングとアンマーシャリングに実装が使用されます。マーシャリング処理は、それぞれのオブジェクト・タイプとメディア・タイプに対して構成されます。

processor

使用場所: processors

説明

processor要素は、キャッシュにあるデータの処理に使用するカスタム入力プロセッサの定義に使用されます。各processor要素には、プロセッサのファクトリ・クラスと名前との間における単一バインディングが含まれている必要があります。

要素

表A-6でprocessor要素の下位要素を説明します。

表A-6 processorの下位要素

要素

必須/
オプション

説明

<name>

必須

プロセッサのファクトリ・クラスにバインドされるREST用URLで使用する名前を指定します。

<class-name>

必須

名前にバインドされるカスタム・プロセッサのファクトリ・クラスの完全修飾名を指定します。このクラスはcom.tangosol.coherence.rest.util.processor.ProcessorFactoryインタフェースを実装する必要があります。

processors

使用場所: rest

説明

processors要素には、任意の数のカスタム・プロセッサ定義が格納されます。

要素

表A-7でprocessors要素の下位要素を説明します。

表A-7 processorsの下位要素

要素

必須/
オプション

説明

<processor>

必須

プロセッサのファクトリ・クラスと名前との間における単一バインディングを指定します。

query

使用場所: resources

説明

query要素は、名前付き問合せを定義します。名前付き問合せにより、REST URLで構成済の問合せ式を名前で実行できます。

GET http://host:port/cacheName/namedQuery?param1=value1,param2=value2...

名前付き問合せ定義は、問合せ名と実行する問合せ式間のバインディングから成ります。リソースに対して複数の名前付き問合せを構成できます。この問合せ要素では、次の属性がサポートされています。

- max-results: 名前付き問合せに返す結果の最大数を指定します。この値は、<resource>要素のmax-results属性よりも優先されます。

- engine: キャッシュに対する問合せ式の実行を受け持つ問合せエンジンの実装を指定します。属性が指定されていない場合のデフォルト値はDEFAULTであり、問合せ式をURLエンコードのCohQL式(CohQLの述語句)として指定する必要があることを示します。カスタム問合せエンジン実装の構成の詳細は、<query-engines>要素を参照してください。

要素

表A-8で、query要素のサブ要素を説明します。

表A-8 queryの下位要素

要素

必須/
オプション

説明

<name>

必須

queryの名前を指定します。

<expression>

必須

問合せ名にバインドする問合せ式を指定します。

query-engines

使用場所: rest

説明

query-engines要素には、任意の数のカスタム問合せエンジン定義が格納されます。問合せエンジンは、キャッシュに対して問合せ式を実行します。直接問合せおよび名前付き問合せは、基盤となる問合せエンジンに、それらの問合せの実行を依存しています。デフォルトの問合せエンジンは、URLエンコードのCohQL式(CohQLの述語句)として指定された問合せ式を実行するために提供されています。また、カスタム問合せエンジンを必要時に定義できます。

要素

表A-9で、query-engines要素のサブ要素を説明します。

表A-9 query-enginesのサブ要素

要素

必須/
オプション

説明

<engine>

必須

名前と問合せエンジン実装クラスの間における単一バインディングを指定します。

resource

使用場所: resources

説明

resource要素によりキャッシュ・エントリのマーシャリングとアンマーシャリングに使用するメタデータを渡します。キャッシュ名とキャッシュ・エントリ・キーと値クラスとの間における単一バインディングがメタデータに含まれます。

次の属性を使用できます。

- name: 名前がRESTのURLパス・セグメント用に理想的でない場合における<cache-name>要素の別名を指定します。この値のデフォルトは、値が指定されていない場合における<cache-name>要素の値です。

- max-results: 問合せに返す結果の最大数を指定します。この値は、max-results属性が、<query>または<direct-query>要素内にも定義されている場合に優先されます。

要素

表A-10でresource要素の下位要素を説明します。

表A-10 resourceの下位要素

要素

必須/
オプション

説明

<cache-name>

必須

このリソースで公開されるキャッシュの名前を指定します。キャッシュは、キャッシュ構成ファイルで定義する必要があります。

<key-class>

必須

このキャッシュに格納されるエントリ・キーのタイプを指定します。

<value-class>

必須

このキャッシュに格納されるエントリ値のタイプを指定します。

<key-converter>

オプション

com.tangosol.coherence.rest.KeyConverterインタフェースを実装するクラスの完全修飾名を指定します。このクラスは、キャッシュ・エントリのキーを文字列に変換したり、REST用URLで使用するキーの文字列表現をキャッシュ・エントリへのアクセスに使用できる適切なオブジェクト・インスタンスに変換するために使用されます。値が渡されない場合、com.tangosol.coherence.rest.DefaultKeyConverterクラスがデフォルトで使用されます。デフォルトのクラスには、Javaのプリミティブ、日付およびUUIDにおける文字列変換処理が用意されています。詳細は、Oracle CoherenceのJava APIリファレンスを参照してください。

<marshaller>

オプション

com.tangosol.coherence.rest.io.Marshallerインタフェースを実装するクラスの完全修飾名を指定します。キャッシュに格納されるキャッシュ・エントリ値のマーシャリングとアンマーシャリングにクラスが使用されます。CoherenceではXMLとJSONのデータ出力のデフォルト実装が用意されています。

<query>

オプション

REST URLで、構成済問合せ式の名前による実行を可能にする名前付き問合せの構成情報を指定します。

<direct-query>

オプション

REST URLに問合せ式をパラメータqの値として含めることができる、直接問合せの構成情報を指定します。

GET http://host:port/cacheName?q=query

次の属性を使用できます。

- enabled: リソースで直接問合せをサポートするかどうかを指定します。有効な値は、trueとfalseです。デフォルト値はfalseです。

- max-results: 直接問合せに返す結果の最大数を指定します。この値は、<resource>要素のmax-results属性よりも優先されます。

- engine: キャッシュに対する問合せ式の実行を受け持つ問合せエンジンの実装を指定します。属性が指定されていない場合のデフォルト値はDEFAULTであり、問合せ式をURLエンコードのCohQL式(CohQLの述語句)として指定する必要があることを示します。カスタム問合せエンジン実装の構成の詳細は、<query-engines>要素を参照してください。

resources

使用場所: rest

説明

リソース要素には、任意の数のリソース定義が格納されます。キャッシュ・エントリのマーシャリングとアンマーシャリングに使用するメタデータをリソース定義により渡します。

要素

表A-11でresources要素の下位要素を説明します。

表A-11 resourcesの下位要素

要素

必須/
オプション

説明

<resource>

必須

キャッシュ・エントリ・キーと値クラスとキャッシュ名との間における単一バインディングを指定します。

rest

root element

説明

rest要素は、Coherence REST実装の構成に使用するcoherence-rest-config.xmlファイルのルート要素です。実装ではRESTのWebサービスを使用して、リモート・クライアントでクラスタにあるデータをHTTPでアクセスでき、POFシリアライズを使用する必要はありません。

要素

表A-12でrest要素の下位要素を説明します。

表A-12 restの下位要素

要素

必須/
オプション

説明

<resources>

オプション

キャッシュ・エントリのマーシャリングとアンマーシャリングに使用するメタデータを渡すリソース定義の数を指定します。

<processors>

オプション

キャッシュにあるデータの処理に使用するカスタム・プロセッサ定義の数を指定します。

<aggregators>

オプション

キャッシュにあるデータの集計に使用するカスタム・アグリゲータ定義の数を指定します。

<query-engines>

オプション

任意の数のカスタム問合せエンジン定義を指定します。問合せエンジンは実行問合せを処理します。

B F5 BIG-IP LTMとの統合

この付録では、F5 BIG-IP Local Traffic Manager (LTM)のハードウェア型ロード・バランサを使用して、Coherence*Extendクライアント接続の負荷を分散させる方法について説明します。BIG-IPシステムを使用してSSL処理の負荷を軽減するための指示も含まれています。

この指示はCoherence*Extend設定に関係するので、BIG-IP構成ユーティリティを使用する場合に特有です。使用方法に関する指示を実行する方法の詳細は、ユーティリティに付属しているヘルプを参照してください。さらに、指示はBIG-IP LTM 10.2.1に基づいて作成されており、将来リリースされるBIG-IP LTMでは正確でなくなる場合があります。

この付録では次の項について説明します。

- 基本概念

- ノードの作成

- ロード・バランシング・プールの構成

- 仮想サーバーの構成

- BIG-IP LTMを使用するようにCoherence*Extendを構成する方法

- 高度な状態モニターの使用方法

- SSLオフロードの有効化

B.1 基本概念

F5 BIG-IP LTMとは、Coherence*Extendクライアント(クライアント層)を実行している1台以上のコンピュータとCoherence*Extendプロキシ・サーバー(プロキシ層)を実行している1台以上のコンピュータとの間にあるハードウェア・デバイスのことです。アプリケーション・トラフィックの保護、最適化およびロード・バランシングに関して多様なテクニックを使用して、LTMによりクライアント接続を複数のクラスタ化プロキシ・サーバーにおいて分散させます。

図B-1は、外部ネットワーク・クライアントと内部ネットワーク・サーバーとの間において設定されているBIG-IPシステムの概念図を示します。

図B-1 F5 BIG-IP LTMの概念図

「図B-1 F5 BIG-IP LTMの概念図」の説明

B.2 ノードの作成

ノードとは、ネットワーク上にある物理リソースのIPアドレスを識別するBIG-IPシステム上の論理オブジェクトのことです。Coherence*Extendの場合、内部ネットワークで1台以上のプロキシ・サーバーをホストする各コンピュータに対してノードを構成します。

ノードを作成するには、次の手順を実行します。

1. BIG-IP構成ユーティリティにログインします。

2. ナビゲーション・ペインの「Main」タブで、「Local Traffic」を展開してから「Nodes」をクリックします。

3. 画面の右上隅にある「Create」をクリックします。「New Node」画面が表示されます。

4. 「Address」設定で、ノードのIPアドレスを入力します。

5. その他の設定のそれぞれに関して値を指定するか、そのままにするか、変更します。

6. 「Finished」をクリックします。

図B-2に、ノード構成例を示します。

図B-2 ノード構成例

「図B-2 ノード構成例」の説明

B.3 ロード・バランシング・プールの構成

ロード・バランシング・プールは、トラフィックを受信および処理する論理デバイス(プロキシ・サーバーなど)のグループです。クライアントのリクエストで指定された送信先IPアドレスにクライアントのトラフィックを送信するのではなく、BIG-IPシステムではそのプールのメンバーであるサーバーにリクエストを送信します。これによって、サーバーのリソースに関して負荷が効率的に分散されます。

プールを作成する際、プール・メンバーをプールに割り当てます。プール・メンバーとは、サーバー・エンドポイントをネットワーク上で示す論理オブジェクトのことです。Coherence*Extendの場合、プロキシ層コンピュータ上で実行している各JVMプロキシ・サーバーに対してプール・メンバーを作成します。

BIG-IPシステムがリクエストの送信先に選択した特定プール・メンバーは、そのプールに割り当てたロード・バランシング方法により判別されます。ロード・バランシング方法とは、リクエストを処理するプール・メンバーを選択するためにBIG-IPシステムで使用するアルゴリズムのことです。たとえば、デフォルトのロード・バランシング方法はラウンド・ロビンで、これによってBIG-IPシステムで各入力リクエストを次に利用可能なプール・メンバーに送信し、プールにあるサーバーにおいてリクエストが均等に分散されます。

この項には、次のトピックが含まれます:

- ロード・バランシング・プールの作成

- ロード・バランシング・プールのメンバーの追加

B.3.1 ロード・バランシング・プールの作成

ロード・バランシング・プールを作成するには、次の手順を実行します。

1. BIG-IP構成ユーティリティにログインします。

2. ナビゲーション・ペインの「Main」タブで、「Local Traffic」を展開してから「Pools」をクリックします。「Pools」画面が表示されます。

3. 画面の右上隅にある「Create」をクリックします。「New Pool」画面が表示されます。

4. 「Configuration」リストで、「Advanced」を選択します。

5. 「Name」設定で、プールの名前を入力します。

6. その他の設定のそれぞれに関して値を指定するか、そのままにするか、変更します。

7. 「Finished」をクリックします。

図B-3は、プール構成例を示します。

図B-3 プール構成例

「図B-3 プール構成例」の説明

B.3.2 ロード・バランシング・プールのメンバーの追加

プールのメンバーをロード・バランシング・プールに追加するには、次の手順を実行します。

1. 「Members」タブで、表示されている番号をクリックします。これによって、プールの既存メンバーが一覧表示されます。

2. 画面の右にある「Add」をクリックします。「New Pool Member」画面が表示されます。

3. 「Address」ボックスで、「Node List」を選択してからIPアドレスを選択します。

4. 「Service Port」ボックスで、対応プロキシ・サーバーがリスニングするポート番号を入力します。

5. その他の設定のそれぞれに関してそのままにするか変更します。

6. 「Finished」をクリックします。

図B-4は、プール構成例を示します。以前に作成したノード上で2つのプロキシ・サーバー用プール・メンバーが稼動し、ポートの9099と9100をそれぞれリスニングしていることが示されています。さらに、接続数最小型ロード・バランシング・ポリシーを使用するようにプールが構成されます。

図B-4 プールのメンバー例

「図B-4 プールのメンバー例」の説明

B.4 仮想サーバーの構成

仮想サーバーとは、BIG-IPシステム上でIPアドレスとポートで示されるトラフィック管理オブジェクトのことです。外部ネットワークにあるクライアントは、アプリケーション・トラフィックを仮想サーバーに送信できます。それから、構成指示に応じてそのトラフィックが転送されます。仮想サーバーの主な目的は、内部ネットワークにあるサーバーのプールにおいてトラフィックの負荷を分散させることにある場合が多いです。仮想サーバーを使用することで、クライアント・リクエストを処理するためのリソースの可用性が向上します。Coherence*Extendの場合、以前に構成したプロキシ・サーバーのプールにトラフィックを転送するように仮想サーバーを構成する必要があります。

仮想サーバーを作成するには、次の手順を実行します。

1. BIG-IP構成ユーティリティにログインします。

2. ナビゲーション画面の「Main」タブで、「Local Traffic」を展開してから「Virtual Servers」をクリックします。「Virtual Servers」画面が表示されます。

3. 画面の右上にある「Create」をクリックします。「New Virtual Server」画面が表示されます。

4. 「Name」設定で、仮想サーバーの名前を入力します。

5. 「Destination」ボックスで、BIG-IPデバイスの外部IPアドレスを割り当て、「Service Port」ボックスでリスニング・ポートを指定します。これは、Coherence*Extendクライアントの接続先となるIPアドレスとポートです。

6. 以前に作成したプールを「Default Pool」ドロップダウン・ボックスで選択します。

7. その他の設定のそれぞれに関してそのままにするか変更します。

8. 「Finished」をクリックします。

図B-5は、10.196.21.3:9099上でTCP/IP接続においてリスニングする仮想構成例を示します。

図B-5 仮想サーバー例

「図B-5 仮想サーバー例」の説明

さらに、図B-6に示すように、構成されたプールにトラフィックがこの仮想サーバーにより転送されます。

図B-6 構成プールを使用する仮想サーバー例

「図B-6 構成プールを使用する仮想サーバー例」の説明

B.5 BIG-IP LTMを使用するようにCoherence*Extendを構成する方法

BIG-IP LTM仮想サーバーを使用するようにCoherence*Extendを構成する必要があります。クラスタ側とクライアント側のキャッシュ構成ファイルの両方で構成が行われている必要があります。

BIG-IP LTMを使用するようにCoherence*Extendを構成するには、次の手順を実行します。

1. プロキシ・サーバーのキャッシュ構成ファイルを開きます。

2. プロキシ・スキーム定義を編集して、clientを<load-balancer>要素内で入力することで、クライアント用ロード・バランシング戦略を指定します。例:

<proxy-scheme>
<service-name>ExtendTcpProxyService</service-name>
<acceptor-config>
<tcp-acceptor>
<local-address>
<address>192.168.1.2</address>
<port>9099</port>
</local-address>
</tcp-acceptor>
</acceptor-config>
<load-balancer>client</load-balancer>
<autostart>true</autostart>
</proxy-scheme>

3. プロキシ・サーバーのキャッシュ構成ファイルを保存してから閉じます。追加プロキシ・サーバーに対して手順2を繰り返します。

4. クライアントのキャッシュ構成ファイルを開きます。

5. <remote-cache-scheme>要素で、BIG-IP仮想サーバーのIPアドレスとポートを一覧表示します。「仮想サーバーの構成」を参照してください。さらに、<heartbeat-interval>要素を<outgoing-message-handler>要素内で指定します。これによって、構成されている時間間隔でTCP/IP接続上にクライアントが定期的にハートビート・メッセージを送信します。アイドル状態のクライアントからBIG-IPデバイスが接続を切断するのを防止するには、これが必要です。例:

<remote-cache-scheme>
<scheme-name>extend-direct</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>10.196.21.3</address>
<port>9099</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<heartbeat-interval>5s</heartbeat-interval>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>

6. クライアントのキャッシュ構成ファイルを保存してから閉じます。

B.6 高度なヘルス・モニタリングの使用方法

サーバーが稼働状態にありトラフィックを受信できることをヘルス・モニターにより確認できます。監視するトラフィックのタイプに応じて、プールに関連付けることができる多様な事前定義済ヘルス・モニターがBIG-IPシステムにはあります。

Coherence*Extendの場合、TCPヘルス・モニターを使用して、プロキシ・サーバーのプールを監視できます。BIG-IPデバイスがプロキシ・サーバーとTCP/IP接続を確立できる場合に、このタイプのモニターでプロキシ・サーバーがマークアップされます。プロキシ・サーバーが機能していることが示されているとしても、プロキシ・サーバーで実際にクライアントのトラフィックを処理できることは保証されません。より詳細に監視するには、BIG-IPでカスタム・ヘルス・モニターを作成し。Coherence*Extendのpingリクエストをプロキシ・サーバーに送信して適切なレスポンスが返されることを確認できます。これによって、プロキシ・サーバーが稼働してクライアントのトラフィックを処理できます。

この項には、次のトピックが含まれます:

- カスタム状態モニターを作成してCoherenceにpingを送信する方法

- カスタム状態モニターをロード・バランシング・プールと関連付ける方法

B.6.1 カスタム・ヘルス・モニターを作成してCoherenceにpingを送信する方法

Coherence*Extendのpingリクエストをプロキシ・サーバーに送信して稼働していることを確認するカスタムCoherence*Extendヘルス・モニターを作成する手順は次のとおりです。

1. BIG-IP構成ユーティリティにログインします。

2. ナビゲーション・ペインの「Main」タブで、「Local Traffic」を展開してから「Monitors」をクリックします。「Monitors」画面が表示されます。

3. 画面の右上隅にある「Create」をクリックします。「New Monitor」画面が表示されます。

4. モニターの名前を「Name」ボックスに入力します。

5. 「TCP」を「Type」ドロップダウン・ボックスで選択します。

6. 次を「Send String」ボックスで入力します。

\x07\x00\x03\x00\x00\x42\x00\x40

7. 次を「Receive String」ボックスで入力します。

\x09\x00\x04\x02\x00\x42\x00\x03\x64\x40

8. 「Finished」をクリックします。

図B-7は、カスタムCoherence*Extendヘルス・モニター構成例を示します。

図B-7 Coherence*Extend pingヘルス・モニター例

「図B-7 Coherence*Extend pingヘルス・モニター例」の説明

前述の手法は、BIG-IPバージョン10.2.1以降でのみ動作します。それより古いバージョンのBIG-IPの場合、手動で外部ヘルス・モニターを構成する必要があります。このためには、実行可能ファイルのシェル・スクリプトをextend_pingの名前でBIG-IPデバイスの/usr/bin/monitorsディレクトリに作成します。スクリプトの内容は次のようにします。

#! /bin/bash
###############################################################################
###  EXTERNAL MONITOR FOR COHERENCE*EXTEND
###   INPUTS:
###     $1    The IPV6 formatted IP address of the pool member to test
###     $2    The port number of the pool member to test
###     $3+   White space delimited parms as listed in the monitor "args"
###   OUTPUTS:
###     If null is returned, the member is "down"
###     If any string of one or more characters is returned, the member is "up"
###############################################################################

IP=${1:-"127.0.0.1"}
IP=${IP##*:} # This removes the leading ::ffff:
PORT=${2:-"80"}
TIMEOUT=${3:-1}
SLEEP=${4:-1}

PID_FILE="/var/run/extend_ping.$IP.$PORT.pid"
HEX_REQUEST="0700030000420040"
HEX_RESPONSE="09000402004200036440"

###
### Terminate existing process, if any
###
if [ -f $PID_FILE ]
then
kill -9 `cat $PID_FILE` > /dev/null 2>&1
fi
echo "$$" > $PID_FILE

###
###  Ping the server and return a user friendly result
###
RESULT=`/bin/echo "$HEX_REQUEST" | /usr/bin/xxd -r -p | /usr/bin/nc -i \
$SLEEP -w $TIMEOUT $IP $PORT | /usr/bin/xxd -p | /bin/grep \
"$HEX_RESPONSE" 2> /dev/null`

if [ "$RESULT" != "" ] ; then
/bin/echo "$IP:$PORT is \"UP\""
fi

rm -f $PID_FILE

extend_pingスクリプトを使用するようにBIG-IPを構成する手順は次のとおりです。

1. ナビゲーション・ペインの「Main」タブで、「Local Traffic」を展開してから「Monitors」をクリックします。「Monitors」画面が表示されます。

2. 画面の右上隅にある「Create」をクリックします。「New Monitor」画面が表示されます。

3. モニターの名前を「Name」ボックスに入力します。

4. 「External」を「Type」ドロップダウン・ボックスで選択します。

5. 次を「External Program」ボックスで入力します。

/usr/bin/monitors/extend_ping

6. 「Finished」をクリックします。

図B-8は、外部Coherence*Extendヘルス・モニター構成例を示します。

図B-8 シェル・スクリプトで実装されたCoherence*Extendヘルス・モニター例

「図B-8 シェル・スクリプトで実装されたCoherence*Extendヘルス・モニター例」の説明

B.6.2 カスタム・ヘルス・モニターをロード・バランシング・プールと関連付ける方法

カスタム・ヘルス・モニターはロード・バランシング・プールと関連付ける必要があります。カスタムCoherence*Extendモニターを作成したら、それをCoherence*Extendロード・バランシング・プールと関連付けます。

カスタム・ヘルス・モニターをロード・バランシング・プールと関連付けるには、次の手順を実行します。

1. BIG-IP構成ユーティリティにログインします。

2. ナビゲーション・ペインの「Main」タブで、「Local Traffic」を展開してから「Pools」をクリックします。「Pools」画面が表示されます。

3. Coherence*Extendプールの名前をクリックします。「Pool」画面が表示されます。

4. カスタムCoherence*Extendヘルス・モニターの名前を「Health Monitors」ボックスで選択します。

5. 「Update」をクリックします。

図B-9は、カスタム・ヘルス・モニターを使用するCoherence*Extendプールを示します。

図B-9 Coherence*Extendプールをカスタム・ヘルス・モニターと関連付ける方法

「図B-9 Coherence*Extendプールをカスタム・ヘルス・モニターと関連付ける方法」の説明

B.7 SSLオフロードの有効化

SSLを使用するようにCoherence*Extendを構成して、クライアントとプロキシ・サーバーのプロセスとの間における通信を保護できます。ただし、これには代償があります。特に、SSLを有効にすると、プロキシ層のCPU使用率が劇的に上昇し、各リクエストの待機時間が長くなります。プライバシの理由で保護されているデータの暗号化と復号化の困難な処理からプロキシ・サーバーが、BIG-IP SSL Accelerationにより解放されます。SSLトランザクションをより効率的に処理するように設計されている高いパフォーマンスのデバイスに、CPU負荷の高い復号化処理が移行されます。この手法はSSLオフロードと知られています。

SLLオフロードを有効にするには、次の手順を記載順に実行する必要があります。

1. Coherence*Extendクライアントのキャッシュ構成ファイルでSSLを有効にします。SSLを使用するようにExtendクライアントを構成する方法の詳細は、『Oracle Coherenceの保護』を参照してください。

2. サーバーのSSL証明書とキーのインポート

3. クライアントSSLプロファイルの作成

4. クライアントSSLプロファイルの関連付け

B.7.1 サーバーのSSL証明書とキーのインポート

サーバーのSSL証明書とキーをBIG-IPシステムにインポートする手順は、次のとおりです。

1. BIG-IP構成ユーティリティにログインします。

2. ナビゲーション・ペインの「Main」タブで、「Local Traffic」を展開し、マウスのポインタを「SSL Certificates」の上に移動してから「Import」選択します。「SSL Certificate」画面が表示されます。

3. 「Import Type」ドロップダウン・ボックスで、「PKCS12」を選択します。

4. 証明書の名前を「Certificate Name」ボックスに入力します。

5. 「Choose File」をクリックしてから、サーバーのPKCS12ファイルを参照します。

6. PKCS12ファイルのパスワードを入力します。

7. 「Import」をクリックします。

図B-10は、サーバーSSL証明書構成例を示します。

図B-10 BIG-IPシステムにおけるSSL証明書構成例

「図B-10 BIG-IPシステムにおけるSSL証明書構成例」の説明

B.7.2 クライアントSSLプロファイルの作成

クライアントSSLプロファイルを作成するには、次の手順を実行します。

1. ナビゲーション・ペインの「Main」タブで、「Local Traffic」を展開し、マウスのポインタを「Profiles」の上に移動してから「SSL」の上に移動し、「Client」選択します。「Client SSL Profiles」画面が表示されます。

2. 画面の右上隅にある「Create」をクリックします。「New Client SSL profile」画面が表示されます。

3. クライアントSSLプロファイルの名前を「Name」ボックスに入力します。

4. 右側で「Custom」チェック・ボックスを選択します。

5. 以前にインポートしたサーバー証明書の名前を「Certificate」と「Key」の両ドロップダウン・ボックスで選択します。

6. 「Finished」をクリックします。

図B-11は、クライアントSSLプロファイル構成例を示します。

図B-11 SSLプロファイル構成例

「図B-11 SSLプロファイル構成例」の説明

B.7.3 クライアントSSLプロファイルの関連付け

クライアントSSLプロファイルを使用するようにCoherence*Extend仮想サーバー構成を変更する手順は次のとおりです。

1. ナビゲーション画面の「Main」タブで、「Local Traffic」を展開してから「Virtual Servers」をクリックします。「Virtual Servers」画面が表示されます。

2. 仮想サーバーの名前をクリックします。

3. クライアントSSLプロファイルの名前を「SSL Profile (Client)」ドロップダウン・ボックスで選択します。

4. 「Update」をクリックします。

図B-12は、クライアントSSLプロファイルを使用する仮想サーバー構成例を示します。

図B-12 クライアントSSLプロファイルのある仮想サーバー構成例

「図B-12 クライアントSSLプロファイルのある仮想サーバー構成例」の説明

Copyright © 2008, 2013, Oracle and/or its affiliates. All rights reserved.