はじめに
ZooKeeperをJavaから利用する場合、直接ZooKeeper APIを使うと接続管理やリトライ処理が煩雑になりがちです。そうした課題を解決してくれるのが、Apache Curatorというライブラリです。中でも CuratorFramework
クラスは、ZooKeeperクライアントとしての中心的な役割を担っており、セッション管理や再接続などの複雑な処理を抽象化してくれます。
この記事では、Apache Curatorの中心クラスであるCuratorFramework
の使い方を、初心者にもわかりやすく、実運用を意識した形で解説します。
なお、Apache Curator全体の概要については以下の記事で解説していますので、あわせてご覧ください。

CuratorFrameworkとは?
CuratorFramework
は、Apache Curatorライブラリが提供する ZooKeeperクライアントの中心的なインタフェース です。このクラスを通じて、ZooKeeperとの接続やノードの作成・監視・削除といった操作を簡潔に行うことができます。
最大の特徴は、セッション管理や再接続処理などの煩雑な処理を内部で自動的に行ってくれる点です。これにより、開発者は接続状態を気にすることなく、ビジネスロジックの実装に集中できます。
イメージしやすい例として、データベースのコネクションに相当するものと考えると理解しやすいでしょう。(※厳密には異なります)
CuratorFrameworkの生成方法
CuratorFramework
を使い始めるには、まずインスタンスを生成して接続を開始する必要があります。
簡易的な生成方法
最もシンプルな書き方は以下の通りです。
try (CuratorFramework client = CuratorFrameworkFactory.newClient(
"localhost:2181",
5000,
3000,
new ExponentialBackoffRetry(1000, 3)
)) {
client.start();
// ZooKeeperとのやり取りをここで実行
}
この newClient
メソッドは、ZooKeeperとの接続に必要な最低限の構成を指定するだけで CuratorFramework
のインスタンスを生成できる簡易APIです。
newClientの引数
パラメータ | 型 | 必須 / 任意 | 説明 |
---|---|---|---|
connectString | String | 必須 | 接続先ZooKeeper(カンマ区切りで複数指定可能) |
sessionTimeoutMs | int | 任意 | セッションタイムアウト(ミリ秒) |
connectionTimeoutMs | int | 任意 | 接続タイムアウト(ミリ秒) |
retryPolicy | RetryPolicy | 必須 | リトライポリシー |
zkClientConfig | ZKClientConfig | 任意 | ZooKeeperクライアント設定 |
builder()を使った柔軟な生成方法
CuratorFramework
の生成には、より詳細な設定を可能にするBuilderパターンも利用できます。
この方法を使うと、接続設定やセキュリティ、名前空間の指定など、さまざまな構成を柔軟にコントロールできます。
try (CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("localhost:2181")
.sessionTimeoutMs(5000)
.connectionTimeoutMs(3000)
.namespace("myapp")
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.build()) {
client.start();
// ZooKeeperとのやり取りをここで実行
}
このように、builder()
を使えば必要なオプションを明示的に設定でき、可読性・保守性にも優れます。
設定メソッド一覧
メソッド | 説明 |
---|---|
aclProvider(ACLProvider) | ACLプロバイダ |
authorization(String, byte[]) | 認証情報(digest 等) |
authorization(List<AuthInfo>) | 複数の認証情報(digest 等) |
canBeReadOnly(boolean) | 読み取り専用モードを許可するか |
compressionProvider(CompressionProvider) | 圧縮プロバイダ |
connectionStateErrorPolicy (ConnectionStateErrorPolicy) | 接続状態エラーポリシー |
connectionStateListenerManagerFactory (ConnectionStateListenerManagerFactory) | 接続状態リスナー管理用ファクトリ |
connectionTimeoutMs(int) | 接続タイムアウト(ミリ秒) |
connectString(String) | 接続先ZooKeeper(カンマ区切りで複数指定可能) |
defaultData(byte[]) | ノード作成時のデフォルトデータ |
dontUseContainerParents() | 親コンテナを作成不可にする |
enableCompression() | 読み書きの際の自動圧縮を有効化 |
ensembleProvider(EnsembleProvider) | アンサンブルプロバイダ |
ensembleTracker(boolean) | アンサンブル構成の変更監視をするか |
maxCloseWaitMs(int) | クローズ時の最大待機時間(ミリ秒) |
namespace(String) | 論理的な名前空間を指定し、すべての操作をその配下に限定 |
retryPolicy(RetryPolicy) | リトライポリシー |
runSafeService(Executor) | WatcherコールバックなどからnotifyAll呼び出しで使用されるエグゼキュータ |
schemaSet(SchemaSet) | 追加する強制スキーマセット |
sessionTimeoutMs(int) | セッションタイムアウト(ミリ秒) |
simulatedSessionExpirationPercent(int) | Curator管理のセッション有効期限(パーセント) |
threadFactory(ThreadFactory) | 内部スレッドの生成方法 |
waitForShutdownTimeoutMs(int) | シャットダウン時のタイムアウト(ミリ秒) |
zkClientConfig(ZKClientConfig) | ZooKeeperクライアント設定 |
zookeeperCompatibility (ZookeeperCompatibility) | ZooKeeperサーバの互換性 |
zookeeperFactory(ZookeeperFactory) | ZooKeeperクライアントのインスタンス生成方法 |
Builderを使うメリット
- 柔軟性が高く、運用環境に応じた構成が可能
- すべての設定を明示的に管理できるため、可読性・保守性に優れる
- セキュリティやパフォーマンスのチューニングにも対応しやすい
開発と本番で構成を切り替えるケースや、セキュリティを考慮した接続が求められる場面では、builder()
による生成が推奨されます。
実運用でのベストプラクティスと注意点
CuratorFramework
を安全かつ効果的に活用するには、いくつかの設計・運用上の工夫が欠かせません。このセクションでは、よくある落とし穴とその対策に加え、実運用でのベストプラクティスをまとめて紹介します。
1. インスタンスはアプリケーション全体で共有する
CuratorFramework
はスレッドセーフな設計ですが、複数インスタンスを生成するとZooKeeper接続が無駄に増え、パフォーマンスや信頼性に悪影響が出ることがあります。
✅ 対策: DIフレームワーク(例:Spring)でシングルトンとして管理し、明示的に再利用される構成にしましょう。
- Springの構成クラスで Bean として定義
- 静的クラスでインスタンスを保持するなどの工夫も有効
2. start()
の呼び忘れに注意
CuratorFramework
は start()
を呼ばないとZooKeeperに接続されません。startを忘れても例外が即座に発生しないため、問題の発見が遅れがちです。
✅ 対策: インスタンス生成後は、必ず start()
を呼ぶことをルール化し、必要に応じてラッパー関数で管理しましょう。
CuratorFramework client = CuratorFrameworkFactory.newClient(...);
client.start(); // ← これを忘れると接続されない
3. close()
の呼び忘れによるリソースリーク
close()
を呼ばずにアプリケーションを終了させると、ZooKeeper側にセッションが残り続け、リソースを圧迫する原因になります。
✅ 対策: try-with-resources
を利用するか、shutdown hook
に明示的に終了処理を登録しましょう。
Runtime.getRuntime().addShutdownHook(new Thread(() -> { client.close(); }));
4. namespace の活用でノードの衝突を回避
ZooKeeperはノードをフラットなパス階層で管理します。複数アプリケーションや環境でクラスタを共有する場合、namespace
を指定しないとノードが競合する可能性があります。
✅ 対策: builder()
で namespace("myapp")
を指定し、すべての操作を独立した仮想パス下に限定しましょう。
/myapp/config
,/myapp/lock
など、用途別に整理可能- テスト・本番で namespace を変えることで環境分離も容易
5. リトライポリシーの誤設定に注意
RetryForever
のような無制限リトライを使うと、障害発生時にZooKeeperへのアクセスが過剰となり、サービス全体に影響を及ぼす可能性があります。
✅ 対策: 通常は ExponentialBackoffRetry
や RetryNTimes
を使い、リトライ回数を制限することを推奨します。
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
6. セッションタイムアウトはZooKeeper設定と整合させる
ZooKeeperサーバ側の tickTime
や minSessionTimeout
に対して、アプリケーション側の sessionTimeoutMs
が短すぎると、頻繁にセッション切れが発生して不安定になります。
✅ 対策: 運用環境に合わせて、セッションタイムアウト値を適切に設定し、切断の再試行を抑えるようにしましょう。
以上のポイントを押さえることで、CuratorFramework を使った ZooKeeper クライアントはより安定かつ安全に動作するようになります。特に、初期化・再接続・終了処理の流れはミスが起こりやすいため、コードパターンとして整備・共有しておくのがおすすめです。
まとめ
CuratorFramework
は、Apache Curator ライブラリの中核を担うクラスであり、ZooKeeper と安定してやり取りを行うための基本インターフェースです。シンプルな初期化から、細かな設定を行う Builder パターンまで、用途に応じた柔軟な生成方法が用意されています。
newClient()
で簡単にインスタンス生成が可能- 詳細な設定を行う場合は、Builder パターン(
builder()
)でインスタンス生成を行う - リトライポリシーやタイムアウト設定は、運用環境に合わせたチューニングが必要
start()
とclose()
のタイミングを誤ると、接続トラブルやリソースリークの原因になる- シングルトン管理や namespace 設定など、実用面での工夫が安定運用に直結
分散システムにおけるZooKeeperの活用では、クライアント側の実装が全体の安定性に大きく影響します。CuratorFramework
を正しく理解し、適切に設定することで、堅牢で保守性の高いシステムを構築できるでしょう。