Amazon Web Services ブログ

AWS で Solana ノードのパフォーマンスを向上させコストを削減する

本記事は、2025 年 9 月 25 日に公開された Improve Solana node performance and reduce costs on AWS を翻訳したものです。翻訳は Blockchain Prototyping Engineer の 深津颯騎 が担当しました。

Solana Agave v2.0.14 は 2024 年 10 月 18 日にリリースされました。
それ以降、Solana ノードのオペレーターから、mainnet-beta の最新スロットとの同期を維持するのに苦労することがあるという報告がありました。
Solana の StackExchange で「catch up」を検索すると、この課題に関する多数の投稿が見つかります。

以前の投稿では、AWS で Solana ノードを実行する方法を説明しました。
この投稿では、より高速な運用と初期同期のためにノードを設定する方法を解説します。
さらに、Amazon Elastic Compute Cloud (Amazon EC2) で Solana ノードのデータ転送のコスト効率を高めるための実験的なトラフィック最適化手法を共有します。

Solana Agave v2.x における変更点

Solana Agave v2.x における最も重要な変更の 1 つは、新しい中央スケジューラです。
これは v1.18.x にも存在していましたが、デフォルトでは無効になっていました。
v2.x のアップデートにより、中央スケジューラがデフォルトで有効になりました。

Solana Agave クライアントのコアコンポーネントとして、中央スケジューラはトランザクション処理アーキテクチャを大幅に変更します。
これは、以前の 4 スレッドによる処理モデルに代わるシングルスレッドによる調整メカニズムである Scheduling Thread を導入します。
この変更について詳しくは、Introducing the Central Scheduler: An Optional Feature of Agave v1.18 を参照してください。

この変更は、推奨される最小 CPU クロック速度に大きな影響を与え、トランザクション処理の最適なパフォーマンスのために、要件が 2.8 GHz から 3.2 GHz に増加しました。
これに基づき、以前のブログ記事で Solana ノードを実行するための推奨 AWS インスタンスタイプを更新し、R7a および I7ie EC2 インスタンスファミリーに切り替えました。
これらのインスタンスファミリーは、さまざまな構成で Solana ノードを実行するために必要な 384 GiB から 1.5 TiB 超の RAM も提供します。

Agave v2.2.15 では、処理ロジックの「ホットパス(頻繁に実行される処理経路)」からブロックストレージ操作を削除することに焦点を当てた、その他の重要なパフォーマンス最適化が導入されました。
これにより、ブロックストレージデバイスに必要な 1 秒あたりの入出力操作数 (IOPS) とレイテンシーが削減され、クラウド上で Agave クライアントを実行するコストがさらに削減されました。

アジア太平洋 AWS リージョンにおける Solana の同期における課題の克服

Solana Agave ノードが起動時に事前ダウンロードされたスナップショットを持っていない場合、クライアントは信頼できるバリデーターノードからそのスナップショットをダウンロードします。
これらのノードは --known-validator フラグで設定され、Anza RPC ノード起動コマンドの例に示されています。
しかし、これらの信頼できるバリデーターは、北米またはヨーロッパの AWS リージョンに配置されていることが多く、東京、香港、ソウル、シンガポールなどのアジア太平洋リージョンで実行されているクライアントにとって問題となります。
これらの場所でのスナップショットのダウンロード速度は、通常、北米またはヨーロッパリージョンのクライアントと比較して遅くなります。

スナップショットをダウンロードした後、Agave はスナップショットのスロットが最新より 2,500 スロット以上遅れているかどうかをチェックします。
この差が 2,500 より大きい場合、クライアントはスナップショットを再ダウンロードし、同期プロセスがさらに遅延します。
この問題は GitHub issue #24486 に記録されています。

デフォルトでは、maximum_local_snapshot_age パラメータは 2,500 に設定されています
スナップショットの再ダウンロードを避けるためにこの値を増やすことはできますが、この方法は推奨しません。
Solana は 400 ミリ秒ごとに新しいスロットを生成する (1 分あたり約 150 スロット) ため、この値を高く設定しすぎると、ノードが最新のスロットに追いつかなくなる可能性があります。

アジアパシフィックリージョンで Solana ノードを実行する際のスナップショットダウンロードパフォーマンスを向上させるには、以下を推奨します。

  • 信頼できるノードを特定する:
    • validator.app を使用して、アジア太平洋地域のあなたの場所に近い信頼できるノードの識別子 を見つけます。
    • これらの識別子を agave-validator 起動コマンドの --known-validator フラグのパラメータとして設定します。
    • 警告マークが付いているバリデーターノードの使用は避けてください。
  • スナップショットソースを制限する:
    • --only-known-rpc フラグを使用して、信頼できるノードからのみスナップショットをダウンロードするようにクライアントを設定します。
  • 最小ダウンロード速度を設定する:
    • --minimal-snapshot-download-speed フラグを使用して、必要な最小スナップショットダウンロード速度を定義し、低速なソースからのダウンロードを防ぎます。テストでは、104,857,600 (100 MiBps) を使用しました。

