Corda Notary Clusterの構築方法とその高可用性(HA)の検証
この投稿では 、Corda Enterprise(CE) 4.0のNotaryノードの「HA設定」を紹介します。この機能と設定方法はCE4.1でも同じです。また、詳細な構築フローの導入に加えて、Notary Clusterの「高可用性」の検証結果も示したいと思います。
この投稿では、前の投稿で説明したものと同じAWS環境を使用します。HA Notary Serviceは、「二重支払い」防止用のトランザクションデータを共有・管理するため、Percona XtraDB Clusterを使用します。Notary Cluster内の全ノードは、ラウンドロビン方式でトランザクションが消費済みか消費済みでないかをチェックします。
この投稿は、下記Cordaの公式ページを参考にしました。:https://docs.corda.r3.com/releases/4.0/running-a-notary-cluster/toctree.html
A. 本記事のNotary Cluster設定の全体的なイメージ
・Cordaノードは5つのEC2インスタンスで構成します。(PartyA Node、PartyB Node、Notary Node1、Notary Node2、Notary Node3)
・各Notary NodeのNode DBはPostgreSQLを使用します。
・Percona XtraDB Clusterを構成するPercona DBは各ノード内に同梱します。構成図としては以下の通りです。
B. Percona XtraDB Clusterの設定
Notary Clusterは、各ノードのWorkerの間で共有されるNotary StatesをPercona XtraDB Clusterで管理します。Percona XtraDB Clusterのセットアップに関しては、Cordaの公式Webサイトに十分なガイダンスが記載されているため、そちらを参照してください。なお、Percona XtraDB Clusterを構成する一般的なサーバ台数は3台で十分です。5台になると、DBサーバ5台とも同期をとるため、DBへの書き込み処理が遅くなります。一般的な企業の運用でも3台運用が多い為、特別な理由がない限り、3台運用で十分です。
1. https://docs.corda.r3.com/releases/4.0/running-a-notary-cluster/installing-percona.html
2. https://www.percona.com/doc/percona-xtradb-cluster/LATEST/index.html
Percona XtraDB Clusterが正常にインストールできたら、DBにログインします。作成されたテーブルは次のように確認することができます。
これらのテーブルは、Notaryノードがトランザクションが消費済みか消費済みでないかをチェックする(2重支払い防止)ために使用します。テーブルの詳細については、 Corda公式サイトのhttps://docs.corda.r3.com/node-database.htmlをご確認ください。これらのテーブルは、上記で構成されたPercona XtraDB Clusterに更新・同期されます。
因みに、Percona XtraDB Clusterの全てのホスティングEC2の電源がオフになっている場合、EC2を再起動し、Percona XtraDB Clusterサービスを再開しようとすると下記のようなエラーメッセージが表示される場合があります。
通常、最後に電源がオフになったPercona DBを最初に再起動する必要があります。具体的な対応方法については、ログファイル/var/log/mysqld.logおよびPercona Webサイトをご確認ください。
この投稿の構成では、図1に示すように、3つのノードのPercona XtraDB Clusterをセットアップします。これらの3つのノードは、NotaryのWorkerノードとしても使用します。次のセクションでNotary Workerのセットアップ方法を紹介します。
C. Notary Serviceの設定
corda公式サイトで提供されている以下の設定情報には、Notaryノードの「node.conf」ファイルしか説明がなく、情報が少ない為、Notary Clusterを設定するプロセス全体を説明します。
Step1. CorDapps生成用の“build.gradle” 設定ファイルを作成
「build.gradle」ファイルでは、各Notaryノードの構成でNotary Clusterの「serviceLegalName」を指定する必要があります。
上記の「build.gradle」ファイルを保存した後、コマンド「./gradlew deployNodes」を使用してCorDappsをコンパイルすると、すべてのCordaノードのディレクトリが「build / nodes /」ディレクトリの下に配置されます。
以下のように、CorDappsのソースコード(Flow)内、Notary部分に指定したいNotaryの情報に合わせて適宜、変更してください。
serviceHub.networkMapCache.getNotary(CordaX500Name(“HA Notary”, “London”, “GB”))
また、パッケージ「import net.corda.core.identity.CordaX500Name」のインポートも必要です。
因みに、Notary ClusterにRAFTやBFTのコンセンサスアルゴリズムを利用したい場合、次のように設定を追加できます。
詳細の構成については、cordaサンプルリポジトリを参照することもできます。
https://github.com/corda/corda/blob/master/samples/notary-demo/build.gradle
ただし、CordaでのRAFTとBFTの実装は、両方とも試験的な実装であることに注意してください。 CE4.0以降、両方の実装は非推奨になりました。 https://docs.corda.r3.com/releases/4.1/changelog-enterprise.html
Step2. 各Notaryノードの「ノードDB」を作成
設定では、AWSのPostgreSQL Database Instanceを各Notaryノードの「ノードDB」として使用します。 これらのDBは、AWSコンソールから作成できます。
作成のガイダンスは、前の投稿「R3 Cordaノードの高可用性(HA)とその構成方法」の「セクションE」を参照してください。
3つのデータベース「Notary_Cluster_1、Notary_Cluster_2、Notary_Cluster_3」を作成し、エンドポイントアドレスをメモしてください。
Step3. 各Notaryノードの「Notary_node.conf」ファイルを変更
CorDappsをコンパイルした後、「build / nodes /」ディレクトリの下で、Notary Clusterの各Notaryノード「Notary1_node.conf、Notary2_node.conf、Notary3_node.conf」の ファイルが作成されます。
「Percona DB」および「ノードDB」に関する設定をすべての「Notary_node.conf」ファイルに追加します。
Step4. 「ノードDB」用の 移行スクリプトを作成
CorDappsに必要なスキーマ/テーブルが「ノードDB」に必要な為、以下のコマンドで「移行スクリプト」を作成し、スキーマ/テーブルを生成してください。
Cordaの公式サイトには、これらのコマンドについての説明があります。 https://docs.corda.r3.com/database-management.html?highlight=node%20migration#adding-database-migration-scripts-retrospectively-to-an-existing-cordapp
Step5. ブートストラップ(Bootstrapper)の使用
上記Step4を完了すると、ブートストラップを使用してCordaネットワークを作成できます。CorDappsのルートディレクトリからコマンドを実行します。※ブートストラップは開発モード=Trueのみ有効です。
> java -jar corda-tools-network-bootstrapper-4.0.jar — dir build/nodes
正常に実行された後、「Bootstrapping complete!」を返します。
次に、Cordaノードのディレクトリを各CordaノードのホスティングEC2にコピーし、そこから各Cordaノードを起動します。
たとえば、Notary1ディレクトリを「***.***.***.191」のEC2にコピーし、下記コマンドで起動します。
> java –jar corda.jar
そして、利用可能なNotary Serviceをリストして、現在のNotary情報を参照することができます:
これで、Notary Cluster Service(3つのNotaryノード)を含むすべてのCordaノードを正常に起動できます。
D. Notary ServiceのHA検証
これで、すべてのCordaノードが各自のホスティングEC2で正常に起動されました。また、PartyAとPartyBの間でトランザクションを発行すると、正常に完了できることが確認できます。
ここでは、いくつかのパターンで、Notary ClusterのHA検証結果を説明します。
1.各Notary ノードのノードDBの更新について
・Notaryノードは基本的にラウンドロビン方式で順番にトランザクションの検証処理を担当し、各自のノードDBを更新します。また、Notaryノードの 「Validation」機能が“TRUE”の場合、Notaryノードはトランザクションの中身まで検証するため、他のCordaノードから該当トランザクションの関連情報を取得することもあります。
この「Validation」機能が“TRUE”の場合の各自のノードDBの更新について、もっと詳しく説明します。
>発行したトランザクションが、それぞれ関連している場合、たとえば、 トランザクション1. AAA→BBB(Notary1)
トランザクション2. BBB→CCC(Notary2)
トランザクション3. CCC→DDD(Notary3)
だとする(前のトランザクションのOUTPUTを次のINPUTにする)と、トランザクション3を受けたNotary3 は、そのトランザクションを検証するために、トランザクション2→トランザクション1と、トランザクションを辿って検証していくので、その情報を他のCordaノードから取得します。
>発行したトランザクションは、それぞれ関連してない場合、たとえば、トランザクション1. AAA→BBB(Notary1)
トランザクション2. CCC→DDD(Notary2)
トランザクション3. EEE→FFF (Notary3)
だとする(前のトランザクションのOUTPUTと次のINPUTが別物だとする)と、トランザクション3を受けたNotary3 は、そのトランザクションを検証するために、トランザクション2やトランザクション1を必要としないので、トランザクション1と2の情報は、Notary3は取得しません。トランザクション1や2の情報が Notary3 に入るタイミングは、INPUTが「BBB」や「DDD」が指定されているトランザクションがNotary3に来た時です。
2.Notary Clusterの中で、1つのNotaryノードをシャットダウンします
- PartyAとPartyBの間のトランザクションへの影響はなく、正常に完了できます.
> Notaryノードはラウンドロビン方式で選択されるため、次のNotaryノードがシャットダウンされる或いは利用できない場合、次に利用可能なNotaryノードを探して、トランザクションを生きているNotaryノードに依頼します。このプロセスの詳細はPartyAのログファイルで確認できます。
- Notary Serviceで必要なデータは各ノード内のPercona DBに格納されており、Percona DBのデータが常に最新で正常であれば、運用し続けることが可能です。
3.Notary Clusterの2つのNotaryノードをシャットダウンする
- PartyAとPartyBの間のトランザクションへの影響はなく、正常に完了できます
>理由は上記と同じです。
> この投稿で使用した「Notary Cluster設定」(セクションCのStep1の構成を参照)では、少なくとも1つのNotaryノードが稼働している場合、Notary Serviceを常に利用できます。
4.NotaryノードでのPercona DBインスタンスをシャットダウンする
- 3台あるうちの2台のPercona DBインスタンスが停止してもトランザクションはエラーなしで完了できます。
>この投稿では、Percona DBの停止をシミュレートするために、「sudo service mysql stop」によってNotaryノードのPercona DBインスタンスを停止して検証を実施しています。
5.NotaryノードでノードDBインスタンスをシャットダウンする
- NotaryノードはノードDBへの接続を失うと自動的にシャットダウンするため、この状況は上記のセッションD‐2およびセッションD-3で説明したものと同じです。
>この投稿では、ノードDBの停止をシミュレートするために、NotaryノードでPostgreSQLインスタンスを停止し検証を実施しています。
E. まとめ
ここでは、3つのノード構成のNotary Clusterの設定プロセスについて説明しました。
CordaはNotary Cluster用のコンセンサスアルゴリズム“RAFT”と“BFT”を提供していますが、これらは実験的な実装であり、まもなく廃止される※ため、この投稿ではラウンドロビン設定を主に紹介しました。
※今後のバージョンアップにより“RAFT”と“BFT”が正式実装される可能性もあります。
「n」個ノードのNotary Clusterは、「n-1」個までのノードの障害(ノードDB、Percona XtraDB Clusterを構成するPercona DB、Notaryノードのシャットダウンなど)に耐えることができることが検証結果により判りました。Notary Clusterでの構成は、Notaryの高可用性は担保できると考えます。
また、Percona XtraDB Clusterを構成するPercona DBは同期を常にとるため、データは常に一緒ですが、各ノードのノードDBはラウンドロビンによる動きから、データの内容は異なります。
よって、ノードDBのデータバックアップは必要なく、実際、ノードDBのデータを初期化(クリア)しても問題なく動作することを確認しています。
Percona DBのデータは運用上、必要ですが、ノードDBのデータについては一時的なものであるため、バックアップの必要はありません。
次回の投稿では、CENMモジュールを利用し、Cordaの実運用環境の構築方法について、紹介する予定です。
記:TIS Blockchain Promotion Office (羅)
Thanks to Kiyotaka Yamasaki.