diff --git a/docs/Architecture.md b/docs/Architecture.md index 4f2b3460787cf..8b5e5519fb390 100644 --- a/docs/Architecture.md +++ b/docs/Architecture.md @@ -290,7 +290,7 @@ public ConsumerConfiguration setReceiverQueueSize(int receiverQueueSize); Creates a Producer (TODO javadocs) with PulsarClient and publish 10 messages. ```java -ProducerConfiguration = config = new ProducerConfiguration(); +ProducerConfiguration config = new ProducerConfiguration(); Producer producer = pulsarClient.createProducer( "persistent://my-property/us-w/my-ns/my-topic", config); // publish 10 messages to the topic diff --git a/docs/Documentation.md b/docs/Documentation.md index 24b285843cfc4..d1bafe46c3aa8 100644 --- a/docs/Documentation.md +++ b/docs/Documentation.md @@ -14,3 +14,5 @@ - [Apache Storm adaptor](PulsarStorm.md) * Internal Docs - [Binary protocol specification](BinaryProtocol.md) +* Other Languages + - [Japanese](locale/ja/Documentation.md) diff --git a/docs/locale/ja/AdminTools.md b/docs/locale/ja/AdminTools.md new file mode 100644 index 0000000000000..97ea6b9b4ef3c --- /dev/null +++ b/docs/locale/ja/AdminTools.md @@ -0,0 +1,2232 @@ + +# Pulsar adminツール + + + +- [Pulsar adminツール](#pulsar-adminツール) + - [Pulsar adminツールとは?](#pulsar-adminツールとは) + - [どのように動作するか?](#どのように動作するか) + - [利用準備](#利用準備) + - [Pulsar admin CLIツール](#pulsar-admin-cliツール) + - [REST API](#rest-api) + - [Java API](#java-api) + - [Pulsarエンティティ](#pulsarエンティティ) + - [Brokers](#brokers) + - [アクティブなBrokerリストの取得](#アクティブなbrokerリストの取得) + - [Brokerが所有するネームスペースリストの取得](#brokerが所有するネームスペースリストの取得) + - [Properties](#properties) + - [存在するプロパティリストの取得](#存在するプロパティリストの取得) + - [プロパティの作成](#プロパティの作成) + - [プロパティの取得](#プロパティの取得) + - [プロパティの更新](#プロパティの更新) + - [プロパティの削除](#プロパティの削除) + - [Clusters](#clusters) + - [クラスタの作成](#クラスタの作成) + - [クラスタの取得](#クラスタの取得) + - [クラスタの更新](#クラスタの更新) + - [クラスタの削除](#クラスタの削除) + - [全クラスタリストの取得](#全クラスタリストの取得) + - [Namespace](#namespace) + - [ネームスペースの作成](#ネームスペースの作成) + - [ネームスペースの取得](#ネームスペースの取得) + - [プロパティ内の全ネームスペースリストの取得](#プロパティ内の全ネームスペースリストの取得) + - [クラスタ内の全ネームスペースリストの取得](#クラスタ内の全ネームスペースリストの取得) + - [ネームスペースの削除](#ネームスペースの削除) + - [パーミッションの付与](#パーミッションの付与) + - [パーミッションの取得](#パーミッションの取得) + - [パーミッションの剥奪](#パーミッションの剥奪) + - [レプリケーションクラスタの設定](#レプリケーションクラスタの設定) + - [レプリケーションクラスタの取得](#レプリケーションクラスタの取得) + - [バックログクォータポリシーの設定](#バックログクォータポリシーの設定) + - [バックログクォータポリシーの取得](#バックログクォータポリシーの取得) + - [バックログクォータポリシーの削除](#バックログクォータポリシーの削除) + - [永続性ポリシーの設定](#永続性ポリシーの設定) + - [永続性ポリシーの取得](#永続性ポリシーの取得) + - [ネームスペースBundleのアンロード](#ネームスペースbundleのアンロード) + - [メッセージTTLの設定](#メッセージttlの設定) + - [メッセージTTLの取得](#メッセージttlの取得) + - [Bundleの分割](#bundleの分割) + - [バックログの削除](#バックログの削除) + - [Bundleバックログの削除](#bundleバックログの削除) + - [リテンションの設定](#リテンションの設定) + - [リテンションの取得](#リテンションの取得) + - [Persistent](#persistent) + - [パーティションドトピックの作成](#パーティションドトピックの作成) + - [パーティションドトピックの取得](#パーティションドトピックの取得) + - [パーティションドトピックの削除](#パーティションドトピックの削除) + - [トピックの削除](#トピックの削除) + - [トピックリストの取得](#トピックリストの取得) + - [パーミッションの付与](#パーミッションの付与) + - [パーミッションの取得](#パーミッションの取得) + - [パーミッションの剥奪](#パーミッションの剥奪) + - [パーティションドトピックの統計情報の取得](#パーティションドトピックの統計情報の取得) + - [統計情報の取得](#統計情報の取得) + - [詳細な統計情報の取得](#詳細な統計情報の取得) + - [メッセージを見る](#メッセージを見る) + - [メッセージのスキップ](#メッセージのスキップ) + - [全メッセージのスキップ](#全メッセージのスキップ) + - [メッセージを有効期限切れにする](#メッセージを有効期限切れにする) + - [全メッセージを有効期限切れにする](#全メッセージを有効期限切れにする) + - [カーソルのリセット](#カーソルのリセット) + - [トピックのルックアップ](#トピックのルックアップ) + - [サブスクリプションリストの取得](#サブスクリプションリストの取得) + - [購読解除](#購読解除) + - [ネームスペースの隔離ポリシー](#ネームスペースの隔離ポリシー) + - [ネームスペースの隔離ポリシーの作成/更新](#ネームスペースの隔離ポリシーの作成更新) + - [ネームスペースの隔離ポリシーの取得](#ネームスペースの隔離ポリシーの取得) + - [ネームスペースの隔離ポリシーの削除](#ネームスペースの隔離ポリシーの削除) + - [ネームスペースの隔離ポリシー全リストの取得](#ネームスペースの隔離ポリシー全リストの取得) + - [リソース割り当て](#リソース割り当て) + - [ネームスペースへのリソース割り当ての設定](#ネームスペースへのリソースの割り当ての設定) + - [ネームスペースへのリソース割り当ての取得](#ネームスペースへのリソースの割り当ての取得) + - [ネームスペースへのリソース割り当てのリセット](#ネームスペースへのリソースの割り当てのリセット) + - [Pulsarクライアントツール](#pulsarクライアントツール) + - [メッセージをproduceするコマンド](#メッセージをproduceするコマンド) + - [メッセージをconsumeするコマンド](#メッセージをconsumeするコマンド) + + + +## Pulsar adminツールとは? + +Pulsar adminツールはコマンドラインユーティリティであり、プロパティ、クラスタ、トピック、ネームスペースなどPulsar Brokerのさまざまなエンティティを設定および監視するための、Brokerと管理の間のインターフェースを提供します。これはプロパティ、クラスタ、ネームスペースを作成できるようにし、アプリケーションをPulsarに載せるのに便利な管理ツールです。またトピックの状態と使用方法を管理する際にも役立ちます。CLI (command line interface) の他に、上述のエンティティを管理および監視するためにREST APIとJava APIの2つの代替手段を使うこともできます。そこでこのドキュメントではCLI, REST API, Java APIを使ってPulsarのエンティティを管理する方法について説明します。 + +### どのように動作するか? + +前述の通り、Pulsar BrokerはPulsarのさまざまなエンティティを設定および管理するためのREST APIを公開しています。Pulsar admin CLIツールはadminコマンドを実行するために、Javaクライアントを使ってこれらのREST APIをコールします。利用可能なREST APIのリストについての詳細は*swaggerドキュメント*から学ぶことができます。 + +## 利用準備 + +### Pulsar admin CLIツール + +Pulsar Brokerが受け取ったリクエストに対して認証認可を行うことが可能である*Pulsarのセキュリティ*機能については他の章で述べました。adminツールはコマンドのリストを実行するためにPulsar BrokerのREST APIを呼びます。しかし、Pulsar Brokerのセキュリティが有効になっている場合、認証されたリクエストを得るためにBrokerのREST APIを呼ぶ際にadminツールは追加の情報を渡す必要があります。そこでこの情報が`conf/client.conf`ファイルにおいて正しく設定されていることを確認してください。 + +これでPulsar admin CLIツールを使う準備が整いました。adminツールの利用を開始するため、下記のコマンドを実行してください。 + +```shell +$ bin/pulsar-admin --help +``` + +前章でPulsarのエンティティを管理するための他の代替手段 - REST APIとJava API - について述べました。このドキュメントではPulsarのエンティティを管理するためのREST APIのエンドポイントとJava APIのスニペットについても説明します。 + +### REST API + +Pulsar admin REST APIの定義については*swaggerドキュメント*から学ぶことができます。このドキュメントでは各APIの利用方法とadmin CLIコマンドがどのようにREST APIに対応するかについて説明します。 + +### Java API + +Java APIは```com.yahoo.pulsar.client.admin.PulsarAdmin```によりアクセスできます。 + +下記のコードスニペットは*PulsarAdmin*の初期化の方法を示しています。後のドキュメントでPulsarのエンティティを管理するための使用方法について説明します。 + + + ```java + URL url = new URL("http://localhost:8080"); + String authPluginClassName = "com.org.MyAuthPluginClass"; //Pass auth-plugin class fully-qualified name if Pulsar-security enabled + String authParams = "param1=value1";//Pass auth-param if auth-plugin class requires it + boolean useTls = false; + boolean tlsAllowInsecureConnection = false; + String tlsTrustCertsFilePath = null; + + ClientConfiguration config = new ClientConfiguration(); + config.setAuthentication(authPluginClassName, authParams); + config.setUseTls(useTls); + config.setTlsAllowInsecureConnection(tlsAllowInsecureConnection); + config.setTlsTrustCertsFilePath(tlsTrustCertsFilePath); + + PulsarAdmin admin = new PulsarAdmin(url, config); + ``` + +### Pulsarエンティティ + +主にadminコマンドラインツールを使って下記のBrokerのエンティティにアクセスします。もしまだ下記のエンティティに対する理解が不十分なのであれば、[Pulsar入門](GettingStarted.md)で詳細を読むことができます。 + +### Brokers + +アクティブなBrokerのリストおよび指定されたBrokerが所有するネームスペースのリストを取得できます。 + +#### アクティブなBrokerリストの取得 +トラフィックを処理している利用可能でアクティブなBrokerを取得します。 + +###### CLI + +``` +$ pulsar-admin brokers list use +``` + +``` +broker1.use.org.com:8080 +``` + +###### REST + +``` +GET /admin/brokers/{cluster} +``` + +###### Java + +```java +admin.brokers().getActiveBrokers(clusterName) +``` + + +#### Brokerが所有するネームスペースリストの取得 + +指定したBrokerが所有し処理しているすべてのネームスペースを取得します。 + +###### CLI + +``` +$ pulsar-admin brokers namespaces --url broker1.use.org.com:8080 use +``` + +```json +{ + "my-property/use/my-ns/0x00000000_0xffffffff": { + "broker_assignment": "shared", + "is_controlled": false, + "is_active": true + } +} +``` +###### REST + +``` +GET /admin/brokers/{cluster}/{broker}/ownedNamespaces +``` + +###### Java + +```java +admin.brokers().getOwnedNamespaces(cluster,brokerUrl) +``` + + +### Properties + +プロパティはアプリケーションのドメインを表します。例えばfinance, mail, sportsなどがプロパティの例です。ツールを使ってPulsarのプロパティを管理するためのCRUD操作を行うことができます。 + +#### 存在するプロパティリストの取得 + +Pulsarシステムに存在しているすべてのプロパティのリストを表示します。 + +###### CLI + +``` +$ pulsar-admin properties list +``` + +``` +my-property +``` + +###### REST + +``` +GET /admin/properties +``` + +###### Java + +```java +admin.properties().getProperties() +``` + + +#### プロパティの作成 + + +Pulsarシステムに新しいプロパティを作成します。プロパティに対し、プロパティの管理権限を持つadminロール(コンマ区切り)とプロパティが利用可能なクラスタ(コンマ区切り)を設定できます。 + +###### CLI + +``` +pulsar-admin properties create my-property --admin-roles admin1,admin2 --allowed-clusters cl1,cl2 +``` + +``` +N/A +``` + +###### REST + +``` +PUT /admin/properties/{property} +``` + +###### Java + +```java +admin.properties().createProperty(property, propertyAdmin) +``` + + +#### プロパティの取得 + +指定した既存プロパティの設定を取得します。 + +###### CLI + +``` +$pulsar-admin properties get my-property +``` + +```json +{ + "adminRoles": [ + "admin1", + "admin2" + ], + "allowedClusters": [ + "cl1", + "cl2" + ] +} +``` + +###### REST + +``` +GET /admin/properties/{property} +``` + +###### Java + +```java +admin.properties().getPropertyAdmin(property) +``` + + + +#### プロパティの更新 + +既に作成されたプロパティの設定を更新します。指定した既存プロパティのadminロールとクラスタの情報を更新できます。 + +###### CLI + +```$ pulsar-admin properties update my-property --admin-roles admin-update-1,admin-update-2 --allowed-clusters cl1,cl2``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/properties/{property} +``` + +###### Java + +```java +admin.properties().updateProperty(property, propertyAdmin) +``` + + +#### プロパティの削除 + +既存プロパティをPulsarシステムから削除します。 +###### CLI + +``` +$ pulsar-admin properties delete my-property +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/properties/{property} +``` + +###### Java + +```java +admin.properties().deleteProperty(property) +``` + + + + +### Clusters + +クラスタは一つ以上の地理的位置においてプロパティとそのネームスペースを利用可能にします。クラスタは一般的にはuse, uswなどの地域のコロケーション名に対応します。ツールを使ってPulsarのクラスタを管理するためのCRUD操作を行うことができます。 + +#### クラスタの作成 + +Pulsarに新しいクラスタを作成します。このようなシステムレベルの操作はスーパーユーザ権限でのみ実行できます。 + +###### CLI + +``` +$ pulsar-admin clusters create --url http://my-cluster.org.com:8080/ --broker-url pulsar://my-cluster.org.com:6650/ cl1 +``` + +``` +N/A +``` + +###### REST + +``` +PUT /admin/clusters/{cluster} +``` + +###### Java + +```java +admin.clusters().createCluster(cluster, new ClusterData(serviceUrl, serviceUrlTls, brokerServiceUrl, brokerServiceUrlTls)) +``` + + + +#### クラスタの取得 + +指定した既存クラスタの設定を取得します。 + +###### CLI + +``` +$ pulsar-admin clusters get cl1 +``` + +```json +{ + "serviceUrl": "http://my-cluster.org.com:8080/", + "serviceUrlTls": null, + "brokerServiceUrl": "pulsar://my-cluster.org.com:6650/", + "brokerServiceUrlTls": null +} +``` + +###### REST + +``` +GET /admin/clusters/{cluster} +``` + +###### Java + +```java +admin.clusters().getCluster(cluster) +``` + + +#### クラスタの更新 + +指定した既存クラスタの設定を更新します。 + +###### CLI + +``` +$ pulsar-admin clusters update --url http://my-cluster.org.com:4081/ --broker-url pulsar://my-cluster.org.com:3350/ cl1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/clusters/{cluster} +``` + +###### Java + +```java +admin.clusters().updateCluster(cluster, new ClusterData(serviceUrl, serviceUrlTls, brokerServiceUrl, brokerServiceUrlTls)) +``` + + +#### クラスタの削除 + +Pulsarシステムから既存クラスタを削除します。 + +###### CLI + +``` +$ pulsar-admin clusters delete cl1 +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/clusters/{cluster} +``` + +###### Java + +```java +admin.clusters().deleteCluster(cluster) +``` + + +#### 全クラスタリストの取得 + +Pulsarシステム内に作成されたすべてのクラスタのリストを取得します。 + +###### CLI + +``` +$ pulsar-admin clusters list +``` + +``` +cl1 +``` + +###### REST + +``` +GET /admin/clusters +``` + +###### Java + +```java +admin.clusters().getClusters() +``` + + +### Namespace + +ネームスペースはプロパティ内の論理的な区切りの名称です。一つのプロパティはそのプロパティの下で異なるアプリケーションを管理するために複数のネームスペースを持つことができます。 + +#### ネームスペースの作成 + +指定した既存クラスタ内のプロパティにネームスペースを作成します。 + +###### CLI + +``` +$ pulsar-admin namespaces create test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +PUT /admin/namespaces/{property}/{cluster}/{namespace} +``` + +###### Java + +```java +admin.namespaces().createNamespace(namespace) +``` + +#### ネームスペースの取得 + +作成済みネームスペースのポリシー情報を取得します。 + +###### CLI + +``` +$pulsar-admin namespaces policies test-property/cl1/ns1 +``` + +```json +{ + "auth_policies": { + "namespace_auth": {}, + "destination_auth": {} + }, + "replication_clusters": [], + "bundles_activated": true, + "bundles": { + "boundaries": [ + "0x00000000", + "0xffffffff" + ], + "numBundles": 1 + }, + "backlog_quota_map": {}, + "persistence": null, + "latency_stats_sample_rate": {}, + "message_ttl_in_seconds": 0, + "retention_policies": null, + "deleted": false +} +``` + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster}/{namespace} +``` + +###### Java + +```java +admin.namespaces().getPolicies(namespace) +``` + + +#### プロパティ内の全ネームスペースリストの取得 + +指定したプロパティ内にあるすべての作成済みネームスペースのリストを取得します。 + +###### CLI + +``` +$ pulsar-admin namespaces list test-property +``` + +``` +test-property/cl1/ns1 +``` + +###### REST + +``` +GET /admin/namespaces/{property} +``` + +###### Java + +```java +admin.namespaces().getNamespaces(property) +``` + + +#### クラスタ内の全ネームスペースリストの取得 + +指定したクラスタのプロパティ内にあるすべての作成済みネームスペースのリストを取得します。 + +###### CLI + +``` +$ pulsar-admin namespaces list-cluster test-property/cl1 +``` + +``` +test-property/cl1/ns1 +``` + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster} +``` + +###### Java + +```java +admin.namespaces().getNamespaces(property, cluster) +``` + +#### ネームスペースの削除 + +既存のネームスペースを削除します。 + +###### CLI + +``` +$ pulsar-admin namespaces delete test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/namespaces/{property}/{cluster}/{namespace} +``` + +###### Java + +```java +admin.namespaces().deleteNamespace(namespace) +``` + +#### パーミッションの付与 + +特定のクライアントロールに対して、produceやconsumeのような必要な操作のリストを許可します。 + +###### CLI + +``` +$ pulsar-admin namespaces grant-permission --actions produce,consume --role admin10 test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/namespaces/{property}/{cluster}/{namespace}/permissions/{role} +``` + +###### Java + +```java +admin.namespaces().grantPermissionOnNamespace(namespace, role, getAuthActions(actions)) +``` + + +#### パーミッションの取得 + +指定したネームスペースに対して作成されたパーミッションルールを表示します。 + +###### CLI + +``` +$ pulsar-admin namespaces permissions test-property/cl1/ns1 +``` + +```json +{ + "admin10": [ + "produce", + "consume" + ] +} +``` + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster}/{namespace}/permissions +``` + +###### Java + +```java +admin.namespaces().getPermissions(namespace) +``` + +#### パーミッションの剥奪 + +特定のクライアントロールのパーミッションを剥奪し、指定したネームスペースにアクセスできないようにします。 + +###### CLI + +``` +$ pulsar-admin namespaces revoke-permission --role admin10 test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/namespaces/{property}/{cluster}/{namespace}/permissions/{role} +``` + +###### Java + +```java +admin.namespaces().revokePermissionsOnNamespace(namespace, role) +``` + + +#### レプリケーションクラスタの設定 + +ネームスペースにレプリケーションクラスタを設定し、Pulsarが内部的に発行されたメッセージを一つのコロケーションから別のコロケーションにレプリケートできるようにします。しかし、レプリケーションクラスタをセットするためにはネームスペースは*test-property/**global**/ns1.*のようにグローバルである必要があります。つまりクラスタ名は*“global”*でなければなりません。 + +###### CLI + +``` +$ pulsar-admin namespaces set-clusters --clusters cl2 test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/namespaces/{property}/{cluster}/{namespace}/replication +``` + +###### Java + +```java +admin.namespaces().setNamespaceReplicationClusters(namespace, clusters) +``` + +#### レプリケーションクラスタの取得 + +指定したネームスペースのレプリケーションクラスタのリストを取得します。 + +###### CLI + +``` +$ pulsar-admin namespaces get-clusters test-property/cl1/ns1 +``` + +``` +cl2 +``` + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster}/{namespace}/replication +``` + +###### Java + +```java +admin.namespaces().getNamespaceReplicationClusters(namespace) +``` + +#### バックログクォータポリシーの設定 + +バックログクォータはBrokerが特定の閾値に達したとき、ネームスペースの帯域幅/ストレージを制限するのに役立ちます。管理者はこの制限と制限に達したときに行う下記のアクションの内一つを設定できます。 + + 1. producer_request_hold: Brokerはproduceリクエストのペイロードをホールドし、永続化しないようになります + + 2. producer_exception: Brokerは例外を発生させてクライアントとの接続を切断します + + 3. consumer_backlog_eviction: Brokerはバックログメッセージの破棄を開始します + + バックログクォータ制限はバックログクォータタイプ: destination_storageを定義することによって考慮されるようになります。 + +###### CLI + +``` +$ pulsar-admin namespaces set-backlog-quota --limit 10 --policy producer_request_hold test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/namespaces/{property}/{cluster}/{namespace}/backlogQuota +``` + +###### Java + +```java +admin.namespaces().setBacklogQuota(namespace, new BacklogQuota(limit, policy)) +``` + +#### バックログクォータポリシーの取得 + +指定したネームスペースのバックログクォータ設定を表示します。 + +###### CLI + +``` +$ pulsar-admin namespaces get-backlog-quotas test-property/cl1/ns1 +``` + +```json +{ + "destination_storage": { + "limit": 10, + "policy": "producer_request_hold" + } +} +``` + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster}/{namespace}/backlogQuotaMap +``` + +###### Java + +```java +admin.namespaces().getBacklogQuotaMap(namespace) +``` + + + + +#### バックログクォータポリシーの削除 + +指定したネームスペースのバックログクォータポリシーを削除します。 + +###### CLI + +``` +$ pulsar-admin namespaces remove-backlog-quota test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/namespaces/{property}/{cluster}/{namespace}/backlogQuota +``` + +###### Java + +```java +admin.namespaces().removeBacklogQuota(namespace, backlogQuotaType) +``` + + +#### 永続性ポリシーの設定 + +永続性ポリシーは指定したネームスペースにあるすべてのトピックの永続性レベルを設定できます。 + + - Bookkeeper-ack-quorum: 各エントリに対して書き込み成功のAckを待機するBookieの数(保証されるコピーの数)、デフォルト: 0 + + - Bookkeeper-ensemble: 一つのトピックに対して使用されるBookieの数、デフォルト: 0 + + - Bookkeeper-write-quorum: 各エントリに対して書き込みを行うBookieの数、デフォルト: 0 + + - Ml-mark-delete-max-rate: mark-delete操作のスロットル率 (0は無制限)、デフォルト: 0.0 + +###### CLI + +``` +$ pulsar-admin namespaces set-persistence --bookkeeper-ack-quorum 2 --bookkeeper-ensemble 3 --bookkeeper-write-quorum 2 --ml-mark-delete-max-rate 0 test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/persistent/{property}/{cluster}/{namespace}/persistence +``` + +###### Java + +```java +admin.namespaces().setPersistence(namespace,new PersistencePolicies(bookkeeperEnsemble, bookkeeperWriteQuorum,bookkeeperAckQuorum,managedLedgerMaxMarkDeleteRate)) +``` + + +#### 永続性ポリシーの取得 + +指定したネームスペースの永続性ポリシーの設定を表示します。 + +###### CLI + +``` +$ pulsar-admin namespaces get-persistence test-property/cl1/ns1 +``` + +```json +{ + "bookkeeperEnsemble": 3, + "bookkeeperWriteQuorum": 2, + "bookkeeperAckQuorum": 2, + "managedLedgerMaxMarkDeleteRate": 0 +} +``` + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster}/{namespace}/persistence +``` + +###### Java + +```java +admin.namespaces().getPersistence(namespace) +``` + + +#### ネームスペースBundleのアンロード + +ネームスペースBundleは同じネームスペースに属するトピックの仮想的なグループです。多数のBundleによりBrokerの負荷が高まった場合、このコマンドを使って処理が重いBundleをそのBrokerから取り外し、より負荷が小さい他のBrokerに扱わせることができます。ネームスペースBundleは0x00000000と0xffffffffのように開始と終了のレンジによって定義されます。 + +###### CLI + +``` +$ pulsar-admin namespaces unload --bundle 0x00000000_0xffffffff test-property/pstg-gq1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +PUT /admin/namespaces/{property}/{cluster}/{namespace}/unload +``` + +###### Java + +```java +admin.namespaces().unloadNamespaceBundle(namespace, bundle) +``` + + +#### メッセージTTLの設定 + +メッセージの生存時間(秒)を設定します。 + +###### CLI + +``` +$ pulsar-admin namespaces set-message-ttl --messageTTL 100 test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/namespaces/{property}/{cluster}/{namespace}/messageTTL +``` + +###### Java + +```java +admin.namespaces().setNamespaceMessageTTL(namespace, messageTTL) +``` + +#### メッセージTTLの取得 + +ネームスペースに対して設定されたメッセージTTLを取得します。 + +###### CLI + +``` +$ pulsar-admin namespaces get-message-ttl test-property/cl1/ns1 +``` + +``` +100 +``` + + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster}/{namespace}/messageTTL +``` + +###### Java + +```java +admin.namespaces().getNamespaceReplicationClusters(namespace) +``` + + +#### Bundleの分割 + +各ネームスペースのBundleは複数のトピックを含み、各Bundleはただ一つのBrokerによって扱われます。Bundleがそれに含まれる複数のトピックの処理で重くなった場合、Brokerに対し負荷を発生させます。これを解決するため、管理者はこのコマンドを用いてBundleを分割できます。 + +###### CLI + +``` +$ pulsar-admin namespaces split-bundle --bundle 0x00000000_0xffffffff test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +PUT /admin/namespaces/{property}/{cluster}/{namespace}/{bundle}/split +``` + +###### Java + +```java +admin.namespaces().splitNamespaceBundle(namespace, bundle) +``` + + +#### バックログの削除 + +指定したネームスペースに属するすべてのトピックのすべてのメッセージバックログを削除します。特定のサブスクリプションのバックログのみを削除することも可能です。 + +###### CLI + +``` +$ pulsar-admin namespaces clear-backlog --sub my-subscription test-property/pstg-gq1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/namespaces/{property}/{cluster}/{namespace}/clearBacklog +``` + +###### Java + +```java +admin.namespaces().clearNamespaceBacklogForSubscription(namespace, subscription) +``` + + +#### Bundleバックログの削除 + +特定のネームスペースBundleに属するすべてのトピックのすべてのメッセージバックログを削除します。特定のサブスクリプションのバックログのみを削除することも可能です。 + +###### CLI + +``` +$ pulsar-admin namespaces clear-backlog --bundle 0x00000000_0xffffffff --sub my-subscription test-property/pstg-gq1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/namespaces/{property}/{cluster}/{namespace}/{bundle}/clearBacklog +``` + +###### Java + +```java +admin.namespaces().clearNamespaceBundleBacklogForSubscription(namespace, bundle, subscription) +``` + + +#### リテンションの設定 + +各ネームスペースは複数のトピックを含み、各トピックのリテンションサイズ(ストレージサイズ)は特定の閾値を超えるべきではなく、特定の期間まで保持されるべきです。このコマンドを使って、指定したネームスペース内のトピックのリテンションサイズと時間を設定できます。 + +###### CLI + +``` +$ pulsar-admin set-retention --size 10 --time 100 test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/namespaces/{property}/{cluster}/{namespace}/retention +``` + +###### Java + +```java +admin.namespaces().setRetention(namespace, new RetentionPolicies(retentionTimeInMin, retentionSizeInMB)) +``` + + +#### リテンションの取得 + +指定したネームスペースのリテンション情報を表示します。 + +###### CLI + +``` +$ pulsar-admin namespaces get-retention test-property/cl1/ns1 +``` + +```json +{ + "retentionTimeInMinutes": 10, + "retentionSizeInMB": 100 +} +``` + +###### REST + +``` +GET /admin/namespaces/{property}/{cluster}/{namespace}/retention +``` + +###### Java + +```java +admin.namespaces().getRetention(namespace) +``` + + + +### Persistent + +persistentコマンドは、メッセージをproduce/consumeするための論理的なエンドポイントであるトピックにアクセスする際に役立ちます。 +Producerはトピックにメッセージをproduceし、Consumerはトピックにproduceされたメッセージをconsumeするためにトピックを購読します。 + +以降に説明とコマンドを記載します - パーシステントトピックのフォーマットは次の通りです: + +```persistent:// ``` + +#### パーティションドトピックの作成 + + +指定されたネームスペース下にパーティションドトピックを作成します。作成のためには、パーティション数は1より大きくなくてはいけません。 + + +###### CLI + + +``` +$ pulsar-admin persistent create-partitioned-topic --partitions 2 persistent://test-property/cl1/ns1/pt1 +``` + +``` +N/A +``` + +###### REST + +``` +PUT /admin/persistent/{property}/{cluster}/{namespace}/{destination}/partitions +``` + +###### Java + +```java +admin.persistentTopics().createPartitionedTopic(persistentTopic, numPartitions) +``` + +#### パーティションドトピックの取得 + +作成されたパーティションドトピックのメタデータを提供します。 + +###### CLI + +``` +$ pulsar-admin persistent get-partitioned-topic-metadata persistent://test-property/cl1/ns1/pt1 +``` + +```json +{ + "partitions": 2 +} +``` + +###### REST + +``` +GET /admin/persistent/{property}/{cluster}/{namespace}/{destination}/partitions +``` + +###### Java + +```java +admin.persistentTopics().getPartitionedTopicMetadata(persistentTopic) +``` + + +#### パーティションドトピックの削除 + +作成されたパーティションドトピックを削除します。 + +###### CLI + +``` +$ pulsar-admin persistent delete-partitioned-topic persistent://test-property/cl1/ns1/pt1 +``` + +``` +N/A +``` + +###### REST +``` +DELETE /admin/persistent/{property}/{cluster}/{namespace}/{destination}/partitions +``` + +###### Java + +```java +admin.persistentTopics().deletePartitionedTopic(persistentTopic) +``` + + +#### トピックの削除 + +トピックを削除します。ただしアクティブなサブスクリプションまたはProducerの接続がある場合には、トピックを削除できません。 + +###### CLI + +``` +pulsar-admin persistent delete persistent://test-property/cl1/ns1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/persistent/{property}/{cluster}/{namespace}/{destination} +``` + +###### Java + +```java +admin.persistentTopics().delete(persistentTopic) +``` + + +#### トピックリストの取得 + +指定されたネームスペース下に存在するパーシステントトピックのリストを提供します。 + +###### CLI + +``` +$ pulsar-admin persistent list test-property/cl1/ns1 +``` + +``` +my-topic +``` + +###### REST + +``` +GET /admin/persistent/{property}/{cluster}/{namespace} +``` + +###### Java + +```java +admin.persistentTopics().getList(namespace) +``` + +#### パーミッションの付与 + +指定されたトピックに対して特定のアクションを実行するためのパーミッションをクライアントロールに付与します。 + +###### CLI + +``` +$ pulsar-admin persistent grant-permission --actions produce,consume --role application1 persistent://test-property/cl1/ns1/tp1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/persistent/{property}/{cluster}/{namespace}/{destination}/permissions/{role} +``` + +###### Java + +```java +admin.persistentTopics().grantPermission(destination, role, getAuthActions(actions)) +``` + +#### パーミッションの取得 + +指定されたトピックに対してのクライアントロールのパーミッションのリストを表示します。 + +###### CLI + +``` +$ pulsar-admin permissions persistent://test-property/cl1/ns1/tp1 +``` + +```json +{ + "application1": [ + "consume", + "produce" + ] +} +``` + +###### REST + +``` +GET /admin/persistent/{property}/{cluster}/{namespace}/{destination}/permissions +``` + +###### Java + +```java +admin.persistentTopics().getPermissions(destination) +``` + +#### パーミッションの剥奪 + +クライアントロールに対して付与されたパーミッションを剥奪します。 + +###### CLI + +``` +$ pulsar-admin persistent revoke-permission --role application1 persistent://test-property/cl1/ns1/tp1 +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/persistent/{property}/{cluster}/{namespace}/{destination}/permissions/{role} +``` + +###### Java + +```java +admin.persistentTopics().revokePermissions(destination, role) +``` + +#### パーティションドトピックの統計情報の取得 + +パーティションドトピックの現在の統計情報を表示します。 + +###### CLI + +``` +$ pulsar-admin persistent partitioned-stats --per-partition persistent://test-property/cl1/ns1/tp1 +``` + +```json +{ + "msgRateIn": 4641.528542257553, + "msgThroughputIn": 44663039.74947473, + "msgRateOut": 0, + "msgThroughputOut": 0, + "averageMsgSize": 1232439.816728665, + "storageSize": 135532389160, + "publishers": [ + { + "msgRateIn": 57.855383881403576, + "msgThroughputIn": 558994.7078932219, + "averageMsgSize": 613135, + "producerId": 0, + "producerName": null, + "address": null, + "connectedSince": null + } + ], + "subscriptions": { + "my-topic_subscription": { + "msgRateOut": 0, + "msgThroughputOut": 0, + "msgBacklog": 116632, + "type": null, + "msgRateExpired": 36.98245516804671, + "consumers": [] + } + }, + "replication": {} +} +``` + +###### REST + +``` +GET /admin/persistent/{property}/{cluster}/{namespace}/{destination}/partitioned-stats +``` + +###### Java + +```java +admin.persistentTopics().getPartitionedStats(persistentTopic, perPartition) +``` + + +#### 統計情報の取得 + +パーティションドトピックではないトピックの現在の統計情報を表示します。 + + - **msgRateIn**: 全てのローカルとレプリケーション用のPublisherの発行レートの合計で、1秒あたりのメッセージ数です。 + + - **msgThroughputIn**: 上記と同様ですが、1秒あたりのバイト数です。 + + - **msgRateOut**: 全てのローカルとレプリケーション用のConsumerへの配送レートの合計で、1秒あたりのメッセージ数です。 + + - **msgThroughputOut**: 上記と同様ですが、1秒あたりのバイト数です。 + + - **averageMsgSize**: 直近のインターバル内で発行されたメッセージの平均バイトサイズです。 + + - **storageSize**: このトピックのLedgerのストレージサイズの合計です。 + + - **publishers**: トピック内の全てのローカルPublisherの一覧です。0または何千もの可能性があります。 + + - **averageMsgSize**: 直近のインターバル内でこのPublisherからのメッセージの平均バイトサイズです。 + + - **producerId**: このトピック上での、このProducerの内部的な識別子です。 + + - **producerName**: クライアントライブラリによって生成されたこのProducerの内部的な識別子です。 + + - **address**: このProducerの接続用のIPアドレスと送信元ポートです。 + + - **connectedSince**: このProducerが作成または最後に再接続したタイムスタンプです。 + + - **subscriptions**: トピックに対してのローカルの全サブスクリプションリストです。 + + - **my-subscription**: このサブスクリプションの名前です (クライアントが定義します) 。 + + - **msgBacklog**: このサブスクリプションのバックログ内のメッセージ数です。 + + - **type**: このサブスクリプションのタイプです。 + + - **msgRateExpired**: TTLのためにこのサブスクリプションから配送されずに破棄されたメッセージのレートです。 + + - **consumers**: このサブスクリプションに接続しているConsumerリストです。 + + - **consumerName**: クライアントライブラリによって生成されたこのConsumerの内部的な識別子です。 + + - **availablePermits**: このConsumerがクライアントライブラリのlistenキューに格納できるメッセージ数です。0はクライアントライブラリのキューがいっぱいであり、receive()はコールされないことを意味します。0でない場合には、このConsumerはメッセージを配送される準備ができています。 + + - **replication**: このセクションは、トピックのクラスタ間でのレプリケーションの統計情報を示します。 + + - **replicationBacklog**: レプリケーション先のバックログに送信されるメッセージです。 + + - **connected**: 送信レプリケータが接続されているかどうかです。 + + - **replicationDelayInSeconds**: connectedがtrueの場合で、最も古いメッセージが送信されるのを待っている時間です。 + + - **inboundConnection**: このBrokerに対しての、リモートクラスタのPublisher接続におけるそのBrokerのIPとポートです。 + + - **inboundConnectedSince**: リモートクラスタにメッセージを発行するためにTCP接続が使われます。もし接続しているローカルのPublisherがいない場合には、この接続は数分後に自動的に閉じられます。 +###### CLI + +``` +$ pulsar-admin persistent stats persistent://test-property/cl1/ns1/tp1 +``` + +```json +{ + "msgRateIn": 0, + "msgThroughputIn": 0, + "msgRateOut": 0, + "msgThroughputOut": 0, + "averageMsgSize": 0, + "storageSize": 11814, + "publishers": [ + { + "msgRateIn": 0, + "msgThroughputIn": 0, + "averageMsgSize": 0, + "producerId": 0, + "producerName": "gq1-54-4001", + "address": "/10.215.138.238:44458", + "connectedSince": "2016-06-16 22:56:56.509" + } + ], + "subscriptions": { + "my-subscription": { + "msgRateOut": 0, + "msgThroughputOut": 0, + "msgBacklog": 17, + "type": "Shared", + "msgRateExpired": 2.1771406267194497, + "consumers": [ + { + "msgRateOut": 0, + "msgThroughputOut": 0, + "consumerName": "a67f7", + "availablePermits": 1186, + "address": "/10.215.166.121:35095", + "connectedSince": "2016-06-25 00:05:58.312" + } + ] + } + }, + "replication": {} +} +``` + +###### REST +``` +GET /admin/persistent/{property}/{cluster}/{namespace}/{destination}/stats +``` + +###### Java + +```java +admin.persistentTopics().getStats(persistentTopic) +``` + +#### 詳細な統計情報の取得 + +トピックの詳細な統計情報を表示します。 + + - **entriesAddedCounter**: このBrokerがこのトピックを読み込んでから発行されたメッセージ数です。 + + - **numberOfEntries**: 書き込まれたメッセージの総数です。 + + - **totalSize**: 全メッセージのバイト単位での合計ストレージサイズです。 + + - **currentLedgerEntries**: 現在openしているLedgerに書き込まれたメッセージ数です。 + + - **currentLedgerSize**: 現在openしているLedgerに書き込まれたメッセージのバイトサイズです。 + + - **lastLedgerCreatedTimestamp**: 最後のLedgerが作成された時刻です。 + + - **lastLedgerCreationFailureTimestamp:** 最後のLedgerに障害が発生した時刻です。 + + - **waitingCursorsCount**:"キャッチアップ状態"で新しいメッセージが発行されるのを待っているカーソル数です。 + + - **pendingAddEntriesCount**: 完了を待っている (非同期) 書き込みリクエストのメッセージ数です。 + + - **lastConfirmedEntry**: 書き込みに成功した最後のメッセージのledgerid:entryid。entryidが−1の場合、Ledgerがすでにオープンされているか現在オープンされていますが、まだ書き込まれたエントリがないことを意味します。 + + - **state**: このLedgerの書き込みのための状態です。LedgerOpenedは、発行されたメッセージを保存するためのLedgerをオープンしていることを意味します。 + + - **ledgers**: このトピックのメッセージを保持している全てのLedgerの順序付きリストです。 + + - **cursors**: このトピック上の全てのカーソルのリストです。トピックの統計情報上に表示されたサブスクリプションごとに1つ表示されます。 + + - **markDeletePosition**: Ackのポジション:SubscriberからAckが返された最後のメッセージです。 + + - **readPosition**: メッセージを読むためのSubscriberの最新のポジションです。 + + - **waitingReadOp**: サブスクリプションが最新のメッセージを読み込み、新しいメッセージが発行されるのを待っている時に、これはtrueになります。 + + - **pendingReadOps**: 進行中のBookKeeperへの未解決の読み取りリクエスト数です。 + + - **messagesConsumedCounter**: このBrokerがこのトピックを読み込んでからこのカーソルがAckしたメッセージ数です。 + + - **cursorLedger**: 永続的に現在のmarkDeletePositionを保存するために利用されているLedgerです。 + + - **cursorLedgerLastEntry**: 永続的に現在のmarkDeletePositionを保存するために使われた最後のentryidです。 + + - **individuallyDeletedMessages**: もしAckが順不同で行われている場合に、markDeletePositionと読み込みポジションの間でAckされたメッセージの範囲を表示します。 + + - **lastLedgerSwitchTimestamp**: カーソルLedgerがロールオーバされた最後の時刻です。 + + - **state**: カーソルLedgerの状態: Openは、markDeletePositionのアップデートを保存するためのカーソルLedgerが存在することを意味します。 + +###### CLI + +``` +$ pulsar-admin persistent stats-internal persistent://test-property/cl1/ns1/tp1 +``` + +```json +{ + "entriesAddedCounter": 20449518, + "numberOfEntries": 3233, + "totalSize": 331482, + "currentLedgerEntries": 3233, + "currentLedgerSize": 331482, + "lastLedgerCreatedTimestamp": "2016-06-29 03:00:23.825", + "lastLedgerCreationFailureTimestamp": null, + "waitingCursorsCount": 1, + "pendingAddEntriesCount": 0, + "lastConfirmedEntry": "324711539:3232", + "state": "LedgerOpened", + "ledgers": [ + { + "ledgerId": 324711539, + "entries": 0, + "size": 0 + } + ], + "cursors": { + "my-subscription": { + "markDeletePosition": "324711539:3133", + "readPosition": "324711539:3233", + "waitingReadOp": true, + "pendingReadOps": 0, + "messagesConsumedCounter": 20449501, + "cursorLedger": 324702104, + "cursorLedgerLastEntry": 21, + "individuallyDeletedMessages": "[(324711539:3134‥324711539:3136], (324711539:3137‥324711539:3140], ]", + "lastLedgerSwitchTimestamp": "2016-06-29 01:30:19.313", + "state": "Open" + } + } +} +``` + + +###### REST + +``` +GET /admin/persistent/{property}/{cluster}/{namespace}/{destination}/internalStats +``` + +###### Java + +```java +admin.persistentTopics().getInternalStats(persistentTopic) +``` + + +#### メッセージを見る + +指定されたトピックの特定のサブスクリプションのNつのメッセージを覗き見ます。 + +###### CLI + +``` +$ pulsar-admin persistent peek-messages --count 10 --subscription my-subscription persistent://test-property/cl1/ns1/my-topic +``` + +``` +Message ID: 315674752:0 +Properties: { "X-Pulsar-publish-time" : "2015-07-13 17:40:28.451" } +msg-payload +``` + +###### REST + +``` +GET /admin/persistent/{property}/{cluster}/{namespace}/{destination}/subscription/{subName}/position/{messagePosition} +``` + + +###### Java + +```java +admin.persistentTopics().peekMessages(persistentTopic, subName, numMessages) +``` + + +#### メッセージのスキップ + +指定されたトピックの指定されたサブスクリプションのNつのメッセージをスキップします。 + +###### CLI + +``` +$ pulsar-admin persistent skip --count 10 --subscription my-subscription persistent://test-property/cl1/ns1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/persistent/{property}/{cluster}/{namespace}/{destination}/subscription/{subName}/skip/{numMessages} +``` + +###### Java + +```java +admin.persistentTopics().skipMessages(persistentTopic, subName, numMessages) +``` + +#### 全メッセージのスキップ + +指定されたトピックの特定のサブスクリプションの全ての古いメッセージをスキップします。 + +###### CLI + +``` +$ pulsar-admin persistent skip-all --subscription my-subscription persistent://test-property/cl1/ns1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/persistent/{property}/{cluster}/{namespace}/{destination}/subscription/{subName}/skip_all +``` + +###### Java + +```java +admin.persistentTopics().skipAllMessages(persistentTopic, subName) +``` + +#### メッセージを有効期限切れにする + +指定された有効期限 (秒単位) よりも古い、指定されたトピック上の特定のサブスクリプションのメッセージを有効期限切れにします。 + +###### CLI + +``` +$ pulsar-admin persistent expire-messages --subscription my-subscription --expireTime 120 persistent://test-property/cl1/ns1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/persistent/{property}/{cluster}/{namespace}/{destination}/subscription/{subName}/expireMessages/{expireTimeInSeconds} +``` + +###### Java + +```java +admin.persistentTopics().expireMessages(persistentTopic, subName, expireTimeInSeconds) +``` + +#### 全メッセージを有効期限切れにする + +指定された有効期限 (秒単位) よりも古い、トピック上の全てのサブスクリプションのメッセージを有効期限切れにします。 + +###### CLI + +``` +$ pulsar-admin persistent expire-messages-all-subscriptions --expireTime 120 persistent://test-property/cl1/ns1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/persistent/{property}/{cluster}/{namespace}/{destination}/all_subscription/expireMessages/{expireTimeInSeconds} +``` + +###### Java + +```java +admin.persistentTopics().expireMessagesForAllSubscriptions(persistentTopic, expireTimeInSeconds) +``` + + + +#### カーソルのリセット + +サブスクリプションのカーソル位置をX分前に記録された位置まで戻します。 +これは、X分前の時間とカーソル位置を計算し、その位置にリセットします。 + +###### CLI + +``` +$ pulsar-admin persistent reset-cursor --subscription my-subscription --time 10 persistent://test-property/pstg-gq1/ns1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/persistent/{property}/{cluster}/{namespace}/{destination}/subscription/{subName}/resetcursor/{timestamp} +``` + +###### Java + +```java +admin.persistentTopics().resetCursor(persistentTopic, subName, timestamp) +``` + + +#### トピックのルックアップ + +指定されたトピックに対応しているBrokerのurlを探します。 + +###### CLI + +``` +$ pulsar-admin persistent lookup persistent://test-property/pstg-gq1/ns1/my-topic +``` + +``` +"pulsar://broker1.org.com:4480" +``` + +###### REST +``` +GET http://:/lookup/v2/destination/persistent/{property}/{cluster}/{namespace}/{dest} +(\* this api serves by “lookup” resource and not “persistent”) +``` + +###### Java + +```java +admin.lookups().lookupDestination(destination) +``` + +#### サブスクリプションリストの取得 + +指定されたトピックの全てのサブスクリプション名を表示します。 + +###### CLI + +``` +$ pulsar-admin persistent subscriptions persistent://test-property/pstg-gq1/ns1/my-topic +``` + +``` +my-subscription +``` + +###### REST + +``` +GET /admin/persistent/{property}/{cluster}/{namespace}/{destination}/subscriptions +``` + +###### Java + +```java +admin.persistentTopics().getSubscriptions(persistentTopic) +``` + +#### 購読解除 + +これ以上メッセージを処理しないサブスクリプションを購読解除する際にも役立ちます。 + +###### CLI + +``` +$pulsar-admin persistent unsubscribe --subscription my-subscription persistent://test-property/pstg-gq1/ns1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/persistent/{property}/{cluster}/{namespace}/{destination}/subscription/{subName} +``` + +###### Java + +```java +admin.persistentTopics().deleteSubscription(persistentTopic, subName) +``` + +### ネームスペースの隔離ポリシー + +#### ネームスペースの隔離ポリシーの作成/更新 + +ネームスペースの隔離ポリシーを作成します。 + + - auto-failover-policy-params: 自動フェイルオーバーポリシーのパラメータで、カンマ区切りでname=value形式で指定します。 + + - auto-failover-policy-type: 自動フェイルオーバーポリシーのタイプ名です。 + + - namespaces: カンマ区切りのネームスペースの正規表現リストです。 + + - primary: カンマ区切りのプライマリBrokerの正規表現リストです。 + + - secondary: カンマ区切りのセカンダリBrokerの正規表現リストです。 + +###### CLI + +``` +$ pulsar-admin ns-isolation-policy --auto-failover-policy-params min_limit=0 --auto-failover-policy-type min_available --namespaces test-property/cl1/ns.*|test-property/cl1/test-ns*.* --secondary broker2.* --primary broker1.* cl1 ns-is-policy1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/clusters/{cluster}/namespaceIsolationPolicies/{policyName} +``` + +###### Java +```java +admin.clusters().createNamespaceIsolationPolicy(clusterName, policyName, namespaceIsolationData); +``` + + +#### ネームスペースの隔離ポリシーの取得 + +ネームスペースの隔離ポリシーを表示します。 + +###### CLI + +``` +$ pulsar-admin ns-isolation-policy get cl1 ns-is-policy1 +``` + +```json +{ + "namespaces": [ + "test-property/cl1/ns.*|test-property/cl1/test-ns*.*" + ], + "primary": [ + "broker1.*" + ], + "secondary": [ + "broker2.*" + ], + "auto_failover_policy": { + "policy_type": "min_available", + "parameters": { + "min_limit": "0" + } + } +} +``` + +###### REST +``` +GET /admin/clusters/{cluster}/namespaceIsolationPolicies/{policyName} +``` + +###### Java + +```java +admin.clusters().getNamespaceIsolationPolicy(clusterName, policyName) +``` + + +#### ネームスペースの隔離ポリシーの削除 + +ネームスペースの隔離ポリシーを削除します。 + +###### CLI + +``` +$ pulsar-admin ns-isolation-policy delete ns-is-policy1 +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/clusters/{cluster}/namespaceIsolationPolicies/{policyName} +``` + +###### Java + +```java +admin.clusters().deleteNamespaceIsolationPolicy(clusterName, policyName) +``` + + +#### ネームスペースの隔離ポリシー全リストの取得 + +指定されたクラスタによって提供されているネームスペースの隔離ポリシーの全リストを表示します。 + +###### CLI + +``` +$ pulsar-admin ns-isolation-policy list cl1 +``` + +```json +{ + "ns-is-policy1": { + "namespaces": [ + "test-property/cl1/ns.*|test-property/cl1/test-ns*.*" + ], + "primary": [ + "broker1.*" + ], + "secondary": [ + "broker2.*" + ], + "auto_failover_policy": { + "policy_type": "min_available", + "parameters": { + "min_limit": "0" + } + } + } +} +``` + +###### REST +``` +GET /admin/clusters/{cluster}/namespaceIsolationPolicies +``` + +###### Java + +```java +admin.clusters().getNamespaceIsolationPolicies(clusterName) +``` + + +### リソース割り当て + +#### ネームスペースへのリソース割り当ての設定 + +指定されたネームスペースBundleに対して独自の割り当て情報をセットします。 + +###### CLI + +``` +$ pulsar-admin resource-quotas set --bandwidthIn 10 --bandwidthOut 10 --bundle 0x00000000_0xffffffff --memory 10 --msgRateIn 10 --msgRateOut 10 --namespace test-property/cl1/ns1 +``` + +``` +N/A +``` + +###### REST + +``` +POST /admin/resource-quotas/{property}/{cluster}/{namespace}/{bundle} +``` + +###### Java + +```java +admin.resourceQuotas().setNamespaceBundleResourceQuota(namespace, bundle, quota) +``` + +#### ネームスペースへのリソース割り当ての取得 + +リソース割り当ての情報を表示します。 + +###### CLI + +``` +$ pulsar-admin resource-quotas get --bundle 0x00000000_0xffffffff --namespace test-property/cl1/my-topic +``` + +```json +{ + "msgRateIn": 80.40352101165782, + "msgRateOut": 132.58187392933146, + "bandwidthIn": 144273.8819600397, + "bandwidthOut": 234497.9190227951, + "memory": 199.91739142481595, + "dynamic": true +} +``` + +###### REST +``` +GET /admin/resource-quotas/{property}/{cluster}/{namespace}/{bundle} +``` + +###### Java + +```java +admin.resourceQuotas().getNamespaceBundleResourceQuota(namespace, bundle) +``` + +#### ネームスペースへのリソース割り当てのリセット + +独自のリソース割り当てをデフォルトの設定に戻します。 + +###### CLI + +``` +$ pulsar-admin resource-quotas reset-namespace-bundle-quota --bundle 0x00000000_0xffffffff --namespace test-property/cl1/my-topic +``` + +``` +N/A +``` + +###### REST + +``` +DELETE /admin/resource-quotas/{property}/{cluster}/{namespace}/{bundle} +``` + +###### Java + +```java +admin.resourceQuotas().resetNamespaceBundleResourceQuota(namespace, bundle) +``` + + +Pulsarの付加的なツール +--- + +### Pulsarクライアントツール + +Pulsarは任意のトピック上でメッセージのproduceとconsumeを行うためのJavaのAPIを提供しています。 +しかし、Pulsarではトピック上でのメッセージのproduceとconsumeに役立つCLIユーティリティも提供しています。 + +ターミナル上で次のディレクトリに移動して、クライアントツールを試してみてください。 + +```$ $PULSAR_HOME/bin``` + +```$ ./pulsar-client --help``` + +#### メッセージをproduceするコマンド + + + + + + + + + + + + + + + + + + + + + + + + + +
```pulsar-client produce```
オプション説明
```-f, --files``````送信するファイルのパスをコンマ区切りで指定。-mと一緒に使用する事はできません。-fか-mのどちらかは指定しなければなりません```
```-m, --messages``````送信するメッセージの文字列をコンマ区切りで指定。-fと一緒に使用する事はできません。-mか-fのどちらかは指定しなければなりません```
```-n, --num-produce``````メッセージを送信する回数 (デフォルト:1) ```
```-r, --rate``````メッセージをproduceするレート (メッセージ/秒) 。0の場合、メッセージは可能な限り速くproduceされます (デフォルト:0.0) ```
+ +#### メッセージをconsumeするコマンド +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
```pulsar-client consume```
オプション説明
```--hex``````バイナリメッセージを16進数で表示 (デフォルト:false) ```
```-n, --num-messages``````consumeするメッセージの数 (デフォルト:1) ```
```-r, --rate``````メッセージをconsumeするレート (メッセージ/秒) 。0の場合、メッセージは可能な限り速くconsumeされます (デフォルト:0.0) ```
```-s, --subscription-name``````サブスクリプション名```
```-t, --subscription-type``````Exclusive, Shared, Failoverの内どれか1つのサブスクリプションタイプ (デフォルト:Exclusive) ```
diff --git a/docs/locale/ja/Architecture.md b/docs/locale/ja/Architecture.md new file mode 100644 index 0000000000000..51962a1aeb543 --- /dev/null +++ b/docs/locale/ja/Architecture.md @@ -0,0 +1,353 @@ + +# システム概要 + + + +- [システム概要](#システム概要) + - [アーキテクチャ](#アーキテクチャ) + - [メッセージBroker](#メッセージbroker) + - [永続ストア](#永続ストア) + - [Managed Ledger](#managed-ledger) + - [メタデータストア](#メタデータストア) + - [デザイン](#デザイン) + - [トピック](#トピック) + - [サブスクリプション](#サブスクリプション) + - [サブスクリプションモード](#サブスクリプションモード) + - [プロパティとネームスペース](#プロパティとネームスペース) + - [Producer](#producer) + - [Consumer](#consumer) + - [パーティションドトピック](#パーティションドトピック) + - [永続性](#永続性) + - [レプリケーション](#レプリケーション) + - [認証と認可](#認証と認可) +- [クライアントライブラリ](#クライアントライブラリ) + - [クライアントのセットアップフェイズ](#クライアントのセットアップフェイズ) + - [PulsarClient](#pulsarclient) + - [Consumer API](#consumer-api) + - [Producer API](#producer-api) + + + +Pulsarはマルチテナントで、ハイパフォーマンスなサーバ間メッセージングのソリューションです。 +主な特徴は: + +- シンプルなAPIによるJavaバインディング +- 複数のサブスクリプションモード: pub/sub、ロードバランサ、フェイルオーバー +- シームレスなメッセージのジオレプリケーション +- 発行、end-to-endでの低レイテンシ +- 永続メッセージングによるメッセージ配信保証; 永続ストレージは複数ホスト間での複数コピーが設定可能な構成 + +## アーキテクチャ + +上位レベルでは、Pulsarインスタンスは単一または複数クラスタで構成され、それぞれのクラスタは異なる地理的地域に存在する可能性があります。 +1つのPulsarクラスタはメッセージBroker, BookKeeperおよび (コンポーネント間の) 連携と構成管理のためのZooKeeperアンサンブルで構成されています。 +そしてクライアントライブラリが使い勝手の良いAPIを提供します。 + +![アーキテクチャ図](../../img/pulsar_system_architecture.png) + + +### メッセージBroker + +PulsarのBrokerはステートレスなコンポーネントで、主に2つの異なるコンポーネントを実行します: +トピックのルックアップと管理操作のためのRESTインターフェースを提供するHTTPサーバと、全てのデータ転送を独自バイナリプロトコル上で行う非同期TCPサーバであるディスパッチャです。 + +バックログがキャッシュサイズを超えない限り、メッセージは通常Managed Ledgerのキャッシュから送信され、超えた場合にはBrokerがBookKeeperからエントリの読み出しを始めます。 + +グローバルトピックでのジオレプリケーションをサポートするためにBrokerはレプリケータを管理します。 +このレプリケータはPulsarクライアントライブラリを利用し、ローカルクラスタ内で発行されるエントリをtailしリモートクラスタに再発行します。 + + +### 永続ストア + +Pulsarは、Apache BookKeeperを分散ログ先行書き込みシステムの永続ストレージとして使用しています。 +BookKeeperでは、アプリケーションはLedgerと呼ばれる多くの独立したログを作成できます。 +Ledgerは、単一のwriterが末尾への追加のみを行うデータ構造で、複数のストレージノード (またはBookieと呼びます) に割り当てられ、エントリはこれらのノードの複数にレプリケートされます。 +Ledgerのセマンティクスはとてもシンプルです:プロセスはLedgerの作成、エントリの末尾への追加、Ledgerのクローズができます。明示的またはwriterのプロセスがクラッシュしてLedgerがクローズされた後、read-onlyモードのみでオープンできます。 +そしてLedger内のエントリが不要になったら、システムからそのLedger自体を削除できます。 + +BookKeeperの主な強みは、障害発生時のLedgerの読み取りの一貫性を保証することです。 +Ledgerは単一のプロセスによってのみ書き込み可能なので、プロセスは非常に効率よく自由にエントリを追加することができ (追加のコンセンサスが不要) 、障害後には、Ledgerは状態を確定しログに最後にコミットされたエントリを確定するリカバリープロセスを実行します。 +その後、Ledgerの全てのreaderは全く同じ内容を参照することが保証されます。 + +BookKeeperはエントリのレプリケーション、ノード障害を処理するのに非常に効率的なシーケンシャルストアであり、加えて容量とスループットが水平にスケーラブルなため、Pulsarで採用しています。 +運用上の観点からも、PulsarクラスタにBookieを追加するだけで容量を即座に増やすことができます。 +BookKeeperの他の強みは、Bookieは並行読み込み/書き込みで何千ものLedgerを処理するようにデザインされている点と、複数ディスクデバイス (1つはJournal用、もう1つは通常のストレージ用) を利用することで、進行中の書き込み処理のレイテンシから読み込み処理の影響を分離できる点です。 + + +### Managed Ledger + +BookKeeperのLedgerが単一のログ抽象化を提供するため、単一トピックのストレージ層を表すManaged Ledgerと呼ばれるLedgerの上位概念を表すライブラリが開発されました。 +Managed Ledgerは、ストリームの最後に追加し続ける単一のwriterとストリームをconsumeしている複数カーソル (それぞれが独自の関連位置を保持します) を持つメッセージストリームの抽象化を表します。 + +内部的には、1つのManaged Ledgerはデータを保持するために複数のBookKeeperのLedgerを使います。 +複数のLedgerを持つのには2つの理由があります: +1つ目は、障害後にLedgerはもはや書き込めないため新しいLedgerを作成する必要があるためで、 +2つ目は、すべてのカーソルがLedgerに含まれるすべてのメッセージをconsumeした時にLedgerを削除する可能性があるため定期的にLedgerをロールオーバーしたいためです。 + +### メタデータストア + +Pulsarはメタデータやクラスタの構成、 (コンポーネント間の) 連携のためにApache ZooKeeperを利用します。 +- *Global ZooKeeper* は、グローバルで整合性が必要なプロパティやネームスペース、ポリシーのようなユーザプロビジョニングデータを保持します。 +- それぞれのクラスタには、ownershipのメタデータやBrokerの負荷レポート、BookKeeperのLedgerのメタデータのようなクラスタ特有の構成、連携のためのデータを保持している*Local ZooKeeper*アンサンブルがあります。 + +## デザイン + +### トピック + +**トピック** はメッセージを発行、購読するするための論理的なエンドポイントです。 +Producerはトピックに対してメッセージを発行し、Consumerはトピックに対して購読します。 +Pulsarではトピックに対する複数のサブスクリプションモードでpub/sub、ロードバランサー、フェイルオーバーのユースケースをサポートします。 + +通常のトピック (パーティションドトピックを除く) は明示的に作成される必要はなく、 +トピックに対してメッセージをproduce/consumeしようとした際に作成されます。 + +### サブスクリプション + +サブスクリプションはConsumerが最初に接続した時に与えられたサブスクリプション名によって作成される永続性のあるリソースです。 +サブスクリプションは作成された後、トピックに対して発行された全てのメッセージを受け取ります。 +Consumerがこのサブスクリプションに1つも接続していない場合、発行された全てのメッセージはバックログに保持されます。 +最終的に、トピックからサブスクリプションを削除するために、Consumerは購読解除できます。 + +### サブスクリプションモード + +サブスクリプションモードはメッセージをConsumerにどのようにメッセージを配送するかを決定する設定です。 + +![サブスクリプションモード](../../img/pulsar_subscriptions.jpg) + +**Exclusive** + +- デフォルトのサブスクリプションモードです。1つのサブスクリプションに対して1つのConsumerのみが接続を許可されます。2つ以上のConsumerが同じサブスクリプション名を用いてトピックに対して購読を試みた場合、エラーが発生します。トピックに対するpublish/subscribeモデルをサポートするために、複数のConsumerは異なるサブスクリプション名を利用します。トピックに発行されたメッセージは全てのConsumerに配送されます。 + +**Shared** + +- 複数のConsumerが同じサブスクリプションに接続できます。メッセージはラウンドロビンで複数のConsumerに配送され、各メッセージは1つのConsumerのみに配送されます。Consumerが切断するとき、送信されたがAck (確認応答) が返ってきていない全てのメッセージは、再送のためにリスケジュールされます。 +- SharedのConsumerに対する配送の順序は保証されません。 + +**Failover** + +- 複数のConsumerが同じサブスクリプションに接続できます。ConsumerはConsumer名により辞書順にソートされ、辞書順で最初のConsumerがMaster Consumerとしてメッセージを受信します。このConsumerが切断された場合、Ackが返ってきていないものとその後に続く全てのメッセージは辞書順で次のConsumerに配送されます。 + +### プロパティとネームスペース + +プロパティとネームスペースはマルチテナントをサポートするためのPulsarのキーコンセプトです。 + +- **プロパティ** はテナントを特定します。Pulsarは適切な容量を割り当てられた特定のプロパティに対して提供されます。 +- **ネームスペース** はプロパティ内での管理単位の名前です。ネームスペースに設定されたポリシーは、そのネームスペース内の全てのトピックに適用されます。プロパティはREST APIやCLIツールを用いてセルフ管理により複数のネームスペースを作成できます。例えば、異なるアプリケーションを持つプロパティは、各アプリケーションのために別々のネームスペースを作成できます。 + +例えば、プロパティ`my-property`のための、クラスタ`us-w`に存在している、アプリケーション`my-app1`が使用するネームスペース、`my-property/us-w/my-app1`ついて考えてみます。 +そのようなネームスペースに対するトピックネームは以下のようになります: + +``` +persistent://my-property/us-w/my-app1/my-topic-1 +persistent://my-property/us-w/my-app1/my-topic-2 +... +``` + + +### Producer + +Producerはトピックに接続し、メッセージを送信します。 + +**同期送信 vs. 非同期送信** - メッセージは同期的あるいは非同期的にBrokerに送信できます: + +- 同期: Producerはメッセージを送信した後Brokerからの確認応答を待ちます。 +- 非同期: Producerはメッセージをブロッキングキューに入れ、制御を戻します。クライアントライブラリはバックグラウンドでBrokerに送信します。キューが最大量 (設定可能) に達した場合、Producerは送信APIを呼び出した時、Producerの引数に応じてブロックされる、あるいは失敗する可能性があります。 + +**圧縮** - 帯域を節約するため、メッセージを圧縮することが可能です。圧縮と解凍はどちらもクライアントで動作します。以下の圧縮形式をサポートしています: + +- LZ4 +- ZLIB + +**バッチ** - バッチ処理が可能な場合、Producerはメッセージを蓄積し、1つのリクエストでメッセージのバッチを送信しようとします。バッチサイズはメッセージの最大数と最大発行レイテンシで定義されます。 + +### Consumer + +Consumerはサブスクリプションに接続し、メッセージを受け取ります。 + +**同期受信 vs. 非同期受信** - 同期受信はメッセージが利用可能になるまでブロックされます。同期受信ではCompletableFutureインスタンスとしてすぐに返却されます。CompletableFutureインスタンスは新しいメッセージが利用可能になった時、受信して完了します。 + +**確認応答** - メッセージは1つ1つ個別に、あるいは累積的に確認応答が返されます。累積的な確認応答をするConsumerは、最後に受け取ったメッセージの確認応答を返します。その場合、確認応答を返したメッセージまでのストリーム内の全てのメッセージはそのConsumerに再送されません。サブスクリプションモードがSharedの場合は、累積的な確認応答は使用できません。 + +**リスナー** - カスタマイズされたMessageListenerの実装をConsumerに渡すことができます。クライアントライブラリは新しいメッセージを受け取るとリスナーを呼び出します (Consumer Receiveを呼び出す必要はありません) 。 + + +### パーティションドトピック + +通常のトピックは最大スループットを制限する1つのBrokerのみから提供されます。パーティションドトピックは高いスループットを達成するために複数のBrokerにまたがる特殊なトピックです。パーティションドトピックは管理API/CLIを通じて明示的に作成される必要があります。トピックを作成する際、パーティションの数を記述できます。 + +パーティションドトピックは実際にはN (パーティションの数) 個の内部トピックとして実装されます。内部トピックと普通のトピックについて、サブスクリプションモードの挙動に違いはありません。 + +![パーティションドトピック](../../img/pulsar_partitioned_topic.jpg) + +**ルーティングモード** - ルーティングモードはどのパーティション (内部トピック) にメッセージが発行されるかを決定します: + +- キーハッシュ: メッセージにキーが指定されていれば、Partitioned Producerはキーをハッシュ化し、キーバケットごとの順序を保証しながら、特定のパーティションに割り当てます。 +- Single Partition: キーが指定されない場合、各プロデューサのメッセージはプロデューサごとのメッセージの順序を保証するために、 (最初にランダムに選ばれた) 専用パーティションにルーティングされます。 +- Round Robin Partition: キーが指定されない場合、最大スループットを達成するために、全てのメッセージはラウンドロビンで異なるパーティションにルーティングされます。順序は保証されません。 +- Custom Partition: メッセージは独自のMessageRouterの実装によってルーティングされます。 + +```java +public interface MessageRouter extends Serializable { + /** + * @param msg メッセージオブジェクト + * @return そのメッセージのために使用するパーティションのインデックス + */ + int choosePartition(Message msg); +} +``` + +### 永続化 + +保証されたメッセージの配送はそれらが配信され、Consumerによる確認応答を受け取るまで頑健な方法で保存される必要があります。このメッセージングの方法は一般的にPersistent Messagingと呼ばれます。 + +メッセージの永続性はトピックレベルで設定されます。トピックは“persistent”にも“non-persistent”にもなりえます。トピック名は以下のようになります: +*persistent://my-property/global/my-ns/my-topic* + +**persistent** + +- 全てのメッセージはディスク上に保存、同期され、N個のコピー (例: 4個のコピーが個別にミラーリングされたRAIDボリュームを持つ2台のサーバに存在) が全てのConsumerがメッセージをconsumeするまで保存されます。カーソルと呼ばれるCosumerの購読位置もディスク上に保存されます。メッセージは必ず1回は配送されることが保証されます。 + +**non-persistent** + +- 現在、PulsarはNon-persistent Messagingとして知られるベストエフォートの配送はサポートしていません。しかし、今後の計画としてNon-persistent Messagingをサポートする予定があります。 + + +### レプリケーション + +Pulsarでは異なるジオロケーションでのメッセージのproduce, consumeが可能です。例えば、アプリケーションが1つのジオ/マーケットにデータを発行し、異なるジオ/マーケットでそれをconsumeし処理したいとします。Global Replicationがそれを可能にします。 + +### 認証と認可 + +TODO + + +# クライアントライブラリ + + +PulsarはJava言語バインディングのクライアントAPIを公開しています。 +クライアントAPIはクライアント-Broker間の通信プロトコルを最適化・カプセル化し、アプリケーションから使用するためのシンプルで直感的なAPIを公開しています。 +その内部では、クライアントライブラリが透過的なBrokerとの再接続や接続フェイルオーバー、BrokerからAckが返されるまでのメッセージのキューイング、バックオフによる接続再試行のようなヒューリスティクスなどをサポートしています。 + +## クライアントのセットアップフェイズ + +アプリケーションがProducer/Consumerを作成する際、Pulsarのクライアントライブラリは2つのステップから成るセットアップフェイズを内部的に開始します。 +最初のタスクは、ルックアップのためのHTTPリクエストを送信してトピックのオーナーであるBrokerを見つける事です。 +このリクエストはアクティブなBrokerの中の1台に届き、 (キャッシュされた) ZooKeeperのメタデータを参照する事でどのBrokerがトピックを提供しているかを知る事ができます。 +どのBrokerもリクエストされたトピックを提供していない場合には、最も負荷の小さいBrokerにそのトピックが割り当てられます。 + +クライアントライブラリがBrokerのアドレスを取得すると、TCPコネクションを作成 (またはプールされた既存のコネクションを再利用) し、認証を行います。 +このコネクションの中で、クライアントとBrokerは独自プロトコルのバイナリコマンドを交換します。 +この時点で、クライアントはProducer/Consumerを作成するためのコマンドをBrokerに送信します。 +なお、このコマンドは認可ポリシーを検証した後、それに従って行われます。 + +TCPコネクションが切断されると、即座にクライアントはこのセットアップフェイズを再実行し、成功するまで指数バックオフを試行し続けます。 + +## PulsarClient + +PulsarClient (TODO: javadocs) インスタンスは、メッセージのproduce/consumeを行う前に必要となります。 + +```java +ClientConfiguration config = new ClientConfiguration(); +PulsarClient pulsarClient = PulsarClient.create("http://broker.example.com:8080", config); +... +pulsarClient.close(); +``` + +PulsarClientに引数を渡すためにClientConfiguration (TODO: javadocs) を使用できます: + +```java +// Pulsarクライアントのインスタンスの中で使用する認証プロバイダをセット +public void setAuthentication(Authentication authentication); +public void setAuthentication(String authPluginClassName, String authParamsString); +public void setAuthentication(String authPluginClassName, Map authParams); + +// オペレーションのタイムアウト値をセット (デフォルト:30秒) +public void setOperationTimeout(int operationTimeout, TimeUnit unit); + +// Brokerとのコネクションをハンドリングするスレッド数をセット (デフォルト:1スレッド) +public void setIoThreads(int numIoThreads); + +// メッセージリスナとして使用するスレッド数をセット (デフォルト:1スレッド) +public void setListenerThreads(int numListenerThreads); + +// 1台のBrokerとの間にオープンするコネクション数の最大値をセット +public void setConnectionsPerBroker(int connectionsPerBroker); + +// Nagleアルゴリズムを無効化するためにTCP no-delayフラグを使用するかどうかを設定 +public void setUseTcpNoDelay(boolean useTcpNoDelay); +``` + +## Consumer API + +PulsarClientを使用してConsumer (TODO javadocs) を作成し、10のメッセージを受信します。 + +```java +ConsumerConfiguration conf = new ConsumerConfiguration(); +conf.setSubscriptionType(SubscriptionType.Exclusive); +Consumer consumer = pulsarClient.subscribe( + "persistent://my-property/us-w/my-ns/my-topic", "my-subscriber-name", conf); + +for (int i = 0; i < 10; i++) { + // メッセージを受信 + Msg msg = consumer.receive(); + + // 何らかの処理を実行 + System.out.println("Received: " + new String(msg.getData())); + + // メッセージの処理に成功した事を通知するAck + consumer.acknowledge(msg); +} + +consumer.close(); +``` + +Consumerに引数を渡すためにConsumerConfiguration (TODO javadocs) を使用できます: + +```java +// Ackが返されていないメッセージのタイムアウト値をセット (最も近いミリ秒の値になるように切り捨て) +public ConsumerConfiguration setAckTimeout(long ackTimeout, TimeUnit timeUnit); +// トピックの購読時に使用するサブスクリプションタイプを選択 +public ConsumerConfiguration setSubscriptionType(SubscriptionType subscriptionType); +// ConsumerのMessageListenerをセット +public ConsumerConfiguration setMessageListener(MessageListener messageListener); +// Consumerの受信キューのサイズをセット +public ConsumerConfiguration setReceiverQueueSize(int receiverQueueSize); +``` + + +## Producer API + +PulsarClientを使用してProducer (TODO javadocs) を作成し、10のメッセージを発行します。 +```java +ProducerConfiguration = config = new ProducerConfiguration(); +Producer producer = pulsarClient.createProducer( + "persistent://my-property/us-w/my-ns/my-topic", config); +// 10のメッセージをトピックに発行 +for (int i = 0; i < 10; i++) { + producer.send("my-message".getBytes()); +} +producer.close(); +``` + +Producerに引数を渡すためにProducerConfiguration (TODO javadocs) を使用できます: + +```java +// 送信タイムアウト値をセット (デフォルト:30秒) +public ProducerConfiguration setSendTimeout(int sendTimeout, TimeUnit unit); +// BrokerからAckを受信するためにペンディング状態になっているメッセージを保持するキューの最大サイズをセット +public ProducerConfiguration setMaxPendingMessages(int maxPendingMessages); +// 送信メッセージキューがいっぱいになった時に Producer#send および Producer#sendAsync をブロックするかどうかをセット +public ProducerConfiguration setBlockIfQueueFull(boolean blockIfQueueFull); +// Partitioned Producerのメッセージのルーティングモードをセット +public ProducerConfiguration setMessageRoutingMode(MessageRoutingMode messageRouteMode); +// メッセージの圧縮方式をセット +public ProducerConfiguration setCompressionType(CompressionType compressionType); +// MessageRouterの実装を渡してカスタマイズされたメッセージのルーティングポリシーをセット +public ProducerConfiguration setMessageRouter(MessageRouter messageRouter); +// メッセージの自動バッチ処理を有効にするかどうかを指定 (デフォルト:false) +public ProducerConfiguration setBatchingEnabled(boolean batchMessagesEnabled); +// 送信メッセージがバッチ処理される期間をセット (デフォルト:10ミリ秒) +public ProducerConfiguration setBatchingMaxPublishDelay(long batchDelay, TimeUnit timeUnit); +// 1回のバッチ処理で許可されるメッセージの最大数をセット (デフォルト:1000) +public ProducerConfiguration setBatchingMaxMessages(int batchMessagesMaxMessagesPerBatch); +``` diff --git a/docs/locale/ja/Authentication.md b/docs/locale/ja/Authentication.md new file mode 100644 index 0000000000000..c36b59cc14d0e --- /dev/null +++ b/docs/locale/ja/Authentication.md @@ -0,0 +1,141 @@ + +# Pulsarにおける認証 + + + +- [認証モデル](#認証モデル) +- [認証プロバイダ](#認証プロバイダ) + - [TLSクライアント認証](#tlsクライアント認証) + - [証明書の作成](#証明書の作成) + - [Brokerの設定](#brokerの設定) + - [ディスカバリサービスの設定](#ディスカバリサービスの設定) + - [Javaクライアントの設定](#javaクライアントの設定) + - [CLIツールの設定](#cliツールの設定) + + + +## 認証モデル + +Pulsarはプラガブル認証メカニズムをサポートし、Brokerは複数の認証ソースをサポートするように設定できます。 + +認証プロバイダ実装の役割は、 クライアントのアイデンティティを *ロール* トークンの形式で確立することです。 +このロールトークンを使用して、このクライアントが特定のトピックに対してproduceまたはconsumeを許可されているかどうかを検証します。 + +## 認証プロバイダ + +### TLSクライアント認証 + +PulsarクライアントとBroker間の接続暗号化を提供することに加えて、 +TLSは信頼された認証局 (CA) によって署名された証明書を通してクライアントを識別できます。 + +**注**: 他のPulsarコードとは異なり、TLS認証プロバイダはYahooのプロダクションでは使用されていません。 +使用する際に発生した問題があれば報告してください。 + + +#### 証明書の作成 + +##### 認証局 (CA) + +最初のステップは、CAの証明書を作成することです。 +CAはBrokerとクライアント両方の証明書に署名するために用いられ、お互いを信頼できるようにします。 + +```shell +# Linuxシステム上で: +$ CA.pl -newca + +# MacOSX上で +$ /System/Library/OpenSSL/misc/CA.pl -newca +``` + + コマンドライン上の質問に回答後、CA関連のファイルが`./demoCA`配下に作成されます。 + * `demoCA/cacert.pem` は公開鍵証明書です。全ての関係者に配布されます。 + * `demoCA/private/cakey.pem` は秘密鍵です。Brokerまたはクライアントの新規の証明書に署名するときのみ必要になります。安全な場所に保管してください。 + +##### Brokerの証明書 + +証明書リクエストを作成し、CAの公開鍵証明書で署名します。 + +これらのコマンドはいくつかの質問をし、証明書を作成します。 +コモンネームは、Brokerのホスト名と一致させる必要があります。 +Brokerのホスト名のグループにマッチするワイルドカードを利用することも可能です。 +例えば`*.broker.usw.example.com`のようにすることで、同じ証明書を複数マシンで再利用できます。 + +```shell +$ openssl req -newkey rsa:2048 -sha256 -nodes -out broker-cert.csr -outform PEM + +# 鍵をPKCS#8フォーマットに変換 +$ openssl pkcs8 -topk8 -inform PEM -outform PEM -in privkey.pem -out broker-key.pem -nocrypt +``` + +このコマンドによりBrokerの証明書リクエストファイル (`broker-cert.csr`と`broker-key.pem`) が生成されます。 + +これで署名付き証明書の作成に進むことができます: + +```shell +$ openssl ca -out broker-cert.pem -infiles broker-cert.csr +``` + +この時点で、Brokerに必要な`broker-cert.pem`と`broker-key.pem`が用意できました。 + +##### クライアントの証明書 + +Brokerと同じステップを繰り返して、`client-cert.pem` と `client-key.pem`を作成してください。 + +クライアントのコモンネームは、クライアントのホスト名と一致させる必要はありませんが、 +*ロール*トークンで使用予定の文字列を用いる必要があります。 + +#### Brokerの設定 + +`conf/broker.conf`にPulsar BrokerのTLS認証を設定: + +```shell +tlsEnabled=true +tlsCertificateFilePath=/path/to/broker-cert.pem +tlsKeyFilePath=/path/to/broker-key.pem +tlsTrustCertsFilePath=/path/to/cacert.pem + +# Add TLS auth provider +authenticationEnabled=true +authorizationEnabled=true +authenticationProviders=com.yahoo.pulsar.broker.authentication.AuthenticationProviderTls +``` + +#### ディスカバリサービスの設定 + +ディスカバリサービスはHTTPSリクエストのリダイレクト処理を行うため、同様にクライアントから信頼される必要があります。 +`conf/discovery.conf`にTLS認証の設定を追加: +```shell +tlsEnabled=true +tlsCertificateFilePath=/path/to/broker-cert.pem +tlsKeyFilePath=/path/to/broker-key.pem +``` + +#### Javaクライアントの設定 + +```java +ClientConfiguration conf = new ClientConfiguration(); +conf.setUseTls(true); +conf.setTlsTrustCertsFilePath("/path/to/cacert.pem"); + +Map authParams = new HashMap<>(); +authParams.put("tlsCertFile", "/path/to/client-cert.pem"); +authParams.put("tlsKeyFile", "/path/to/client-cert.pem"); +conf.setAuthentication(AuthenticationTls.class.getName(), authParams); + +PulsarClient client = PulsarClient.create( + "https://my-broker.com:4443", conf); +``` + +#### CLIツールの設定 + +`pulsar-admin`, `pulsar-perf`や`pulsar-client`のようなコマンドラインツールは設定ファイル`conf/client.conf`を利用します。 +認証パラメータの追加: + +```shell +serviceUrl=https://broker.example.com:8443/ +authPlugin=com.yahoo.pulsar.client.impl.auth.AuthenticationTls +authParams=tlsCertFile:/path/to/client-cert.pem,tlsKeyFile:/path/to/client-cert.pem +useTls=true +tlsAllowInsecureConnection=false +tlsTrustCertsFilePath=/path/to/cacert.pem +``` diff --git a/docs/locale/ja/Authorization.md b/docs/locale/ja/Authorization.md new file mode 100644 index 0000000000000..d6439495550e7 --- /dev/null +++ b/docs/locale/ja/Authorization.md @@ -0,0 +1,66 @@ + +# Pulsarにおける認可 + + + +- [認可モデル](#認可モデル) +- [新規プロパティの作成](#新規プロパティの作成) +- [ネームスペースの管理](#ネームスペースの管理) +- [スーパーユーザ](#スーパーユーザ) + + + +## 認可モデル + +Pulsarにおいて、認証プロバイダは特定のクライアントを識別し***ロール***トークンと関連付けます。 + +ロールは単一または複数のクライアントを表す文字列で、 +これらのクライアントは、特定のトピックに対してproduceまたはconsumeを行う権限、または特定の[プロパティ](Architecture.md#プロパティとネームスペース)の設定を管理する権限が付与されます。 + +## 新規プロパティの作成 + +Pulsarのプロパティはテナントを示す識別子で、一般的にPulsarインスタンスの管理者またはセルフサービスのポータルなどによって提供されます。 + +```shell +$ bin/pulsar-admin properties create my-property \ + --admin-roles my-admin-role \ + --allowed-clusters us-west,us-east +``` + +このコマンドはクラスタ`us-west`と`us-east`を利用可能な新規プロパティ`my-property`を作成します。 + +ロール`my-admin-role`と識別されたクライアントは、このプロパティ上での全ての管理操作が許可されます。 + +## ネームスペースの管理 + +プロパティ管理者は指定されたクラスタ内に複数ネームスペースを作成できます。 + +``` +$ bin/pulsar-admin namespaces create my-property/us-west/my-namespace +``` + +作成後、このネームスペースの利用権限の付与ができます: + +``` +$ bin/pulsar-admin namespaces grant-permission \ + my-property/us-west/my-namespace \ + --role my-client-role \ + --actions produce,consume +``` + +コマンド実行後、ロール`my-client-role`と識別されたクライアントは指定されたネームスペースのトピックを利用可能になります。 + +## スーパーユーザ + +Pulsarでは、システムの*スーパーユーザ*を特定のロールに割り当てることができます。 + +スーパーユーザは全てのプロパティとネームスペースに対する全ての管理操作、および全てのトピックに対する発行と購読が許可されます。 + +スーパーユーザはBrokerの設定ファイル`conf/broker.conf`で設定されます: + +```shell +superUserRoles=my-super-user-1,my-super-user-2 +``` + +一般的に、スーパーユーザロールはadminクライアントやBroker間の認可で利用されます。 +ジオレプリケーションにおいては、各Brokerが他クラスタのトピックに発行できる必要があります。 diff --git a/docs/locale/ja/BinaryProtocol.md b/docs/locale/ja/BinaryProtocol.md new file mode 100644 index 0000000000000..ec9de7a12c92e --- /dev/null +++ b/docs/locale/ja/BinaryProtocol.md @@ -0,0 +1,522 @@ + +# Pulsarのバイナリプロトコルの仕様 + + + +- [フレーミング](#フレーミング) +- [メッセージ・メタデータ](#メッセージメタデータ) + - [バッチ・メッセージ](#バッチメッセージ) +- [インタラクション](#インタラクション) + - [接続の確立](#接続の確立) + - [Keep Alive](#keep-alive) + - [Producer](#producer) + - [Consumer](#consumer) +- [サービスディスカバリ](#サービスディスカバリ) + - [トピックのルックアップ](#トピックのルックアップ) + - [パーティションドトピックのディスカバリ](#パーティションドトピックのディスカバリ) + + + +PulsarはProducer/ConsumerとBrokerの通信に独自バイナリプロトコルを利用しています。 +プロトコルは転送と実装の最大効率を保証しながら、 +要求される全ての特徴 (例: Ack、フロー制御) をサポートするようにデザインされています。 + +クライアントとBrokerは互いに *コマンド* を交換します。 +コマンドは[Protocol Buffers](https://developers.google.com/protocol-buffers/)によるバイナリメッセージの形式です。 + +Protocol Buffersによるコマンドの仕様は`PulsarApi.proto` + ([pulsar-common/src/main/proto/PulsarApi.proto](https://github.com/yahoo/pulsar/blob/master/pulsar-common/src/main/proto/PulsarApi.proto)) に記述されています。 + +異なるProducerとConsumerのコマンドは同じ接続を介して +制限なく送信、インターリーブできます。 + +全てのコマンドはenum型と全ての可能なサブコマンドをオプショナルフィールドに含むProtocol Buffersのオブジェクト +[`BaseCommand`](https://github.com/yahoo/pulsar/blob/master/pulsar-common/src/main/proto/PulsarApi.proto#L335) +に埋め込まれています。 +いかなる時も、1つの`BaseCommand`は1つのサブコマンドしか設定できません。 + +## フレーミング + +Protocol Buffersはメッセージ・フレームのソートを提供していないため、 +Protocol Buffersのデータの前に4バイトのフィールドを追加しています。 + +1つのフレームの最大サイズは5 MBです。 + +Pulsarのプロトコルには以下の2つのタイプのコマンドがあります: + 1. ペイロードを持たないシンプルなコマンド。 + 2. メッセージの配送や発行に使われるペイロードを持つコマンド。 + このケースではそのコマンドのデータの後に、他のProtocol Buffersのメタデータが追従します。 + 効率的な理由からペイロードはProtocol Buffersの外側でRaw形式で渡されます。 + +全てのサイズは4バイト符号なしビッグエンディアン整数として渡されます。 + +#### シンプルなコマンド + +``` +[TOTAL_SIZE] [CMD_SIZE] [CMD] +``` + + * `TOTAL_SIZE` → *(4バイト)* フレームのサイズ。その後に続く全てのデータを数える。 + * `CMD_SIZE` → *(4バイト)* シリアライズされたProtocol Buffersのコマンドのサイズ。 + * `CMD` → バイナリ形式にシリアライズされたProtocol Buffersのオブジェクト。 + +#### ペイロードを持つコマンド + + ``` + [TOTAL_SIZE] [CMD_SIZE][CMD] [MAGIC_NUMBER][CHECKSUM] [METADATA_SIZE][METADATA] [PAYLOAD] + ``` + + * `TOTAL_SIZE` → *(4バイト)* フレームのサイズ。その後に続く全てのデータを数えます。 + * `CMD_SIZE` → *(4バイト)* シリアライズされたProtocol Buffersのコマンドのサイズ。 + * `CMD` → バイナリ形式にシリアライズされたProtocol Buffersのオブジェクト。 + * 実際に永続化されたあとに受け取るデータ。 + * `MAGIC_NUMBER` → *(2バイト)* `0x0e01` 現在のフォーマットを特定するマジックナンバー。 + * `CHECKSUM` → *(2バイト)* この後に続くデータに対するCRC32-Cチェックサム。 + * `METADATA_SIZE` → *(4バイト)* メッセージ・メタデータのサイズ。 + * `METADATA` → バイナリのProtocol Buffers形式のメッセージ・メタデータ。 + * `PAYLOAD` → フレームの残りの部分はペイロードとみなされます。 + 任意のバイト列を含めることができます。 + +## メッセージ・メタデータ + +メッセージ・メタデータは、アプリケーションに指定されたペイロードとともに、 +シリアライズされたProtocol Buffersオブジェクトとして保存されます。 + +メタデータはProducerに作成され、変更されることなくConsumerに渡されます。 + +フィールド: + * `producer_name` → メッセージを発行したProducerの名前。 + * `sequence_id` → Producerから割り当てられたメッセージのシーケンスID。 + * `publish_time` → 発行時のタイムスタンプ (UTCで1970年1月1日からのミリ秒単位の経過時間) 。 + * `properties` → アプリケーションに定義された`Pair`形式のデータ (Pulsarの動作には影響を与えないKey-Value) 。 + * `replicated_from` → *(任意)* メッセージがレプリケートされたものかを表し、 + レプリケートされたものである場合レプリケート元のクラスタ名。 + * `partition_key` → *(任意)* パーティションドトピックでpubulishされる間、 + キーが存在すれば、そのハッシュをパーティションの選択に利用します。 + * `compression` → *(任意)* ペイロードが圧縮されているか、 + どの圧縮ライブラリが使用されているか。 + * `uncompressed_size` → *(任意)* 圧縮されている場合、 + Producerはこのフィールドに元のペイロードサイズを記述する必要があります。 + * `num_messages_in_batch` → *(任意)* このメッセージが複数のメッセージのバッチである場合は、 + 含まれているメッセージの数が記述されている必要があります。 + +### バッチ・メッセージ + +バッチ・メッセージを利用する時、ペイロードはエントリのリストを含んでいます。 +それらは`SingleMessageMetadata`により定義された固有のメタデータを持ちます。 + +1つのバッチのペイロードは以下の通りです: + +``` +[MD_SIZE_1] [MD_1] [PAYLOAD_1] [MD_SIZE_2] [MD_2] [PAYLOAD_2] ... +``` + +ここで: + * `MD_SIZE_X` → シリアライズされたProocol Buffers形式のシングル・メッセージ・メタデータのサイズ。 + * `MD_X` → シングル・メッセージ・メタデータ。 + * `PAYLOAD_X` → アプリケーションから渡されたメッセージペイロード。 + +`SingleMessageMetadata`のフィールド: + * `properties` → アプリケーションが定義したプロパティ。 + * `partition_key` → *(任意)* ハッシュによりパーティションを特定するためのKey。 + * `payload_size` → バッチ内の1つのメッセージについてのペイロードのサイズ。 + +圧縮が有効な場合、バッチ全体が一度に圧縮されます。 + +## インタラクション + +### 接続の確立 + +BrokerへのTCPコネクションの確立後、クライアントはセッションを開始しなければなりません。 +通常これには6650番のポートが利用されます。 + +![Connect interaction](../../img/Binary Protocol - Connect.png) + +Brokerから`Connected`という応答を受け取ると、クライアントは +接続準備完了とみなします。もしBrokerが +クライアントの認証を検証できなれければ、代わりに`Error`コマンドを返し +TCPコネクションをクローズします。 + +例: + +```json +CommandConnect { + "client_version" : "Pulsar-Client-Java-v1.15.2", + "auth_method_name" : "my-authentication-plugin", + "auth_data" : "my-auth-data", + "protocol_version" : 6 +} +``` + +フィールド: + * `client_version` → フォーマットの強制されていないString形式の識別子。 + * `auth_method_name` → *(任意)* 認証が有効な場合は認証プラグインの名前。 + * `auth_data` → *(任意)* プラグイン固有の認証データ。 + * `protocol_version` → クライアントのサポートするプロトコルのバージョン。 + Brokerは指定されたバージョンより新しいプロトコルのコマンドを送りません。 + Brokerは最低限のバージョンを要求する可能性があります。 + +```json +CommandConnected { + "server_version" : "Pulsar-Broker-v1.15.2", + "protocol_version" : 6 +} +``` + +フィールド: + * `server_version` → BrokerのバージョンのString形式の識別子。 + * `protocol_version` → Brokerがサポートするプロトコルのバージョン。 + クライアントは指定されたバージョンより新しいプロトコルのコマンドを送ることができません。 + +### Keep Alive + +クライアントとBrokerの長期のネットワークのパーティションやリモートエンドでの +TCPコネクションを終了しないままマシンがクラッシュした場合 +(例: 停電、カーネルパニック、ハードリブート) を識別するため、 +リモートピアのアベイラビリティステータスを調べる仕組みが備わっています。 + +クライアントとBrokerは`Ping`コマンド定期的に送信し、 +タイムアウト時間内 (Brokerが使用するデフォルトの値は60秒)に`Pong`レスポンスを受け取らなければ +ソケットをクローズします。 + +Pulsarクライアントの実装において、`Ping`の送信は必須ではありません。 +しかし、Brokerから強制的にTCPコネクションを終了されないために、`Ping`を受け取った場合は +迅速な返答が必要です。 + +### Producer + +メッセージを送るために、クライアントはProducerを作成する必要があります。 +Producerを作成する時、Brokerは最初にそのクライアントがトピックへの発行を +認可されているかを検証します。 + +クライアントがProducerの作成を完了すると、ネゴシエートされたProducer IDを参照して +Brokerにメッセージを発行できます。 + +![Producer interaction](../../img/Binary Protocol - Producer.png) + +##### Producerコマンド + +```json +CommandProducer { + "topic" : "persistent://my-property/my-cluster/my-namespace/my-topic", + "producer_id" : 1, + "request_id" : 1 +} +``` + +パラメータ: + * `topic` → Producerを作成したいトピックの完全な名前。 + * `producer_id` → クライアントが生成した同一接続内で一意に定まるProducerの識別子。 + * `request_id` → レスポンスのマッチングに用いる同一接続内で一意に定まるリクエストの識別子。 + * `producer_name` → *(任意)* Producer名が指定されていればそれが利用され、 + そうでなければ、Brokerが一意に定まる名前を生成します。生成されたProducer名は + グローバルで一意に定まることが保証されます。Producerが最初に作成された時、 + Brokerに新しいProducer名を作成させ、再接続後にProducerを再作成する時は再利用するという + 実装が期待されます。 + +Brokerは`ProducerSuccess`コマンドか`Error`コマンドを返します。 + +##### ProducerSuccessコマンド + +```json +CommandProducerSuccess { + "request_id" : 1, + "producer_name" : "generated-unique-producer-name" +} +``` + +パラメータ: + * `request_id` → `CreateProducer`リクエストのID。 + * `producer_name` → 生成されたグローバルで一意に定まるProducer名、 + もしくはクライアントにより指定された名前。 + +##### Sendコマンド + +`Send`コマンドは既に存在するProducerのコンテキスト内で新しいメッセージを +発行する時に使用されます。このコマンドはコマンドだけでなくペイロードを含むフレーム内で +使用されます。ペイロードは[ペイロードコマンド](#ペイロードコマンド) セクションに記されている +完全なフォーマットで記述されます。 + +```json +CommandSend { + "producer_id" : 1, + "sequence_id" : 0, + "num_messages" : 1 +} +``` + +パラメータ: + * `producer_id` → ProducerのID。 + * `sequence_id` → 各メッセージは関連する0からカウントが始まるような + 実装が期待されるシーケンスのIDを持ちます。メッセージの効果的な発行を承認する。 + `SendReceipt`は、シーケンスIDによってメッセージを参照します。 + * `num_messages` → *(任意)* バッチ・メッセージが発行される時に使用されます。 + +##### SendReceiptコマンド + +メッセージが設定されたレプリカの数に応じて永続化されたあと、 +BrokerはProducerにメッセージを受け取ったことを示すAck (確認応答) を返します。 + +```json +CommandSendReceipt { + "producer_id" : 1, + "sequence_id" : 0, + "message_id" : { + "ledgerId" : 123, + "entryId" : 456 + } +} +``` + +パラメータ: + * `producer_id` → ProducerのID。 + * `sequence_id` → pubulishされたメッセージのシーケンスのID。 + * `message_id` → システムに割り当てられた1つのクラスタ内で一意に定まるメッセージのID。 + メッセージIDは`ledgerId`と`entryId`の2つのlong値から構成されます。 + これらの値はBookKeeperのLedgerに追加された時に割り振られたIDに基づいています。 + +##### CloseProducerコマンド + +**注**: *このコマンドはProducerとBrokerの両方から送信される可能性があります*。 + +Brokerが`CloseProducer`コマンドを受け取った時、BrokerはProducerからそれ以上のメッセージの受信を +停止し、ペンディング中の全てのメッセージが永続化されるまで待ち、クライアントに`Success`を返します。 + +Brokerは、正常なフェイルオーバー +(例: Brokerの再起動中、またはトピックが別のBrokerに転送されるようにロードバランサによってアンロードされている場合など) +を実行している時、クライアントに`CloseProducer`コマンドを送ることができます。 + +Producerが`CloseProducer`コマンドを受け取った時、クライアントはサービスディスカバリ・ルックアップを通じて +Producerを再作成することが期待されます。 +この際TCPコネクションは影響を受けません。 + +### Consumer + +Consumerはサブスクリプションへの接続とそこからのメッセージのconsumeに利用されます。 +接続後、クライアントはトピックを購読する必要があります。 +もしサブスクリプションがそのトピックになければ、新しく作成されます。 + +![Consumer](../../img/Binary Protocol - Consumer.png) + +#### フロー制御 + +Consumerの準備が整ったあと、クライアントはBrokerにメッセージをプッシュするための +*パーミッションを与える* 必要があります。これは`Flow`コマンドによって成されます。 + +`Flow`コマンドは追加の *パーミッション* を与えます。 +一般的なConsumerの実装では、アプリケーションがメッセージをconsumeする +準備が整うまでのメッセージの蓄積にキューを利用します。 + +アプリケーションがメッセージをデキューしたあと、Consumerは +Brokerに対してさらなるメッセージをプッシュするパーミッションを送ります。 + +##### Subscribeコマンド + +```json +CommandSubscribe { + "topic" : "persistent://my-property/my-cluster/my-namespace/my-topic", + "subscription" : "my-subscription-name", + "subType" : "Exclusive", + "consumer_id" : 1, + "request_id" : 1 +} +``` + +パラメータ: + * `topic` → Consumerを作成したいトピックの完全な名前。 + * `subscription` → サブスクリプション名。 + * `subType` → サブスクリプションタイプ: Exclusive, Shared, Failover + * `consumer_id` → クライアントが生成した同一接続内で一意に定まるConsumerの識別子。 + * `request_id` → レスポンスのマッチングに用いる同一接続内で一意に定まるリクエストの識別子。 + * `consumer_name` → *(任意)* クライアントはConsumer名を指定できます。 + この名前は、ステータス上で特定のConsumerを追跡するのに利用されます。 + また、サブスクリプションタイプがFailoverの時、この名前はどのConsumerが *master* (メッセージを受け取るConsumer) となるかを + 決めるのに使用されます。ConsumerはConsumer名によってソートされ、最初のものが + masterとして選ばれます。 + +##### Flowコマンド + +```json +CommandFlow { + "consumer_id" : 1, + "messagePermits" : 1000 +} +``` + +パラメータ: + * `consumer_id` → ConsumerのID。 + * `messagePermits` → Brokerに対して追加でプッシュを許可するメッセージの数。 + +##### Messageコマンド + +`Message`コマンドはBrokerが、与えられたパーミッションの制限内で +Consumerにメッセージをプッシュする際に使用されます。 + +このコマンドはコマンドだけでなくペイロードを含むフレーム内で +使用されます。ペイロードは[ペイロードコマンド](#ペイロードコマンド) セクションに記されている +完全なフォーマットで記述されます。 + +```json +CommandMessage { + "consumer_id" : 1, + "message_id" : { + "ledgerId" : 123, + "entryId" : 456 + } +} +``` + + +#### Ackコマンド + +`Ack`コマンドは与えられたメッセージがアプリケーションによって正しく処理され、 +Brokerによる破棄が可能であるというBrokerへの信号です。 + +加えて、Brokerは`Ack`の返されたメッセージに基いて +Consumerの購読位置を管理します。 + +```json +message CommandAck { + "consumer_id" : 1, + "ack_type" : "Individual", + "message_id" : { + "ledgerId" : 123, + "entryId" : 456 + } +} +``` + +パラメータ: + * `consumer_id` → ConsumerのID。 + * `ack_type` → Ackのタイプ: `Individual` もしくは `Cumulative` + * `message_id` → メッセージのID。 + * `validation_error` → *(任意)* Consumerが次の理由のためメッセージを + 破棄したことを示します: `UncompressedSizeCorruption`, + `DecompressionError`, `ChecksumMismatch`, `BatchDeSerializeError` + +##### CloseConsumerコマンド + +***注***: *このコマンドはConsumerとBrokerの両方から送信される可能性があります*。 + +このコマンドは[`CloseProducer`](#closeproducerコマンド)と同様の振る舞いをします。 + +##### RedeliverUnacknowledgedMessagesコマンド + +ConsumerはBrokerに、特定のConsumerにプッシュしたがまだ`Ack`が返っていないメッセージの +再配送を要求できます。 + +そのProtocl BuffersオブジェクトはConsumerが再配送してほしい +メッセージのIDのリストから構成されます。リストが空の場合は、 +Brokerはペンディング中の全てのメッセージを再送します。 + +再配送において、メッセージは同一のConsumer、あるいはサブスクリプションタイプがSharedの場合は +全ての利用可能なConsumerに送信されます。 + +## サービスディスカバリ + +### トピックのルックアップ + +トピックのルックアップはクライアントがProducer, Consumerを作成、再接続する度に必要となります。 +ルックアップはどの特定のBrokerが、利用しようとしているTopicを提供しているかを見つけるのに使用されます。 + +ルックアップは[admin API](AdminTools.md#トピックのルックアップ)で +説明されているREST APIのコールで行うことが可能です。 + +Pulsar-1.16からは、バイナリプロトコルで行うことも可能です。 + +例として、サービスディスカバリコンポーネントを`pulsar://broker.example.com:6650`で +起動していると仮定します。 + +個別のBrokerは`pulsar://broker-1.example.com:6650`, +`pulsar://broker-2.example.com:6650`, ...で起動しています。 + +クライアントはサービスディスカバリへの接続を`LookupTopic`コマンドを +送るために利用できます。レスポンスは接続すべきBrokerのホスト名、あるいは +ルックアップをリトライするためのBrokerのホスト名のどちらかです。 + +`LookupTopic`コマンドは`Connect` / `Connected`の最初のハンドシェイクを終えた +接続で使用されなければなりません。 + +![トピックのルックアップ](../../img/Binary Protocol - Topic lookup.png) + +```json +CommandLookupTopic { + "topic" : "persistent://my-property/my-cluster/my-namespace/my-topic", + "request_id" : 1, + "authoritative" : false +} +``` + +フィールド: + * `topic` → ルックアップするトピックの名前。 + * `request_id` → レスポンスとともに受け取るリクエストのID。 + * `authoritative` → 最初のルックアップリクエストではfalse、その後に続くリダイレクトのレスポンスでは + クライアントはレスポンスに含まれているものと同じ値を渡すべきです。 + +##### LookupTopicResponse + +成功時のレスポンス例: + +```json +Command LookupTopicResponse { + "request_id" : 1, + "response" : "Connect", + "brokerServiceUrl" : "pulsar://broker-1.example.com:6650", + "brokerServiceUrlTls" : "pulsar+ssl://broker-1.example.com:6651", + "authoritative" : true +} +``` + +リダイレクト時のレスポンス例: + +```json +Command LookupTopicResponse { + "request_id" : 1, + "response" : "Redirect", + "brokerServiceUrl" : "pulsar://broker-2.example.com:6650", + "brokerServiceUrlTls" : "pulsar+ssl://broker-2.example.com:6651", + "authoritative" : true +} +``` + +後者の場合、`LookupTopic`コマンドリクエストを`broker-2.example.com` に対して再発行する必要があります。 +このBrokerはルックアップリクエストに対して決定的なレスポンスを返すことができます。 + +### パーティションドトピックのディスカバリ + +パーティションドトピックのメタデータのディスカバリはトピックがパーティションドトピックかどうか、 +いくつのパーティションがセットアップされているかを調べるのに利用されます。 + +トピックがパーティションドである場合、クライアントは`partition-X`というサフィックスを用いて +各パーティションにつき一つのProducerあるいはConsumerを作成することが期待されます。 + +この情報は最初にProducerあるいはConsumerが作成される時のみに利用されます。 +再接続後は必要ありません。 + +パーティションドトピック・メタデータのディスカバリはトピックのルックアップと非常によく似た働きをします。 +クライアントはサービスディスカバリに対してリクエストを送り、レスポンスには実際のメタデータが含まれます。 + +##### PartitionedTopicMetadataコマンド + +```json +CommandPartitionedTopicMetadata { + "topic" : "persistent://my-property/my-cluster/my-namespace/my-topic", + "request_id" : 1 +} +``` + +フィールド: + * `topic` → パーティションのメタデータを確認するトピック。 + * `request_id` → レスポンスに渡されるリクエストのID。 + +##### PartitionedTopicMetadataResponseコマンド + +メタデータ付きのレスポンスの例: + +```json +CommandPartitionedTopicMetadataResponse { + "request_id" : 1, + "response" : "Success", + "partitions" : 32 +} +``` diff --git a/docs/locale/ja/ClusterSetup.md b/docs/locale/ja/ClusterSetup.md new file mode 100644 index 0000000000000..d5db5b22eb4d9 --- /dev/null +++ b/docs/locale/ja/ClusterSetup.md @@ -0,0 +1,345 @@ +# Pulsarクラスタのセットアップ + + + +- [セットアップ](#セットアップ) + - [システム要件](#システム要件) + - [コンポーネント](#コンポーネント) + - [ZooKeeper](#zookeeper) + - [Global ZooKeeper](#global-zookeeper) + - [クラスタのメタデータの初期化](#クラスタのメタデータの初期化) + - [BookKeeper](#bookkeeper) + - [Broker](#broker) + - [Service Discovery](#service-discovery) + - [adminクライアントと検証](#adminクライアントと検証) +- [モニタリング](#モニタリング) + + + +## セットアップ + +### システム要件 + +サポートされるプラットフォーム: + * Linux + * MacOS X + +必要なソフトウェア: + * Java 1.8 + +### コンポーネント + +#### ZooKeeper + +全てのZKサーバをクォーラム構成に追加します。 +全てのZKサーバの `conf/zookeeper.conf` を編集し、以下の行を追加してください: + +``` +server.1=zk1.us-west.example.com:2888:3888 +server.2=zk2.us-west.example.com:2888:3888 +server.3=zk3.us-west.example.com:2888:3888 +... +``` + +全てのホストでZKサービスを開始します: + +```shell +$ bin/pulsar-daemon start zookeeper +``` + +#### Global ZooKeeper + +参加者と全てのオブサーバを追加する事でグローバルクォーラムを構成します。 + +##### 単一クラスタのPulsarインスタンス + +単一クラスタでPulsarインスタンスをデプロイする場合、 +Global ZooKeeperは_ローカル_のZKクォーラムと同じマシンにデプロイし、異なるTCPポートで実行させる事ができます。 +`conf/global_zookeeper.conf` にサーバを追加し、ポート `2184` でサービスを開始してください: + +``` +clientPort=2184 +server.1=zk1.us-west.example.com:2185:2186 +server.2=zk2.us-west.example.com:2185:2186 +server.3=zk3.us-west.example.com:2185:2186 +... +``` + +##### 複数クラスタのPulsarインスタンス + +異なる地理的地域に分散したクラスタを持つグローバルなPulsarインスタンスをデプロイする場合、 +Global ZooKeeperは地域全体の障害や分断に耐え得る高い可用性と強い一貫性を持つメタデータストアとして機能します。 + +ここで重要な点は、ZKクォーラムのメンバが少なくとも3つの地域にまたがって存在しており、 +他の地域がオブザーバとして動作している事を確認する事です。 + +この場合も、Global ZooKeeperサーバの負荷は非常に低いため、 +ローカルのZooKeeperクォーラムに使用されているのと同じホストを共有させる事ができます。 + +例として、クラスタ `us-west`, `us-east`, `us-central`, `eu-central`, `ap-south` を持つPulsarインスタンスを仮定します。 +また、各クラスタには次のような名前のローカルZKサーバがあるものとします。 +``` +zk[1-3].${CLUSTER}.example.com +``` + +このシナリオでは、少数のクラスタからクォーラムの参加者を選び、そのほかの全てをZKのオブザーバにします。 +例えば、7台のサーバから成るクォーラムを形成するには、`us-west`から3台、`us-central`から2台、`us-east`から2台のサーバを選択できます。 + +これによって、これらの地域の内1つに到達できなくてもGlobal ZooKeeperへの書き込みが保証されます。 + +全てのサーバにおけるZKの設定は次のようになります: + +``` +clientPort=2184 +server.1=zk1.us-west.example.com:2185:2186 +server.2=zk2.us-west.example.com:2185:2186 +server.3=zk3.us-west.example.com:2185:2186 +server.4=zk1.us-central.example.com:2185:2186 +server.5=zk2.us-central.example.com:2185:2186 +server.6=zk3.us-central.example.com:2185:2186:observer +server.7=zk1.us-east.example.com:2185:2186 +server.8=zk2.us-east.example.com:2185:2186 +server.9=zk3.us-east.example.com:2185:2186:observer +server.10=zk1.eu-central.example.com:2185:2186:observer +server.11=zk2.eu-central.example.com:2185:2186:observer +server.12=zk3.eu-central.example.com:2185:2186:observer +server.13=zk1.ap-south.example.com:2185:2186:observer +server.14=zk2.ap-south.example.com:2185:2186:observer +server.15=zk3.ap-south.example.com:2185:2186:observer +``` + +さらに、ZKのオブザーバは次のように設定する必要があります: + +``` +peerType=observer +``` + +##### サービスの開始 + +```shell +$ bin/pulsar-daemon start global-zookeeper +``` + +#### クラスタのメタデータの初期化 + +新しいクラスタをセットアップする場合、最初に初期化する必要のあるメタデータがいくつか存在します。 +次のコマンドでPulsarのメタデータだけではなくBookKeeperの準備も行う事ができます。 + +```shell +$ bin/pulsar initialize-cluster-metadata --cluster us-west \ + --zookeeper zk1.us-west.example.com:2181 \ + --global-zookeeper zk1.us-west.example.com:2184 \ + --service-url http://pulsar.us-west.example.com:8080/ \ + --service-url-tls https://pulsar.us-west.example.com:8443/ +``` + +#### BookKeeper + +Bookieホストはディスク上にデータを保存する責任があり、良好なパフォーマンスを確保するためには適切なハードウェア構成を持つ事が非常に重要です。 + +キャパシティには2つの重要な側面があります: + +- 読み書きに対するディスクI/Oのキャパシティ +- ストレージのキャパシティ + +Bookieに書き込まれたエントリは、Pulsar BrokerにAck (確認応答) を返す前に常にディスク上で同期されます。 +書き込みのレイテンシを低くするために、BookKeeperは複数のデバイスを使用するように設計されています: + +- 耐久性を確保するための_Journal_ + + - シーケンシャルな書き込みに対しては、このデバイスで高速な_fsync_操作が可能である事が重要です。 + 通常、小型で高速なSSDか、RAIDコントローラとバッテリバックアップ式のライトキャッシュを備えたHDDが適しています。 + どちらのソリューションもfsyncのレイテンシは~0.4 msに達します。 + +- _"Ledgerストレージデバイス"_ + + - これは全てのConsumerがメッセージのAckを返すまでの間データが格納される場所です。 + 書き込みはバックグラウンドで行われるため、書き込みI/Oはそれほど重要ではありません。 + 読み込みはほとんどのタイプでシーケンシャルに行われ、一部のConsumerがバックログからメッセージを取り出している場合にのみ発生します。 + 一般的な構成では、大量のデータを保存できるようにRAIDコントローラを備えた複数のHDDを使用します。 + +##### 設定 + +`conf/bookkeeper.conf` の設定の必要最小限の変更は次の通りです: + +```shell +# Change to point to journal disk mount point +journalDirectory=data/bookkeeper/journal + +# Point to ledger storage disk mount point +ledgerDirectories=data/bookkeeper/ledgers + +# Point to local ZK quorum +zkServers=zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181 + +# Change the ledger manager type +ledgerManagerType=hierarchical +``` + +Apache BookKeeperの詳細なドキュメントは http://bookkeeper.apache.org/ を参照してください。 + +##### サービスの開始 + +Bookieを起動します: +```shell +$ bin/pulsar-daemon start bookie +``` + +Bookieが正常に動作している事を確認します: + +```shell +$ bin/bookkeeper shell bookiesanity +``` + +これによってローカルのBookieに新しいLedgerが作成され、少数のエントリを書き込み、それらを読み込んで最後にLedgerを削除します。 + +#### Broker + +Pulsar Brokerはローカルディスクを使用しないため特別なハードウェアの検討を必要としません。 +ソフトウェアが十分に利用できる高速なCPUと10GbpsのNICが推奨されます。 + +`conf/broker.conf` の最小限の設定変更は次の通りです: + +```shell +# Local ZK servers +zookeeperServers=zk1.us-west.example.com:2181,zk2.us-west.example.com:2181,zk3.us-west.example.com:2181 + +# Global Zookeeper quorum connection string. Here we just need to specify the +# servers located in the same cluster +globalZookeeperServers=zk1.us-west.example.com:2184,zk2.us-west.example.com:2184,zk3.us-west.example.com:2184 + +clusterName=us-west +``` + +##### Brokerサービスの開始 + +```shell +$ bin/pulsar-daemon start broker +``` + +#### Service Discovery + +Service Discoveryコンポーネントは、クライアントが使用する単一のURLを提供するために使用されます。 + +利用者は提供されたディスカバリサービスか、何らかの他の方法を使用できます。 +唯一の要件は、クライアントが `http://pulsar.us-west.example.com:8080/` にHTTPリクエストを送信した時、 +それが (DNSやIP、HTTPリダイレクトなどを通して) アクティブなBroker 1台に優先度なしでリダイレクトされなければならない事です。 + +Pulsarに含まれるディスカバリサービスはHTTPリダイレクトで動作し、ZooKeeper上のアクティブなBrokerのリストを管理します。 + +`conf/discovery.conf` にZKサーバを追記してください: +```shell +# Zookeeper quorum connection string +zookeeperServers=zk1.us-west.example.com:2181,zk2.us-west.example.com:2181,zk3.us-west.example.com:2181 + +# Global zookeeper quorum connection string +globalZookeeperServers=zk1.us-west.example.com:2184,zk2.us-west.example.com:2184,zk3.us-west.example.com:2184 +``` + +サービスを開始します: + +``` +$ bin/pulsar-daemon start discovery +``` + +#### adminクライアントと検証 + +この時点で、クラスタを利用する準備が整ったはずです。 +adminクライアントとして機能するクライアントマシンを構成できるようになりました。 + +クライアントホストの `conf/client.conf` を編集して正しいサービスURLを指定してください: + +```shell +serviceUrl=http://pulsar.us-west.example.com:8080/ +``` + +##### 新しいテナントの準備 + +新しいテナントがシステムを利用できるようにするためには、新しいプロパティを作成しなければいけません。 +通常、この作業はPulsarクラスタの管理者または自動化されたツールによって行われます: + +```shell +$ bin/pulsar-admin properties create test \ + --allowed-clusters us-west \ + --admin-roles test-admin-role +``` + +これによって、ロール `test-admin-role` 持つユーザは、クラスタ `us-west` のみの利用を許可されたプロパティ `test` の構成を管理できるようになります。 + +ここから、テナントは自身のリソースを自身で管理できます。 + +最初のステップはネームスペースの作成です。 +ネームスペースは多くのトピックを含む事のできる管理単位です。 +一般的なプラクティスは、単一のテナントから異なる用途ごとにネームスペースを作成する事です。 + +```shell +$ bin/pulsar-admin namespaces create test/us-west/ns1 +``` + +##### ProducerとConsumerのテスト + +これでメッセージを送受信するための全ての準備が整いました。 +システムをテストする最も簡単な方法は、`pulsar-perf` クライアントツールです。 + +たった今作成したネームスペースの中のトピックを使用しましょう。 +トピックはProducerまたはConsumerがそのトピックを初めて使用する時に自動的に作成されます。 + +今回の場合、トピック名は次のようになります: +``` +persistent://test/us-west/ns1/my-topic +``` + +トピック上にサブスクリプションを作成し、メッセージを待ち受けるConsumerを起動します: + +```shell +$ bin/pulsar-perf consume persistent://test/us-west/ns1/my-topic +``` + +固定レートでメッセージを発行し、10秒ごとに統計情報をレポートするProducerを起動します: + +```shell +$ bin/pulsar-perf produce persistent://test/us-west/ns1/my-topic +``` + +トピックの統計情報をレポートするには次のようにします: +```shell +$ bin/pulsar-admin persistent stats persistent://test/us-west/ns1/my-topic +``` + + +-------------------------------------------------------------------------------- + +## モニタリング + +### Brokerの統計情報 + +Pulsar Brokerのメトリクスは複数のBrokerから収集され、JSON形式で送出されます。 + +メトリクスには主に2つのタイプが存在します: + +* 個別のトピックの統計情報を含む、Destinationダンプ +```shell +bin/pulsar-admin broker-stats destinations +``` + +* Brokerの情報とネームスペースレベルで集約されたトピックの統計情報を含む、Brokerメトリクス +```shell +bin/pulsar-admin broker-stats monitoring-metrics +``` + +全てのメッセージレートは1分ごとに更新されます。 + +### BookKeeperの統計情報 + +BookKeeperで動作する統計フレームワークがいくつか存在しており、`conf/bookkeeper.conf` の `statsProviderClass` の値を変更する事で有効化できます。 + +上記の手順に従うと、`DataSketchesMetricsProvider` が有効になります。 +これはレイテンシの分位値をレートや数と共に計算するための非常に効果的な方法を備えます。 + +統計情報は一定期間ごとにJSONファイルにダンプされ、毎回上書きされます。 + +```properties +statsProviderClass=org.apache.bokkeeper.stats.datasketches.DataSketchesMetricsProvider +dataSketchesMetricsJsonFileReporter=data/bookie-stats.json +dataSketchesMetricsUpdateIntervalSeconds=60 +``` diff --git a/docs/locale/ja/Documentation.md b/docs/locale/ja/Documentation.md new file mode 100644 index 0000000000000..ade0fbc3d3706 --- /dev/null +++ b/docs/locale/ja/Documentation.md @@ -0,0 +1,15 @@ +# Pulsarのドキュメンテーション + +* [Pular入門](GettingStarted.md) +* [システム概要](Architecture.md) +* 運用管理 + - [クラスタのセットアップ](ClusterSetup.md) + - [adminツールとAPI](AdminTools.md) +* 特徴的な機能 + - [認証](Authentication.md) + - [認可](Authorization.md) + - [ジオレプリケーション](GeoReplication.md) + - [WebSocket API](WebSocket.md) + - [Apache Stormのためのアダプタ](PulsarStorm.md) +* 内部仕様 + - [バイナリプロトコルの仕様](BinaryProtocol.md) diff --git a/docs/locale/ja/GeoReplication.md b/docs/locale/ja/GeoReplication.md new file mode 100644 index 0000000000000..0b717ed798762 --- /dev/null +++ b/docs/locale/ja/GeoReplication.md @@ -0,0 +1,110 @@ + +# Pulsar ジオレプリケーション + + + +- [レプリケーションモデル](#レプリケーションモデル) +- [レプリケーション設定](#レプリケーション設定) + - [プロパティへの権限付与](#プロパティへの権限付与) + - [グローバルネームスペースの作成](#グローバルネームスペースの作成) + - [グローバルトピックの利用](#グローバルトピックの利用) + + + +## レプリケーションモデル + +複数のクラスタを設定されたプロパティはそれらのクラスタ間においてレプリケーションを有効にできます。レプリケーションはネームスペースレベルで利用者が直接管理します。グローバルネームスペース内のすべてのトピックがレプリケートされます。利用者はグローバルネームスペースを作成し、2つあるいはそれ以上のクラスタ間でレプリケートされるよう設定します。そのネームスペース内のトピックに発行されたすべてのメッセージは、設定したすべてのクラスタにレプリケートされます。 + +メッセージはまずローカルクラスタに永続化され、そして非同期にリモートクラスタに転送されます。 + +通常時、接続の問題がない場合、メッセージはローカルのConsumerに配信されると同時に即座にレプリケートされます。一般的にend-to-endの配送にかかるレイテンシはリモートの地域間のネットワーク*RTT* (Round Trip Time; 往復遅延時間) によって定義されます。 + +アプリケーションはリモートクラスタが到達不可能 (例. ネットワークが分離されている状況) であっても、ProducerとConsumerをどのクラスタにも作ることができます。 + +サブスクリプションはそれが作成されたクラスタ内に閉じており、クラスタ間で転送されることはありません。 + +![Replication Diagram](../../img/GeoReplication.png) + +上の例ではトピックは***Cluster-A***, ***Cluster-B***, ***Cluster-C***という3つのクラスタにレプリケートされます。 + +任意のクラスタにproduceされたすべてのメッセージはすべてのクラスタのすべてのサブスクリプションに配送されます。この例では、***C1***と***C2***の両方は***P1***, ***P2***, ***P3***に発行されたすべてのメッセージを受け取ります。Producerごとのメッセージの順序は保証されます。 + +## レプリケーション設定 + +### プロパティへの権限付与 + +クラスタ間のレプリケーションを行うため、テナントにクラスタを利用する権限が必要です。この権限はプロパティ作成時に付与するか、後で更新できます。 + +作成時、利用したいクラスタを指定します: +```shell +$ bin/pulsar-admin properties create my-property \ + --admin-roles my-admin-role \ + --allowed-clusters us-west,us-east,us-cent +``` + +既存のプロパティの権限を更新する際は、`create`の代わりに`update`を使用します。 + +### グローバルネームスペースの作成 + +レプリケーションを利用するためには*グローバル*トピック、すなわちグローバルネームスペースに属し、特定のクラスタに紐付けられていないトピックが必要となります。 + +グローバルネームスペースは***global***仮想クラスタの中に作成される必要があります: + +```shell +$ bin/pulsar-admin namespaces create my-property/global/my-namespace +``` + +最初はネームスペースはどのクラスタにも紐付けられていません。 + +```shell +$ bin/pulsar-admin namespaces set-clusters + my-property/global/my-namespace \ + --clusters us-west,us-east,us-cent +``` + +ネームスペースのレプリケーション先クラスタは進行中のトラフィックを中断することなく、いつでも変更が可能です。設定が変更されると即座にすべてのクラスタのレプリケーションチャンネルはセットアップあるいは停止されます。 + +### グローバルトピックの利用 + +この時点でProducerまたはConsumerを単に作成すれば、自動的にグローバルトピックを作成できます。 + +一般的に各アプリケーションはローカルクラスタの`serviceUrl`を使用します。 + +#### 選択的レプリケーション + +デフォルトでは、メッセージはネームスペースに設定されているすべてのクラスタにレプリケートされます。メッセージのレプリケーションリストを指定することでレプリケーション先を制限できます。するとメッセージは一部のクラスタのみにレプリケートされます。 + +Java APIでは、これは`MessageBuilder`において行われます: +```java +... +List restrictReplicationTo = new ArrayList<>(); +restrictReplicationTo.add("us-west"); +restrictReplicationTo.add("us-east"); + +Message message = MessageBuilder.create() + .setContent("my-payload".getBytes()) + .setReplicationClusters(restrictReplicationTo) + .build(); + +producer.send(message); +``` + +#### トピックの統計情報 + +グローバルトピックの統計情報は通常のトピックと同じAPIとツールによって取得できます: + +```shell +$ bin/pulsar-admin persistent stats persistent://my-property/global/my-namespace/my-topic +``` + +各クラスタは入力/出力のレプリケーションのレートおよびバックログを含む自身の統計情報をレポートします。 + +#### グローバルトピックの削除 + +複数の地域に存在するグローバルトピックを直接削除はできません。削除の処理は自動的に行われるトピックのガベージコレクションに依存します。 + +Pulsarではトピックがもう利用されていないとき、すなわちProducerまたはConsumerが一つも接続しておらず、***かつ***サブスクリプションが存在しないときに自動的に削除されます。 + +グローバルトピックにおいて、各地域はフォールトトレラントな仕組みを使用して、そのトピックをいつローカルで削除するのが安全かを判断します。 + +グローバルトピックを削除するために、そのトピックのすべてのProducerとConsumerを閉じ、すべてのレプリケーション先クラスタにおけるローカルなサブスクリプションを削除します。Pulsarがシステム内に有効なサブスクリプションが残っていないと判断すると、そのトピックをガベージコレクトします。 diff --git a/docs/locale/ja/GettingStarted.md b/docs/locale/ja/GettingStarted.md new file mode 100644 index 0000000000000..03922589bf069 --- /dev/null +++ b/docs/locale/ja/GettingStarted.md @@ -0,0 +1,148 @@ + +# Pulsar入門 + + + +- [基本コンセプト](#基本コンセプト) + - [トピック名](#トピック名) + - [サブスクリプションモード](#サブスクリプションモード) + - [ソフトウェアの入手](#ソフトウェアの入手) +- [スタンドアローンなPulsarサーバの起動](#スタンドアローンなpulsarサーバの起動) +- [PulsarのJavaクライアントAPIの使用](#pulsarのjavaクライアントapiの使用) + - [Consumer](#consumer) + - [Producer](#producer) + + + +## 基本コンセプト + +Pulsarはpub-subパラダイムに基づいて構築されたメッセージングシステムです。 +**トピック**は**Producer**と**Consumer**を結びつける基本的なリソースです。 + +Producerはトピックに接続してメッセージを発行する事ができます。 +Consumerはトピックを**購読**してメッセージを受信する事ができます。 + +一度サブスクリプションが作成されると、たとえConsumerが切断された場合でも、 +Consumerから処理の成功を通知する**Ack (確認応答) **が返されるまで全てのメッセージは +システムによって*保持*されます。 + +### トピック名 + +トピック名は次のようになります: +``` +persistent://my-property/us-west/my-namespace/my-topic +``` + +トピック名の構造は、Pulsarのマルチテナント性に関連しています。 +この例では: + * `persistent` → + 全てのメッセージが複数のディスクに永続化されるトピックである事を示します。 + これは現時点でサポートされている唯一のトピック形式です。 + * `my-property` → + **プロパティ**はPulsarインスタンスにおける*テナント*を示す識別子です。 + * `us-west` → + トピックが存在する**クラスタ**です。 + 典型的には、地理的地域やデータセンタごとにクラスタが存在する事になります。 + * `my-namespace` → + **ネームスペース**は管理単位であり、関連するトピックのグループを表します。 + ほとんどの設定はネームスペースレベルで行われます。各プロパティは複数のネームスペースを持つ事が可能です。 + * `my-topic` → + トピック名の最後の部分です。この部分は自由形式であり、システム上の特別な意味は持ちません。 + +### サブスクリプションモード + +各トピックは複数の**サブスクリプション**を持つ事ができます。 +それぞれのサブスクリプションは異なる名前を持ち、またサブスクリプションごとに異なるタイプを指定できます: + + * **Exclusive** → + 1つのConsumerだけがこのサブスクリプションに所属する事を許されます。メッセージの順番は保証されます。 + * **Shared** → + 複数のConsumerが同じサブスクリプションに接続し、メッセージは利用可能なConsumerの間でラウンドロビンで配信されます。 + メッセージの順番は入れ替わる可能性があります。 + * **Failover** → + 1つのConsumerだけがアクティブにメッセージを受信し、他のConsumerはスタンバイ状態になります。 + メッセージの順番は保証されます。 + +詳しい説明は[アーキテクチャ](Architecture.md)のページを参照してください。 + +## ソフトウェアの入手 + +次の場所から最新のバイナリリリースをダウンロードしてください。 + +``` +https://github.com/yahoo/pulsar/releases/latest +``` + +```shell +$ tar xvfz pulsar-X.Y-bin.tar.gz +$ cd pulsar-X.Y +``` + +## スタンドアローンなPulsarサーバの起動 + +アプリケーション開発や実際に稼働するサービスの迅速なセットアップのために、 +Pulsarのスタンドアローンモードを使用する事ができます。 +このモードでは、Broker, ZooKeeper, BookKeeperの3コンポーネントを +単一のJVMプロセスで起動します。 + +```shell +$ bin/pulsar standalone +``` + +Pulsarのサービスはすぐに利用可能となり、`http://localhost:8080/` +をサービスのURLとしてクライアントに使用させる事ができます。 + +サンプルのネームスペース `sample/standalone/ns1` が既に利用可能な状態になっています。 + +## PulsarのJavaクライアントAPIの使用 + +Pulsarクライアントライブラリの依存関係をインクルードしてください。 + +最新のバージョンは [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.yahoo.pulsar/pulsar-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.yahoo.pulsar/pulsar-client) です。 + +```xml + + com.yahoo.pulsar + pulsar-client + ${pulsar.version} + +``` + +### Consumer + +```java +PulsarClient client = PulsarClient.create("http://localhost:8080"); + +Consumer consumer = client.subscribe( + "persistent://sample/standalone/ns1/my-topic", + "my-subscribtion-name"); + +while (true) { + // 1つのメッセージを待ち受け + Message msg = consumer.receive(); + + System.out.println("Received message: " + msg.getData()); + + // Brokerがメッセージを削除できるようにするためのAck + consumer.acknowledge(msg); +} + +client.close(); +``` + + +### Producer + +```java +PulsarClient client = PulsarClient.create("http://localhost:8080"); + +Producer producer = client.createProducer( + "persistent://sample/standalone/ns1/my-topic"); + +// 10のメッセージをトピックに発行 +for (int i = 0; i < 10; i++) { + producer.send("my-message".getBytes()); +} + +client.close(); +``` diff --git a/docs/locale/ja/PulsarStorm.md b/docs/locale/ja/PulsarStorm.md new file mode 100644 index 0000000000000..e4d29f85470fb --- /dev/null +++ b/docs/locale/ja/PulsarStorm.md @@ -0,0 +1,107 @@ +# Apache StormのためのPulsarアダプタ + + + +- [概要](#概要) +- [Pulsar Stormアダプタの利用](#pulsar-stormアダプタの利用) + - [Pulsar Spout](#pulsar-spout) + - [Pulsar Bolt](#pulsar-bolt) +- [実装例](#実装例) + + + +## 概要 +Pulsar StormはApache Storm Topologyと連携するためのアダプタであり、データの送受信を行うためのStromの実装を提供します。 + +アプリケーションはPulsar Spoutを通してStorm Topologyにデータを注入したり、Pulsar Boltを通してStorm Topologyからデータを取り出すことができます。 + +## Pulsar Stormアダプタの利用 +Pulsar Stormアダプタの依存をincludeします: + +```xml + + com.yahoo.pulsar + pulsar-storm + ${pulsar.version} + +``` + +## Pulsar Spout +Pulsar Spoutを使って、Storm Topologyは[Pulsarのトピック](Architecture.md#トピック)に発行されたデータをconsumeできます。Pulsar Spoutは受信したメッセージとクライアントが提供するMessageToValuesMapperをもとにStorm Tupleを発行します。 + +下流のBoltでの処理に失敗したTupleはSpoutから再注入されます。この再注入は指数バックオフアルゴリズムに従い、設定可能なタイムアウト (デフォルト: 60秒) または設定可能なリトライ回数のどちらかに達するまで行われます。その後、Consumerにより処理成功の応答が返されます。 + +```java +// Pulsarクライアントの設定 +ClientConfiguration clientConf = new ClientConfiguration(); + +// Pulsar Consumerの設定 +ConsumerConfiguration consumerConf = new ConsumerConfiguration(); + +@SuppressWarnings("serial") +MessageToValuesMapper messageToValuesMapper = new MessageToValuesMapper() { + + @Override + public Values toValues(Message msg) { + return new Values(new String(msg.getData())); + } + + @Override + public void declareOutputFields(OutputFieldsDeclarer declarer) { + // 出力フィールドを宣言 + declarer.declare(new Fields("string")); + } +}; + +// Pulsar Spoutの設定 +PulsarSpoutConfiguration spoutConf = new PulsarSpoutConfiguration(); +spoutConf.setServiceUrl("http://broker.messaging.usw.example.com:8080"); +spoutConf.setTopic("persistent://my-property/usw/my-ns/my-topic1"); +spoutConf.setSubscriptionName("my-subscriber-name1"); +spoutConf.setMessageToValuesMapper(messageToValuesMapper); + +// Pulsar Spoutの作成 +PulsarSpout spout = new PulsarSpout(spoutConf, clientConf, consumerConf); +``` + +## Pulsar Bolt +Pulsar Boltを使って、Storm Topology内のデータを[Pulsarのトピック](Architecture.md#トピック)に発行できます。Pulsar Boltは受信したStorm Tupleとクライアントが提供するTupleToMessageMapperをもとにメッセージを発行します。 + +異なるトピックのメッセージを発行するためにパーティションドトピックを利用できます。その場合TupleToMessageMapperの実装において、メッセージに「キー」を用意する必要があります。同じキーを持つメッセージは同じトピックに送信されるようになります。 + +```java +// Pulsarクライアントの設定 +ClientConfiguration clientConf = new ClientConfiguration(); + +// Pulsar Producerの設定 +ProducerConfiguration producerConf = new ProducerConfiguration(); + +@SuppressWarnings("serial") +TupleToMessageMapper tupleToMessageMapper = new TupleToMessageMapper() { + + @Override + public Message toMessage(Tuple tuple) { + String receivedMessage = tuple.getString(0); + // メッセージを処理 + String processedMsg = receivedMessage + "-processed"; + return MessageBuilder.create().setContent(processedMsg.getBytes()).build(); + } + + @Override + public void declareOutputFields(OutputFieldsDeclarer declarer) { + // 出力フィールドを宣言 + } +}; + +// Pulsar Boltの設定 +PulsarBoltConfiguration boltConf = new PulsarBoltConfiguration(); +boltConf.setServiceUrl("http://broker.messaging.usw.example.com:8080"); +boltConf.setTopic("persistent://my-property/usw/my-ns/my-topic2"); +boltConf.setTupleToMessageMapper(tupleToMessageMapper); + +// Pulsar Boltの作成 +PulsarBolt bolt = new PulsarBolt(boltConf, clientConf); +``` + +## 実装例 +完全な実装の例は[StormExample.java](../../../pulsar-storm/src/test/java/com/yahoo/pulsar/storm/example/StormExample.java)を参照してください。 diff --git a/docs/locale/ja/README.md b/docs/locale/ja/README.md new file mode 100644 index 0000000000000..3ab898452bfc1 --- /dev/null +++ b/docs/locale/ja/README.md @@ -0,0 +1,44 @@ +***訳注: [v1.16のドキュメント](https://github.com/yahoo/pulsar/tree/v1.16/docs)を日本語訳したものです。*** + +![logo](../../img/pulsar.png) + +Pulsarは、非常に柔軟なメッセージングモデルと直感的なクライアントAPIを備えた分散pub-subメッセージングプラットフォームです。 + +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.yahoo.pulsar/pulsar/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.yahoo.pulsar/pulsar) + + +## 主な特徴 +* 水平方向にスケーラブル (数百万の独立したトピックと毎秒数百万発行されるメッセージ) +* 強い順序と一貫性の保証 +* 低レイテンシな永続性のあるストレージ +* トピックとキューのセマンティクス +* ロードバランサ +* ホステッドサービスとしてデプロイ可能な設計: + * マルチテナント + * 認証 + * 認可 + * リソース割り当て + * 著しく異なるワークロードのサポート + * 選択的なハードウェアの分離 +* Consumerのカーソル位置を常に把握 +* 提供準備、管理、統計のためのREST API +* ジオレプリケーション +* 透過的なパーティションドトピックの処理 +* 透過的なメッセージのバッチ処理 + +## ドキュメンテーション + +* [Pulsar入門](GettingStarted.md) +* [システム概要](Architecture.md) +* [ドキュメンテーションのインデックス](Documentation.md) +* [Yahoo Eng Blogのアナウンス記事](https://yahooeng.tumblr.com/post/150078336821/open-sourcing-pulsar-pub-sub-messaging-at-scale) + +## 連絡先 +* 開発に関する議論は [Pulsar-Dev](https://groups.google.com/d/forum/pulsar-dev) へ +* ユーザからの質問は [Pulsar-Users](https://groups.google.com/d/forum/pulsar-users) へ + +## ライセンス + +Copyright 2016 Yahoo Inc. + +Apache License Version 2.0に基づいて使用許諾されます: http://www.apache.org/licenses/LICENSE-2.0 diff --git a/docs/locale/ja/WebSocket.md b/docs/locale/ja/WebSocket.md new file mode 100644 index 0000000000000..153e864c81b30 --- /dev/null +++ b/docs/locale/ja/WebSocket.md @@ -0,0 +1,276 @@ +# Pulsar WebSocket API + + + +- [WebSocketサービスの実行](#websocketサービスの実行) +- [APIリファレンス](#apiリファレンス) + - [Producer](#producer) + - [Consumer](#consumer) + - [エラーコード](#エラーコード) +- [実装例](#実装例) + - [Python](#python) + - [NodeJS](#nodejs) + + + +***このAPIは実験的なものであり、仕様は最終的に確定されるまでに変更が加えられる可能性があります。 +私たちはこのWebSocket APIに対するフィードバックを求めています。*** + +PulsarのWebSocket APIは、PulsarとJVMの外の言語とのやりとりを簡単に行う方法を提供するためのものです。 + +WebSocketを通してメッセージのproduceとconsumeを行う事ができ、 +Javaのクライアントライブラリから利用可能な全ての機能を使用できます。 + +## WebSocketサービスの実行 + +既にWebSocketサービスが有効になっているスタンドアローンなPulsarを使用する他に、 +WebSocketサービスをデプロイする2つの方法があります。 + +#### Pulsar Brokerへの組み込み + +`conf/broker.conf` でWebSocketを有効化します: + +```shell +webSocketServiceEnabled=true +``` + +これによって、既にBrokerで実行されているHTTPサーバの中でWebSocketサービスも実行されます。 + +#### 独立したコンポーネントとしてのWebSocket + +WebSocketサービスは別のコンポーネントとして単独で動作する事ができます。 + +設定は `conf/websocket.conf` にあり、変更の必要がある最小限のパラメータは次の通りです: + +```shell +globalZookeeperServers=... + +# Port to use to server HTTP request +webServicePort=8080 + +# Name of the pulsar cluster to connect to +clusterName=... +``` + +そして、WebSocketサービスを実行するには次のようにします: + +```shell +$ bin/pulsar-daemon start websocket +``` + +## APIリファレンス + +WebSocketのエンドポイントは、メッセージのproduce用とconsume用の2つが存在しています。 +また、全てのやりとりはJSON形式のメッセージを通して行われます。 + +### Producer + +特定のトピックに対するProducerを作成するために、WebSocketのセッションをオープンします。 + +```perl +http://{serviceUrl}:8080/ws/producer/persistent/{property}/{cluster}/{namespace}/{topic} +``` + +##### メッセージの送信 + +```json +{ + "payload": "SGVsbG8gV29ybGQ=", + "properties": {"key1": "value1", "key2": "value2"}, + "context": "1" +} +``` + +| キー | 型 | 要求 | 説明 | +|:----------------------|:---------------:|:-----------:|:------------------------------------------------------------:| +| `payload` | String | 必須 | Base-64エンコードされたペイロード | +| `properties` | Key-Value pairs | 任意 | アプリケーションによって定義されたプロパティ | +| `context` | String | 任意 | アプリケーションによって定義されたリクエスト識別子 | +| `key` | String | 任意 | パーティションドトピックの場合、使用するパーティション | +| `replicationClusters` | List | 任意 | レプリケーションを行うクラスタをここで指定したものだけに制限 | + + +##### サーバからの応答 + +###### 成功時のレスポンス +```json +{ + "result": "ok", + "messageId": "CAAQAw==", + "context": "1" + } +``` +###### 失敗時のレスポンス +```json + { + "result": "send-error:3", + "errorMsg": "Failed to de-serialize from JSON", + "context": "1" + } +``` + +| キー | 型 | 要求 | 説明 | +|:------------|:------:|:-----------:|:---------------------------------------------------:| +| `result` | String | 必須 | 成功時は `ok` 、失敗時はエラーメッセージ | +| `messageId` | String | 必須 | produceされたメッセージに割り当てられたメッセージID | +| `context` | String | 任意 | アプリケーションによって定義されたリクエスト識別子 | + + +### Consumer + +特定のトピックに対するConsumerを作成するために、WebSocketのセッションをオープンします。 + +```perl +http://{serviceUrl}:8080/ws/consumer/persistent/{property}/{cluster}/{namespace}/{topic}/{subscription} +``` + +##### メッセージの受信 + +WebSocketセッション上でサーバからメッセージがプッシュされます: + +```json +{ + "messageId": "CAAQAw==", + "payload": "SGVsbG8gV29ybGQ=", + "properties": {"key1": "value1", "key2": "value2"}, + "publishTime": "2016-08-30 16:45:57.785", + "context": "1" +} +``` + +| キー | 型 | 要求 | 説明 | +|:--------------|:---------------:|:-----------:|:--------------------------------------------------------:| +| `messageId` | String | 必須 | メッセージID | +| `payload` | String | 必須 | Base-64エンコードされたペイロード | +| `properties` | Key-Value pairs | 任意 | アプリケーションによって定義されたプロパティ | +| `publishTime` | String | 必須 | produceされた時間のタイムスタンプ | +| `context` | String | 任意 | アプリケーションによって定義されたリクエスト識別子 | +| `key` | String | 任意 | Producerによってセットされたオリジナルのルーティングキー | + +##### メッセージへの応答 + +Pulsar Brokerがメッセージを削除できるように、Consumerはメッセージが正常に処理できたという応答を返す必要があります。 + +```json +{ + "messageId": "CAAQAw==" +} +``` + +| キー | 型 | 要求 | 説明 | +|:------------|:------:|:-----------:|:-----------------------------------:| +| `messageId` | String | 必須 | 処理したメッセージのメッセージID | + + +### エラーコード + +エラーの場合、サーバは次のエラーコードを使用してWebSocketセッションをクローズします。 + +#### 可能性のあるさまざまなエラータイプ + +| エラーコード | エラーメッセージ | +|:------------:|:---------------------------------| +| 1 | Producerの作成に失敗 | +| 2 | 購読に失敗 | +| 3 | JSONからのデシリアライズに失敗 | +| 4 | JSONへのシリアライズに失敗 | +| 5 | クライアントの認証に失敗 | +| 6 | クライアントが認可されていない | +| 7 | ペイロードの誤ったエンコード | +| 8 | 未知のエラー | + +アプリケーションは、バックオフ期間後にWebSocketセッションを再確立する責任があります。 + +## 実装例 + +### Python +この例では `websocket-client` パッケージをインストールする必要があります。 +それは `pip install websocket-client` を使用するか、[Pypi page](https://pypi.python.org/pypi/websocket-client) からダウンロードしてインストールする事ができます。 + +#### Python Producer + +```python +import websocket, base64, json + +ws = websocket.create_connection( + 'ws://localhost:8080/ws/producer/persistent/sample/standalone/ns1/my-topic') + +# 1つのメッセージを送信します +ws.send(json.dumps({ + 'payload' : base64.b64encode('Hello World'), + 'properties': { + 'key1' : 'value1', + 'key2' : 'value2' + }, + 'context' : 5 +})) + +response = json.loads(ws.recv()) +if response['result'] == 'ok': + print 'Message published successfully' +else: + print 'Failed to publish message:', response +ws.close() +``` + +#### Python Consumer + +```python +import websocket, base64, json + +ws = websocket.create_connection( + 'ws://localhost:8080/ws/consumer/persistent/sample/standalone/ns1/my-topic/my-sub') + +while True: + msg = json.loads(ws.recv()) + if not msg: break + + print 'Received: ', msg, ' - payload:', base64.b64decode(msg['payload']) + + # 正常に処理できた事を応答します + ws.send(json.dumps({'messageId' : msg['messageId']})) + +ws.close() +``` + +### NodeJS + +#### NodeJS Producer + +```javascript +var WebSocket = require('ws'); +var ws = new WebSocket( + "ws://localhost:8080/ws/producer/persistent/my-property/us-west/my-ns/my-topic1"); + +var message = { + "payload" : new Buffer("Hello World").toString('base64'), + "properties": { + "key1" : "value1", + "key2" : "value2" + }, + "context" : "1" +}; + +ws.on('open', function() { + // 1つのメッセージを送信します + ws.send(JSON.stringify(message)); +}); + +ws.on('message', function(message) { + console.log('received ack: %s', message); +}); + +``` + +#### NodeJS Consumer +```javascript +var WebSocket = require('ws'); +var socket = new WebSocket( + "ws://localhost:8080/ws/consumer/persistent/my-property/us-west/my-ns/my-topic1/my-sub1") + +socket.onmessage = function(pckt){ + var receiveMsg = JSON.parse(pckt.data); + var ackMsg = {"messageId" : receiveMsg.messageId} + socket.send(JSON.stringify(ackMsg)); +}; +```