これらの最適化を実装することで、初期同期を高速化し、アジア太平洋リージョンにおける Solana ノードのデプロイをより高速で信頼性の高いものにすることができます。

Agave RPC ノードのデータ転送コストの最適化

Solana Agave クライアントは、Turbine と呼ばれるデータ伝播プロトコルにより、大量のアウトバウンドデータトラフィックを生成します。
近年、月間トラフィック量は増加しており、RPC のみとして構成されたノードであっても、現在は 100 TiB から 200 TiB 以上の範囲になっています。
これらのコストをより効果的に管理するために、Solana ノードの同期を維持するために最小限必要なアウトバウンドデータスループットを決定するための一連の実験を実施しました。

まず、ノードの「Slots Behind」メトリクスを 1 分ごとにチェックし、初期同期が完了した後に実行するスクリプトを作成しました。
1 分間隔は、Solana ノードが正常に同期しているか、遅れ始めているかを確実に検出できるのに通常十分です。
「Slots Behind」メトリクスがゼロに達し、ノードが完全に同期されたことを示すと、別のスクリプトがユーザー定義の帯域幅制限を MiBps 単位で適用します。
「Slots Behind」メトリクスが 10 を超えると、ノードが追いつくまで制限が一時的に解除されます。
運用効率を維持するために、システムはこれらの制限から内部ネットワークトラフィックを除外します。
標準的な内部 IP 範囲 (10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16) 内のトラフィックは制限の対象外とし、内部 IP を使用する AWS アプリケーションが正常に機能することを確保します。
この機能は RPC ノードに対して非常に効果的ですが、コンセンサスノードには実装すべきではありません。
コンセンサスノードでアウトバウンドトラフィックを制限すると、パフォーマンスが低下するため、最適なネットワーク参加のためには推奨されません。

このトラフィック最適化手法をテストするために、eu-central-1 リージョンで 5 台の i7ie.12xlarge EC2 インスタンスを使用して 5 日間の比較テストを実施しました。
4 つのノードにトラフィックシェーピングスクリプトを設定し、1 つのコントロールノードには制限を設けず、「Current Slots」と「Slots Behind」のメトリクスを収集して、ノードの同期速度と安定性を比較しました。

テストの結果、ノードは 20 MiBps という低いアウトバウンドトラフィック帯域幅 (月間約 6.5 TiB) で同期を維持でき、最適な価格対パフォーマンス比は 40-50 MiBps で達成され、推定データ転送コストを 85% 以上削減できることが示されました。
テスト期間全体を通じて、5 つのノードすべてが同期を維持し、アウトバウンド帯域幅を削減してもノードの同期状態に影響しないことが確認されました。
驚くべきことに、Agave v2.2.16 でアウトバウンドトラフィック帯域幅を 20-50 MiBps に制限したノードは、制限のないコントロールノードと比較して最大 5%より一貫して同期を維持しました。

Agave RPC ノードのトラフィックシェーピングの設定

これらの結果に基づき、AWS Blockchain Node Runners の Solana ブループリントに動的トラフィックシェーピングを導入しました (Optimizing Data Transfer Costs を参照)。
その実装の主要な部分は以下のとおりです。

  • net-rules-start.sh はトラフィックシェーピングを有効にします。
#!/bin/bash 

# Specify max value for outbound data traffic in Mbps. 
 LIMIT_OUT_TRAFFIC_MBPS=20 

# Step 1: Create nftables rules to mark packets going to public IPs 
# Create table if it doesn't exist 
 if ! nft list table inet mangle >/dev/null 2>&1 ; then 
    nft add table inet mangle 
 fi 

# Create chain if it doesn't exist 
 if ! nft list chain inet mangle output >/dev/null 2>&1 ; then 
    nft add chain inet mangle output { type route hook output priority mangle\ ; }
 fi 

# Check if specific private IP return rule exists 
 if ! nft list chain inet mangle output | grep -q "10\.0\.0\.0/8.*172\.16\.0\.0/12.*192\.168\.0\.0/16.*169\.254\.0\.0/16.*return"; then 
    nft add rule inet mangle output ip daddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } return 
 fi 

# Check if mark rule with value 1 exists 
 if ! nft list chain inet mangle output | grep -q "meta mark set 0x00000001"; then 
    nft add rule inet mangle output meta mark set 1 
 fi 

# Step 2: Set up tc with filter for marked packets 
 INTERFACE=$(ip -br addr show | grep -v '^lo' | awk '{print $1}' | head -n1)

# Check if root qdisc already exists 
 if ! tc qdisc show dev $INTERFACE | grep -q "qdisc prio 1:"; then 
    tc qdisc add dev $INTERFACE root handle 1: prio 
 fi 

# Step 3: Add the tbf filter for marked packets 
# Check if filter already exists 
 if ! tc filter show dev $INTERFACE | grep -q "handle 0x1 fw"; then 
    tc filter add dev $INTERFACE parent 1: protocol ip handle 1 fw flowid 1:1 
 fi 

