ドキュメント › 処理の分担

地形生成の分担

地形生成で一番重い処理を、暗号化した通信で別のマシンに計算してもらう。結果はまったく同じ。

地形生成はいくつかの段階に分かれています。一番重い ノイズ の段階では、土地の形(どこが石・空気・水・溶岩か、洞窟や帯水層)を決めます。 この計算に必要なのはシード・ワールドの設定・近くの構造物だけで、隣のチャンクやプレイヤーの行動には左右されません。だから別のマシンで計算できます。

分担を使うと、Storia サーバー(クライアント)は 1 台以上の ワーカー にノイズの計算を依頼します。ワーカーは計算したブロックを送り返し、 それ以外の処理はすべてメインサーバーに残ります。

 Storia サーバー(プレイヤー、ワールド)        Storia Worker(別のマシン)
   構造物、地物、光      --- 依頼(チャンク+近くの構造物) --->
                         <--- 地形のブロック、高さマップ    ---   地形ノイズ

移るもの・残るもの#

段階 処理する場所
構造物の開始点と参照 メインサーバー
バイオーム メインサーバー
ノイズ(地形の形、洞窟、帯水層) 空いていれば ワーカー
地表、洞窟の彫り込み、地物(木・鉱石)、光、スポーン メインサーバー
ティックで動くものすべて メインサーバー

ノイズより後の段階は、隣のチャンクに左右されたり、50 ms のティック内に終わらせる必要があったりするので、メインサーバーに残ります。 ノイズは生成の中で一番大きな部分なので、これを移すだけで多くの CPU が空きます。

結果は常に同じ#

  • 接続時の照合。 サーバーがワーカーに接続すると、両方がディメンションごとに同じ確認用チャンクを生成し、ハッシュを比べます。 完全に一致したディメンションだけを分担します。シード・データパック・Storia のビルドが違えばそのディメンションは断られ、理由がログに出ます。
  • 検証。 ワーカーからの返事は、チャンクに反映する前に毎回チェックします。
  • 自分で生成に戻る。 空いているワーカーがない、ワーカーが遅い(timeout-ms)、接続が切れた、といったときは、そのチャンクを自分で生成するだけです。 止まったワーカーのせいでプレイヤーが待たされることはありません。
  • 検証モード。 メインサーバーを -Dstoria.verifyOffload=true 付きで起動すると、分担したチャンクを自分でも生成して照合します。テストでは差異 0 件でした。

設定#

必要なもの:

  • メインの Storia サーバー
  • Java 25 が入った、手伝う側のマシン 1 台以上(Storia Worker のパッケージを使います)
  • サーバーの設定を変えずにワーカーを増減したいなら Storia Relay(任意)
  • 8 文字以上の共通の 合言葉

メインサーバー#

# storia.yml
offload:
  mode: client
  secret: "長くてランダムな合言葉"
  workers:
  - 192.168.0.20:25590
  - 192.168.0.21:25590

再起動します。サーバーの読み込みが終わる(Done)と、分担が始まります。

ワーカー#

Storia Worker の手順に従います。要約すると、storia-worker-26.2.zip を展開し、メインサーバーのワールドフォルダを region・entities・poi を除いてコピーし、 同じ合言葉を設定して start-worker.sh を実行します。

リレーを使う場合#

Storia サーバー --\                  /-- ワーカー A
                   >-- Storia Relay <---- ワーカー B
Storia サーバー --/                  \-- ワーカー C

サーバーはリレーだけをワーカーとして登録し、ワーカーは自分からリレーに接続します。Storia Relay を参照してください。

動作の確認#

/storia offload
Client mode: 3120 chunks offloaded, 0 generated locally after a failure
 generated locally: 41 (workers busy), 0 (blending with old terrain), 0 (upgraded chunk), 12 (no plain noise state)
 192.168.0.20:25590: connected (encrypted), 6 threads, 7/24 in flight, 3120 done, 0 failed, avg 38.5 ms, dims [minecraft:overworld, minecraft:the_nether, minecraft:the_end]
自分で生成した理由 意味
workers busy すべての接続が満杯でした。ワーカーかスレッドを増やしてください。
blending with old terrain 古いバージョンの地形と接していて、なじませる処理が必要なチャンクです。
upgraded chunk 古いバージョンで途中まで生成されたチャンクです。
no plain noise state ワーカーに伝えられない種類のチャンクです。まれで、正常な動作です。

性能#

メインサーバー 3 コア、ワーカー 1 台(別の 3 コア)で 3,721 チャンクを事前生成した結果:

時間
メインサーバーだけ 1分35秒
メインサーバー+ワーカー 1 台 1分6秒(ノイズの 95% を分担、検証した 888 チャンクの差異 0 件)

ワーカーを増やすほど速くなり、最後はメインサーバーに残る段階が上限になります。分担が効くのは 新しい地形(探索と事前生成)です。 エンティティやレッドストーンは速くなりません。

ポート#

ポートはマシンごとに自由に決められます。25590 は初期設定の値にすぎません。

マシン ポートを設定する場所
ワーカー(待ち受け) その storia.yml の offload.port
リレー relay.properties の port=
メインサーバー 開ける必要なし(自分から接続します)。offload.workers の各行に host:port を書きます。
リレーを使うワーカー 開ける必要なし。offload.relay: "host:port" にリレーのポートを書きます。

たとえば、ワーカー 2 台を別々のポートで動かす場合:

# ワーカー A(storia.yml)
offload:
  port: 10000
# ワーカー B(storia.yml)
offload:
  port: 10001
# メインサーバー(storia.yml)
offload:
  mode: client
  workers:
  - 192.168.0.20:10000
  - 192.168.0.21:10001

ポート転送も使えます。ルーターで外側のポート 10001 をワーカーの 25590 に転送しているなら、メインサーバーには外側のアドレスとポート (203.0.113.5:10001)を書きます。

ネットワーク#

  • 通信はワーカー(またはリレー)ごとに TCP 接続 1 本です。
  • 1 チャンクあたりの通信量は小さく、圧縮もしています。LAN や、データセンター間の VPN が理想です。遅延が大きくても、1 件ごとの依頼が遅くなるだけで、サーバーは遅くなりません。
  • すべて暗号化・認証されています。暗号化とセキュリティ を参照してください。