公式の Java API Client 8.x を使用して、Java から Alibaba Cloud Elasticsearch クラスターに接続します。このガイドでは、Maven の依存関係、基本認証によるクライアントの初期化、およびインデックスを作成、削除、一覧表示する完全な例について説明します。
Java REST クライアントは Elasticsearch 7.17 以降、非推奨になりました。すべての新規開発には Java API クライアントを使用してください。
前提条件
開始する前に、以下が準備できていることを確認してください。
-
JDK 1.8 以降がインストールされていること。詳細については、「JDK のインストール」をご参照ください。
-
バージョン 8.x の Alibaba Cloud Elasticsearch クラスターがあること。詳細については、「Alibaba Cloud Elasticsearch クラスターの作成」をご参照ください。
クラスターのバージョンと一致する Java API クライアントのバージョンを使用してください。たとえば、クラスターのバージョンが 8.17.0 の場合、クライアントのバージョンを
8.17.0に設定します。 -
クラスターで 自動インデックス作成 が有効になっていること。詳細については、「YML ファイルの設定」をご参照ください。自動インデックス作成が有効でない場合、ドキュメントのインデックス作成リクエストはエラーを返します。
-
ネットワークアクセスが設定されていること:
-
インターネットアクセス: クラスターで [パブリックネットワークアクセス] を有効にし、サーバーのパブリック IP アドレスをクラスターのパブリック IP アドレスホワイトリストに追加します。サーバーが NAT (ホームネットワークまたはオフィス LAN) の背後にある場合は、マシンのプライベート IP ではなく、インターネット Egress IP を追加します。「Elasticsearch クラスターのパブリックまたはプライベート IP アドレスホワイトリストを設定する」をご参照ください。
-
VPC アクセス: クラスターの内部エンドポイントを使用します。デフォルトでは、
0.0.0.0/0はすでにプライベート IP アドレスホワイトリストに含まれています。
-
パブリック IP アドレスホワイトリストに 0.0.0.0/0 を追加すると、すべての IPv4 アドレスがクラスターにアクセスできるようになります。この設定を行う前に、セキュリティリスクを評価してください。
Maven 依存関係の追加
以下の依存関係を pom.xml に追加します。8.x を実際のクライアントバージョン (たとえば、バージョン 8.17.0 のクラスターの場合は 8.17.0) に置き換えます。
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.x</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.20.0</version>
</dependency>
Apache Log4j には、既知のリモートコード実行 (RCE) の脆弱性があります。本番環境でこれらのバージョンを使用する前に、「Apache Log4j 2 の RCE 脆弱性」をご参照ください。
クライアントの初期化
Java API クライアントは、次の 3 つのレイヤーで構成されています:
-
HTTP 接続を処理する低レベルの
RestClientです。 -
RestClientTransportは、JacksonJsonpMapperを使用して JSON シリアル化を追加します。 -
型付き API を提供する
ElasticsearchClientです。
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build(); // <1>
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper()); // <2>
ElasticsearchClient elasticsearchClient = new ElasticsearchClient(transport); // <3>
-
低レベルの HTTP クライアントを作成します。
-
Jackson シリアライゼーションを使用してトランスポートレイヤーでラップします。
-
型付き API クライアントを作成します。
Alibaba Cloud Elasticsearch クラスターでは、基本認証が必要です。RestClient をビルドする際に、HttpClientConfigCallback を介して認証情報を渡します:
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("<username>", "<password>")); // <1> 本番環境では認証情報をハードコーディングしないでください。
RestClient restClient = RestClient.builder(
new HttpHost("<ES cluster endpoint>", 9200, "http")) // <2>
.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
.build();
-
ユーザー名とパスワードは、クラスターの作成時に設定した認証情報です。これらは Kibana へのログインにも使用されます。認証情報をハードコーディングする代わりに、環境変数またはシークレットマネージャーを使用してください。
-
Alibaba Cloud コンソールのクラスターの[基本情報]ページから、パブリックまたは内部エンドポイントを取得します。
完全な例
次の例では、基本認証を使用して Alibaba Cloud Elasticsearch クラスターに接続し、書き込みエイリアスを持つインデックスを作成し、結果を検証し、インデックスを削除して、すべてのインデックスを一覧表示します。
<username>、<password>、<ES cluster endpoint>、<index_name>、および <foo> を実際の値に置き換えます。
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.cat.IndicesResponse;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.*;
import java.io.IOException;
public class RestClientTest {
public static void main(String[] args) {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
// 本番環境では認証情報をハードコーディングせず、環境変数またはシークレットマネージャーを使用してください。
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("<username>", "<password>"));
RestClient restClient = RestClient
.builder(new HttpHost("<ES cluster endpoint>", 9200, "http"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
}).build();
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient elasticsearchClient = new ElasticsearchClient(transport);
try {
// 書き込みエイリアスを持つインデックスを作成します。
// isWriteIndex(true) を設定すると、すべての書き込み操作 (インデックス作成、更新、削除) が
// エイリアス経由でこのインデックスにルーティングされます。
CreateIndexResponse indexRequest = elasticsearchClient.indices().create(
b -> b.index("<index_name>")
.aliases("<foo>", a -> a.isWriteIndex(true))
);
boolean acknowledged = indexRequest.acknowledged();
System.out.println("Index created: " + acknowledged);
// インデックスを削除します。
DeleteIndexResponse deleteResponse = elasticsearchClient.indices().delete(
b -> b.index("<index_name>")
);
System.out.println("Index deleted: " + deleteResponse.toString());
// すべてのインデックス (ヘルス、ステータス、インデックス名、UUID、プライマリシャード、レプリカ) を一覧表示します。
IndicesResponse indicesResponse = elasticsearchClient.cat().indices();
indicesResponse.valueBody().forEach(info ->
System.out.println(
info.health() + "\t" + info.status() + "\t" + info.index() + "\t" +
info.uuid() + "\t" + info.pri() + "\t" + info.rep()
)
);
transport.close();
restClient.close();
} catch (IOException e) {
// 接続エラーと API エラーを処理します。
}
}
}
高い同時実行性のためのチューニング
高い同時実行性が求められるワークロードの場合、RestClient の HTTP 接続の最大数を増やしてください。デフォルト値は、本番環境のトラフィックには低すぎます。
httpClientBuilder.setMaxConnTotal(500); // すべてのルートにわたる接続の合計
httpClientBuilder.setMaxConnPerRoute(300); // 単一の ES エンドポイントへの接続
接続プールの設定を含む完全な例:
final int maxConnTotal = 500;
final int maxConnPerRoute = 300;
RestClient restClient = RestClient
.builder(new HttpHost("<ES cluster endpoint>", 9200, "http"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.setMaxConnTotal(maxConnTotal);
httpClientBuilder.setMaxConnPerRoute(maxConnPerRoute);
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
}).build();
トラブルシューティング
「Timeout connecting」エラー
クライアントがクラスターエンドポイントに到達できません。以下を確認してください:
-
パブリックアクセス:クラスターで パブリックネットワークアクセス が有効になっていることを確認してください。
-
ホワイトリスト:サーバーのパブリック IP アドレス (または NAT 環境の場合はインターネット出口 IP) が、クラスターのパブリック IP アドレスホワイトリストに含まれていることを確認してください。
-
エンドポイント:正しいエンドポイントを使用していることを確認してください。インターネット接続にはパブリックエンドポイント、仮想プライベートクラウド (VPC) 接続には内部エンドポイントを使用してください。
ホワイトリストが設定されていない場合、または誤った IP アドレスがホワイトリストに登録されている場合、接続は常にタイムアウトします。
ドキュメント挿入時の自動インデックス作成エラー
ドキュメントをインデックス化しようとして、インデックスが存在しないというエラーが表示された場合は、クラスターで [自動インデックス作成] を有効にしてください。「YML ファイルを設定する」をご参照ください。
Kibana のアクセスに関する問題
Kibana には、クラスター API とは別の IP アドレスホワイトリストがあります。クラスター API にはアクセスできるが Kibana にはアクセスできない場合は、お使いの IP アドレスを Kibana ホワイトリストに追加してください。詳細については、「Kibana のパブリックネットワークまたはプライベートネットワークの設定」をご参照ください。
次のステップ
-
「公式 Java API クライアントドキュメント」で、Java API クライアントの全機能をご確認ください。
-
型付きビルダー API を使用して、インデックスマッピングの管理や検索クエリの実行方法を学習してください。