# Check if tbf qdisc already exists on class 1:1 
 if ! tc qdisc show dev $INTERFACE | grep -q "parent 1:1"; then 
    tc qdisc add dev $INTERFACE parent 1:1 tbf rate "${LIMIT_OUT_TRAFFIC_MBPS}mbit" burst 20kb latency 50ms 
 fi
  • net-rules-stop.sh はすべてのトラフィックシェーピングを削除します:
#!/bin/bashINTERFACE=$(ip -br addr show | grep -v '^lo' | awk '{print $1}' | head -n1)# Remove tc rulestc qdisc del dev $INTERFACE root 2>/dev/null# Remove nftables rules# Delete the entire mangle table (removes all chains and rules)nft delete table inet mangle 2>/dev/nullexit 0 ;
  • 簡単にするために、自動化スクリプト net-rules-start.shnet-rules-stop.sh は systemd サービス net-rules.service を通じて制御されます。
[Unit] 
 Description="ipables and Traffic Control Rules"
 After=network.target 

 [Service] 
 Type=oneshot 
 RemainAfterExit=yes 
 ExecStart=/opt/instance/network/net-rules-start.sh 
 ExecStop=/opt/instance/network/net-rules-stop.sh 

 [Install] 
 WantedBy=multi-user.target
  • net-syncchecker.sh は、内部からアクセスする API を使用してノードの同期ステータスをチェックし、net-rules サービスでトラフィックシェーピングのオンとオフを切り替えます。これは 1 分ごとに呼び出す必要があるため、systemd timercron のような他のサービスを使用してスケジュールできます。
#!/bin/bash 

 INIT_COMPLETED_FILE=/data/data/init-completed 
 MAX_SOLANA_SLOTS_BEHIND=10 

# Check if jq is available 
 if ! command -v jq &> /dev/null ; then 
    echo "Error: jq is required but not installed"
    exit 1 
 fi 

 TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
 if [ -z "$TOKEN" ] ; then 
    echo "Error: Failed to get EC2 metadata token"
    exit 1 
 fi 

 EC2_INTERNAL_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/local-ipv4)

# Start checking the sync node status only after the node has finished the initial sync 
 if [ -f "$INIT_COMPLETED_FILE" ] ; then 
    SOLANA_SLOTS_BEHIND_DATA=$(curl -s -X POST -H "Content-Type: application/json" -d ' {"jsonrpc":"2.0","id":1, "method":"getHealth"}' http://$EC2_INTERNAL_IP:8899 | jq .error.data)
    SOLANA_SLOTS_BEHIND=$(echo $SOLANA_SLOTS_BEHIND_DATA | jq .numSlotsBehind -r)

    if [ "$SOLANA_SLOTS_BEHIND" == "null" ] || [ -z "$SOLANA_SLOTS_BEHIND" ] 
    then 
        SOLANA_SLOTS_BEHIND=0 
    fi 

    if [ $SOLANA_SLOTS_BEHIND -gt $MAX_SOLANA_SLOTS_BEHIND ] 
    then 
        if systemctl is-active --quiet net-rules ; then 
            systemctl stop net-rules 
        fi 
    fi 

    if [ $SOLANA_SLOTS_BEHIND -eq 0 ] 
    then 
        if ! systemctl is-active --quiet net-rules ; then 
            systemctl start net-rules 
        fi 
    fi 
 fi

本番環境で使用する前に、この投稿のコードまたは AWS Blockchain Node Runners について:

  • これらのスクリプトを安全な環境でレビューおよびテストしてください
  • 必要に応じて入力検証を追加してください
  • 適切なエラー処理とログ記録を実装してください
  • 必要最小限の権限でスクリプトを実行してください

まとめ

この記事では、Solana Agave v2.x で導入された変更により必要な CPU クロック速度が増加したことを確認し、アジア太平洋地域における Solana Agave クライアントの同期時間を改善する方法を検討し、Solana RPC ノードのデータ転送コストを最適化する方法を紹介しました。
これらの最適化をご自身のノードでテストするか、AWS Blockchain Node Runners イニシアチブの Solana ブループリントを使用してください。
さらに質問がある場合は、AWS re:Post で「blockchain」タグを付けて質問するか、Solana StackExchange でディスカッションに参加するか、Solana コミュニティにお問い合わせください。

著者について

Tao Gong

Tao Gong

Tao はブロックチェーン技術の愛好家です。AWS 上で革新的なソリューションを構築するために顧客と協力し、ビジネス上の課題を克服し、AWS サービスを効率的に採用できるよう支援しています。

Jinsong Zhu

Jinsong Zhu

Jinsong は AWS のシニアソリューションアーキテクトで、大手 Web3 および暗号資産企業向けに高性能、低レイテンシー、コスト最適化されたクラウドソリューションの設計を専門としています。

Nikolay Vlasov

Nikolay Vlasov

Nikolay は、AWS Worldwide Specialist Solutions Architect 組織における分散型台帳技術インフラストラクチャのグローバルリードです。顧客が AWS 上で分散型ウェブおよび台帳技術のワークロードを実行できるよう支援しています。