Minecraft のサーバうんちく

この記事は 30 分程度で読めます。

Minecraft（Java）のサーバについてのうんちくをバラまいて日本を救うスーパーエンジニアを１人でも多く輩出することを目的としています。あわよくば日本に大規模マルチプレイサーバがたくさんできることを祈っております。

# はじめに
この記事は IT 系コラムです。参考書ではないので読んだらサーバを建てられるというものではありません。前半はサーバって何？という IT 初心者なところから、後半は大人数のマルチプレイを実現するための要素についてゆるく説明します。宇宙中のどこを探してもこういう Minecraft サーバのコラムは存在しないと思うので読んでみてください。

用語に興味がない人は後半の [大規模なマルチプレイサーバの考え方](#大規模なマルチプレイサーバの考え方) まで読み飛ばしてもらってもいいです。

昔書いた Java についてのうんちくはこちら↓

https://qiita.com/johniki/items/a6aa7cd762092e262b9b

# 対象者

コラムとして読むだけなら知識が無くても読めると思います。
- 情報工学系の学生　～　IT系エンジニア１～２年目くらいまでの人
- Minecraft サーバ運営には興味があるけど IT については良く分からない人
- 大規模なマルチプレイサーバを運営したいけど何から始めたら良いか分からない人
- ファンボーイ

## まずは用語から
この記事で説明していない用語は自分で調べながら読んでください。最低限の用語だけ説明しています。

## サーバとクライアント
皆さんはオンラインゲームやってますか？Minecraft に限らずそもそも「サーバ」というのは、サービスを「提供する側（serve）」のことであり、もう一方の「提供される側（cliens）」のことを「クライアント」と呼んでいます。IT システムの場合には２つあわせてクライアント/サーバ（C/S）システムなどと呼ばれます。間にインターネットがある場合もあれば、建物の中のように LAN ケーブルで接続されているだけの場合もあります。

通常は１つのサービスに対して利用者の方がはるかに多く、数百～数万のクライアントが１つのサーバに同時に接続することになります。しかし数万のクライアントを１つのサーバで処理することは非常に難しいため、大抵は１つに見えるサービスの中で複数のサーバが頑張って動いています。例えばケータイは１人で複数台持ちだったりするので、ケータイキャリアなどのインフラを司るシステムは日本人１億人くらいのクライアントを支えるサービスを平然と動かしたりしています。大人数を支えるサービスを安定して動かすためには複数台のサーバが必要になる、というのが基本的な考え方です。

|　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　|
|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/e262fa47-e268-4ab6-9bc1-25452bff3c80.png" width="50%">|
<font color="gray">　</font>

話は Minecraft に戻って、Minecraft には「クライアント」と「サーバ」、そして特殊ですがその２つをくっつけた「統合サーバ」という３つの分類があります。「統合サーバ」は形式上そう呼ばれているだけで、IT システムの用語の中に明確にそういう分類が存在するわけではありません。オンラインゲームを実現する手法の１つとして「統合サーバ」や「専用サーバ（dedicated server）」という用語が存在しますが、ゲームによってその定義もまちまちなので Minecraft の中ではこういうものなんだなと思って読んでください。

![figure2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/17aa219f-8780-38c6-096d-36229a879179.png)

## Minecraft クライアント
みんなが一番良く知ってるクライアント。ざっくり以下の通り。

- プレイヤー各自の PC にインストールされている Minecraft のことで、プレイヤーが操作して遊ぶ部分、いわゆる「ゲーム機」の部分のこと
- クライアントはマルチワールドに接続する場合、シングルプレイとは違ってワールド（地形）や他プレイヤーや Mob の情報を初めは何も持っておらず空っぽの状態から始まる
- サーバとの間でネットワークを介して様々なパケットを送受信することで徐々にクライアントの中にワールドデータが蓄積され、シングルプレイのときと同じように地形が描画され、ワールド内を移動できるようになる
- クライアントには Minecraft のゲームと共に標準のリソースパックが元から入っているため、りんごやオオカミの画像を都度サーバから貰う必要は無く、りんごの個数やオオカミの座標などの情報を貰うだけで、その座標にりんごやオオカミが描画される（画像の情報はりんごの個数などの情報と比べると～1000倍くらい大きいので基本的には送りません）

![figure3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/3f594cb1-0f52-7b0c-7e64-73da0ae2d1bb.png)

- ログイン時や未開拓の場所へ移動した際はサーバからワールドの一部分（チャンクやリージョンと呼ぶ）のデータを受信し、受信が終わるとそこでようやく地面が描画される
  - サーバから貰うデータの中で最も容量が大きいのはワールドデータであり、回線速度が遅いとクライアントの画面はずっとフリーズしたまま別のチャンクに移動できない、あるいは奈落に落ちる絵が続く
  - キーボード、マウスの操作内容（歩いた、首の角度を変えた、ブロックを置いた、クリックした等）のほぼ全てがサーバに連携される
  - 新しいリソースパックはサーバから１度ダウンロードすることで、次回以降ダウンロードせずにリソースパックを使うことができる（自分の PC の中を探すと実はサーバからダウンロードしたリソースパックが隠されており暫くの間は PC の中に残り続ける。データが「キャッシュされる」という。）

## Minecraft サーバ
今回の話の主役。ざっくり以下の通り。
- クライアントから届いた情報を蓄積し、サーバの中にあるワールドデータに反映し、その結果やその情報そのものを全クライアントに連携するという中継役を担っている
- サーバにはワールド、全プレイヤー、全エンティティに関する様々な情報がデータとして蓄積される
- 全プレイヤーに情報を連携する必要があるため、人数に応じて性能の良いサーバや高速なインターネット回線が必要となる
  - ちょっとだけ算数をします。N 人のプレイヤーがいる場合、単純に計算すると1人の情報を自分以外の (N-1) 人に連携する必要があるため、N 人分の情報が全員に行きわたるにはパケットの総数は最大で N の２乗個近くになることがあります。常にではないですが、単純に N に比例して帯域を増やしただけでは帯域が足りなくなる場合があることに注意が必要
- データを蓄積・連携するだけではなく、当然 Minecraft のプログラムなので、重力の計算をしてプレイヤーがどれだけ落下するかも計算できるし、かまどがどれくらいの速度で燃料を消費するかも計算できるし、エンドラがベッド爆破でどれくらいダメージを受けるかも計算できる

![figure4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/3925ce05-04c2-ad18-2cbe-c1d38378277c.png)

- クライアント（プレイヤー）が誰もいなくても、サーバ内では時間が止まることなくイベントが発生し続けており、時間と共に作物が育ったりする
- サーバ内では常に数百、数千のイベントが発生し、それを計算し続けている（1tick：50ミリ秒毎に数千のイベントが発生する）
- クライアントから見てスムーズに動いているように見えても、回線やサーバの調子が悪いと他のプレイヤーへの情報連携が遅れるため、他のプレイヤーから見ると動きが遅延したりカクカクして見える（どんなに性能が良いサーバ・回線でもそもそも情報連携が行き届くまでの間は少し遅延している）

## 統合サーバ
一応説明しておきます。ざっくり以下の通り。
- Minecraft をシングルプレイで遊ぶと、自分の PC の中に「統合サーバ」という「クライアントとサーバをあわせた」プログラム（正確にはプロセスと呼ぶ）が起動する
- 自分の「クライアント」があたかも自分自身の「サーバ」に接続をして遊んでいるように動くが、実際には１つのプログラムなのでインターネット上にパケットが流れたりはしない
- 統合サーバを「LANに公開」することで、友達を自分の「統合サーバ」のサーバ機能の部分に招待することができるようになる
- シンプルに「クライアント」と「サーバ」を足しただけと思ってもよい
- Mod を作る場合には「クライアント」「サーバ」「統合サーバ」の３つのどこで動かしたいプログラムなのかを意識して作る必要がある

![figure5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/20779938-d470-b4d1-09f5-4f407eaf4e52.png)

# サーバの種類
ここから先はサーバのお話。

## ①シンプルなバニラサーバ
一番基本となるバニラサーバに接続するときの全体像を説明します。この構成を説明できなくてもサーバ運営はできますが、せっかくなので今日は読むついでに覚えて帰ってください。登場人物は、クライアント（パソコン）、インターネット回線、回線終端装置（とルーター）、ファイアウォール、サーバです。図で書くとこんな感じでとてもシンプル。

![figure6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/2e21fae8-0be9-ccd4-ecb0-3c9ecd10531d.png)

- クライアント：プレイヤーが操作する端末。基本的にはサーバとは別の場所にあるので、インターネットを通してサーバと接続することになる
- 回線終端装置：電波みたいなものが出てる絵。回線業者が送ってくる機械。無線や有線でインターネットと接続できる
- ファイアウォール：火を遮る壁の絵。サーバを攻撃から守るセキュリティ装置。機械のこともあれば内臓されてることもある
- ルーター(*)：図には書いて無い。回線終端装置に内臓されてたり単品の機械のこともある。大きなネットワークを複数の小さなネットワークに分割したいときに置く（部署や研究室などの場所や、用途、管理用／一般用などの権限で分けたりする）。タブレットやノートPCを使う人が増えたので最近は専ら無線対応するためだけの理由で無線対応ルーターを置くことも多い
- サーバ：ここで Minecraft サーバのプログラムを動かす。ファイアウォール機能が内臓されていたり、場合によってはただの高性能なパソコンのこともある

建てたサーバを外部に公開するにはいくつかの用語を覚える必要があります。ざっくり説明していきます。

### IPアドレス
インターネットに接続すると回線終端装置に世界で唯一のグローバル IP アドレスという住所（aaa.bbb.ccc.ddd）が割り当てられますが、これは家全体の住所なので、サーバにはそれとは別に身内だけが知っているローカル IP アドレスという住所（192.168.1.100 など）を決めてサーバに付ける必要があります。ローカル IP アドレスは他人に教える必要はありません。

### ポート番号
次はポート番号ですが、特に変更しなければポート番号は Java 版なら TCP/25565 番に設定されています（統合版は UDP/19132 番）。これは集合住宅でいうところのあなたの「部屋番号」や、企業でいうところの「〇〇部署」のように住所の中で更に細かく相手を特定するための番号です。サーバに話を戻すと、サーバの中のどこで Minecraft というサーバプログラム（プロセス）が動いているかを見つけるための番号です。

IPアドレスとポート番号の組のことをソケットと呼びますが、1台のサーバの中で同じソケットを2つの用途で使うことはできません（Minecraft 用に使ったり、Web サーバ用に使ったり、メールサーバ用に使ったりはできない）。

ポート番号は Minecraft 標準の 25565 番を使っても良いですが、内部の情報を隠ぺいするために自分だけが知っている番号にすることが多いです（上の図は 50001 を利用）。1台のサーバの中に複数の Minecraft サーバを建てたい場合には、どの Minecraft サーバかを見分けるために IP アドレス、またはポート番号を分ける必要があります。例えばポート番号を分ける場合には 50001 ～ 50010 の 10 個のポート番号を使えば、1台のサーバの中に 10 個のサーバプログラムを同時に動かすことができます。

以下の図は Minecraft のマルチプレイでサーバの情報を入力する画面です。IP アドレスに続けて「:」の横にポート番号を書きます。省略すると 25565 番が使われます。必要な情報は上の図でいうところの、家に割り当てられたグローバル IP アドレス（とポート番号）だけです。外から接続する場合にはローカル IP アドレスやローカルのポート番号は必要ありません。サーバ の IP アドレスを教えてと友達に言ったときに「192.xxx.xxx.xxx」と返事が帰ってきたら「それローカル IP アドレスだから違うよ。」と親切に教えてあげてください（家の中で使う場合は正しいです）。

![ipaddress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/30249239-5527-b8cd-fe71-3173bc4a37ee.png)

### ポート開放とポートフォワーディング（ポート転送）
回線終端装置は、グローバル IP アドレスとポート番号宛に届いた通信を、ローカル IP アドレスとポート番号に届ける（転送する）機能を持っています。これをポートフォワーディング（ポート転送）などと呼びます。回線終端装置によっては IP アドレスの転送にのみ対応している機種があったり、25565 番を使えない機種があったり、そもそもファイアウォールが閉じられており外部にサーバを公開できない機種もあります。

以下の図はポートフォワーディングの設定例です。例えば TCP/30001 番（WAN側）に向けて届いた通信を、家の中の 192.168.3.4 （転送先IP）というサーバの TCP/50001 番（LAN側）に届ける設定の例です。意味が分かると簡単ですね。

![port_forward.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/a68e4b68-ba79-3b64-12e9-f68cab30e1b6.png)

### ファイアウォール
これに加えて、ファイアウォールの設定が自由にできる場合には、回線終端装置のポート番号宛てに届いた通信を許可して通す必要があります。サーバの中にソフトウェアとしてファイアウォールが動いている場合には、ポートフォワーディング後の最終的なポート番号を許可するようにサーバのファイアウォールも正しく設定する必要があります。

以上がサーバを建てる際の説明でよく「ポート開放が必要」と説明されてるものの正体です。ようはパケットが通れるように適切にポートフォワーディングをして通り道が塞がっていたら穴を空けて繋げていくという作業です。

もちろん必要に応じて Minecraft のホワイトリストも設定してください。Minecraft は世界でもっとも同時接続数が多いゲームであり、ポート番号もデフォルトの番号は知られているため放っておくとすぐに攻撃されてしまいます。

### とりあえず必要な知識

- サーバを起動するためのポート番号、外部に公開するポート番号の２種類がある
- IP アドレスにはグローバル IP アドレスとローカル IP アドレスの２種類がある
- ポートフォワーディングを使って（使わなくてもいい）必要な IP アドレスとポート番号に転送する
- 回線終端装置とサーバなど複数箇所のファイアウォールで必要なポート番号の通信を許可する
- ホワイトリストを有効にし、ホワイトリストで必要なゲーマータグのみ許可する

## ②Bukkit 系サーバ（プラグインサーバ）
バニラサーバを改造し、プラグインと呼ばれる追加のサーバプログラムを動作できるようにしたサーバです。Bukkit API と呼ばれる便利な拡張機能を使用できるサーバで、Bukkit 系と呼ばれる多くの派生サーバ（CraftBukkit、Spigot、Paper、Purpurなど）があります。

Mod サーバは機能の拡張を行って楽しむことを主に設計されているため、クライアント・サーバともに好きな Mod を詰め込んで遊ぶことが多く、サーバの性能も高いものが要求されます。それに対してプラグインサーバは、クライアント側がバニラクライアントでも参加できるため、多数のクライアントが接続しても動作することを意識して設計されており、多くの軽量化機能がサーバ自体に備わっています。さほどハイスペックじゃなくても軽々と同時接続 100 人を達成できます。大規模なマルチプレイサーバを運営するためにはプラグインサーバが必要となります。

![figure7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/b5062845-5640-80e5-c1a4-9144e84b1b58.png)

バニラサーバの構造をもう少し詳細に見ると「NMS：Net Minecraft Server」と呼ばれるコアなプログラムがサーバの低レベルな部分で動いており、これによって Minecraft のベースとなる機能が実現されています。「低レベル」というのは頭が悪いとかそういう話ではなく、コンピューターにより近く、Minecraft の基礎的な部分を操作できるという意味です。

しかし、Minecraft のバージョンアップと共に NMS は大きく変更されることがあるため、開発者が Minecraft に追加プログラムを導入しやすくするために、非公式の Bukkit API と呼ばれる API が作られました。公式からは API は提供されておらず、有識者が NMS を解読して非公式に API を作り、公式のバージョンアップに追従するようにアップデートをしてくれています。また API であることから Minecraft のコアな部分には直接アクセスすることはできませんが、それでもコマンドに比べればかなり自由度の高いプログラムを作ることができます。コアな部分にアクセスしたい場合には NMS を解読して利用する必要があります。

この Bukkit API と NMS をより安全に、より簡単に扱えるようにしたサーバが上で挙げた CraftBukkit サーバです。これを軽量化の観点で更に進化させた Spigot サーバが世の中的には広く利用されていますが、大規模なサーバ運営を行うためには、これに更に機能追加を行った Paper サーバ、Purpur サーバ、およびそれらを大規模マルチサーバ用に魔改造したサーバが必要となります。

![figure8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/a099c0cb-75cb-824b-42a3-29200ff48ae8.png)

### Mammoth
今よりも更に大人数で Minecraft を楽しみたいというのはマルチプレイを経験したことがある人ならみんな思っている夢かもしれません。2011年にこれを実現するために Mammoth（マンモス） というプロジェクトが誕生しました。これは Spigot サーバで動作するプラグインとデータベースで作成されており、Minecraft サーバが蓄積している情報をサーバ外のデータベースに配置することで、複数のサーバから同じ情報にアクセスできるようにした簡易的なデータベース連携のプロジェクトです。

１台のサーバでは大人数のクライアントを制御できないので、サーバ１台あたりのクライアント数を少なくし、情報を共有しあうことで見かけ上、何千人ものクライアントがサーバ内にいるように見せかけるという仕組みです。違うサーバにログインしていても、全てのプレイヤーが見えるように作られています。

2011年当時で Yogscast が同時接続 2622 人を達成してギネス記録に認定されました。私がこれを知ったのは 4 年前の丁度今頃でした。大人数で色々動き回って遊べるサービスを作りたいなと心を燃やした記憶があります。その後、2021年末頃に Mr.Beast が Mammoth を使ってサーバ 64 台で同時接続 4000 人を達成したようですが、それ以降特に目立った記録は出ていないようです。なお1台1台のサーバはノート PC のような低スペック PC も混ざっていたそうです。

### MultiPaper
Mammoth のプロジェクトは役目を終えて停止し、それを引き継ぐように MultiPaper と呼ばれるサーバが開発されました。Mammoth は Spigot サーバが持つ機能はほぼそのままに、サーバが持つ情報を外のデータベースに格納するプラグインを動かすことで、複数のサーバ間で情報を連携するように試みようとしていました。
一方で MultiPaper サーバはサーバの仕組み自体を改造し、そもそも情報を外に書き出すように作られた子供サーバとそれらを管理する親サーバという２種類のサーバにサーバの機能を分割し、Mammoth が本来やりたかった機能をプラグインではなく、サーバ自身で実現しました。

MultiPaper サーバは非常に強力なサーバですが、外に書き出した情報はデータベースではなくファイルベースであることからまだまだ改善の余地はありそうです。更に、Minecraft 自体がもともと複数のサーバ、複数の CPU を使って動くように作られていない（マルチスレッド非対応、スレッドセーフではない）ため、その動作も完全ではなく、MultiPaper を使ってもデフォルトではシンプルなサバイバルモードが遊べるだけです。通常のマルチサーバのようにコマンドを使って遊びたい場合には MultiPaper 専用のプラグインを開発する必要があります。

Mammoth も MultiPaper も共通して、サーバの台数を増やせば増やすほど（理論的には）同時接続数を増やすことができます。このような方法をスケールアウトと呼びます。性能を外側に拡張することでサービスをパワーアップさせるという意味です。そうではなく、サーバ自体をハイスペックに変えることをスケールアップと言いますが、スケールアップには限界があるため一時しのぎにしかなりません。同時接続数を 2 倍にしたいからといってもサーバのスペックは簡単には 2 倍になりません。一般的にスペックが 2 倍になるためには 18 か月かかると言われています。

|　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　|
|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/61e43a1f-e476-fc1c-5e9c-fa025bc6cfa0.jpeg" width="75%">|
<font color="gray">抜粋：https://github.com/MultiPaper/MultiPaper</font>

### Folia
前項にも書いたように Minecraft はマルチスレッド非対応であり、どんなにスペックの高いサーバを用意しても同時には1つの CPU コアしか利用しません。複数のコア／スレッドを持つ超ハイスペックサーバを使っても性能を上げられないことが今でも界隈では問題視されています。それを部分的にマルチスレッドで動くように改造したサーバが Folia です。最近のコンシューマー向けパソコンは CPU の性能が非常に高くなっており、スレッド数も16、24、32、64といった昔では考えられないほど同時処理数が多くなっています（昔は 1 や 2 だった）。マルチスレッドというのは聖徳太子のように同時に 10 人と会話できる（嘘）脳みそを持っているということです。

ものすごく単純に言ってしまうと、マルチスレッドで 16 個のスレッドを同時に使えれば、Minecraft の負荷を 16 個に分散できるため、結果的に 16 倍の人数を収容することができます（理論的には）。

Mammoth や MultiPaper とは考え方が違いますが、これも大人数マルチプレイを実現するための１つの手段です。しかしスレッド数には限界がある上に1台の PC が利用できる回線速度にも上限があるため、あくまでもコンシューマー向けの対策です。サーバがたくさん用意できる場合には MultiPaper サーバを使えば良いので Folia を使う意味はありません。

また、コンシューマー向けに便利とは言っても Folia も万能ではありません。マルチスレッドで動作しない Minecraft を無理やりマルチスレッドに対応させているため動作は不安定であり、いくつかの主要機能も動作しません。MultiPaper と同様、コマンドで遊びたい場合には Folia 専用のプラグインを開発する必要があります。Folia の他にもマルチスレッドで動作する派生プロジェクトは何種類かありますが、いずれも現時点（2025年2月）では開発中です。

### Bukkit のまとめ
- NMS のバージョンアップに影響されないように Bukkit API という開発者用 API が作られた
- サーバに追加のプラグインを導入することで追加プログラムを動かすことができる
- より便利でより安定したサーバを目指して派生した Bukkit 系サーバがたくさんある（Spigot がベース）
- サーバ自体に軽量化を行う機能が内蔵されている
- 大規模マルチプレイを実現するためには Spigot から派生した魔改造のサーバが必要

# 大規模なマルチプレイサーバの考え方
ものすごく単純にいうと、大規模マルチプレイは前項で説明したサーバをたくさん並べて実現します。Mammoth も MultiPaper も Folia も共通して、１つでは処理しきれない負荷を複数（サーバ、スレッド）に分散するという考え方に基づいています。これはクライアント/サーバ（C/S）システムにおける負荷分散やスケールアウトと呼ばれる考え方です。

|　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　|
|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/27553064-b4ec-38f4-7ab2-33561bc910ce.jpeg" width="50%">|
<font color="gray">抜粋：https://github.com/MultiPaper/MultiPaper</font>

## リバースプロキシ
一番簡単な負荷分散であるリバースプロキシから説明していきます。Minecraft のワールドをロビー、サバイバルワールド、資源ワールド、ミニゲームワールドなどと機能を分割することによって、１つのワールドにログインしている人数を分散させることで、実質の負荷を下げる考え方です。よくある「ロビー」にログインしてから色々なミニゲームワールドに移動して遊ぶ、という形式は全てこれです。

前項までは同じサーバの負荷を複数に分散する考え方でしたが、これはそもそも違う種類のサーバ（ロビー、ミニゲーム、その他）に負荷を分散させる考え方です。

インターネットで検索するとこれらは「プロキシ」と紹介されていますが「プロキシ」は内部（クライアント）から外部（インターネットなどの広域）のサーバにアクセスするときに使う用語であり、今回の用途はその逆で、外部（インターネットなどの広域）から内部のサーバにアクセスするケースなので、正しくは「リバースプロキシ」と呼ばれています。気にせずに「プロキシ」と言えば伝わりますが、Minecraft 以外の場面でこの単語を使う場合は「？？？」と思われてしまうので気を付けましょう。ちなみに「プロキシ」というのは「代理」のことです。

リバースプロキシは Bungeecord、Velocity、Waterfall といった有名なサーバソフトウェアで実現します。
以下にどんなことができるかを説明します。

### ①サーバ移動
リバースプロキシはアクセスしてきたプレイヤーのユーザ認証などをサーバの代理で行い、その後は必要なサーバへプレイヤーを転送してくれます。一番最初に入るサーバ（例えばロビー）にプレイヤーをログインさせた後は、各サーバ（ワールド）へ移動するポータルをくぐることで、Minecraft のタイトル画面に戻ることなくサーバ（ワールド）を移動できるプラグインもあります。

勘違いしてはいけないことは、リバースプロキシ ⇒ ロビー ⇒ サバイバルワールドのような数珠繋ぎになっている訳ではない、ということです。あくまでもロビーは最初に招待されるサーバというだけであり、サバイバルワールドへの接続は、リバースプロキシ ⇒ サバイバルワールドのように直接繋がっています。そのため、ロビーに多人数が接続していても、サバイバルワールドにはなんの影響も無いということを理解しておく必要があります。

Java 版の1.20.5 からは /transfer コマンドが実装されたため、リバースプロキシが無くてもサーバ間を移動できるようになりました。バニラの Minecraft も大規模なマルチプレイを意識するようになったのかもしれませんね。

![figure9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/30ebbf4a-7171-43f2-4a82-c91a68706669.png)

### ②クライアント互換性（おまけ）
プロキシの役割にはクライアントとサーバの間に入って、お互いが流暢に会話できるように代理でお互いの言葉を翻訳する役割もあります。リバースプロキシの中に統合版と Java 版の通信を翻訳するプラグインを導入したり、異なるバージョンの Minecraft の通信を翻訳するプラグインを導入することで、統合版クライアントから Java 版サーバに接続したり、古い（新しい）Java 版のクライアントからバージョンの異なる Java 版サーバに接続することができます。

ただし、あくまでも翻訳しているだけなのでレッドストーン回路や特殊なアイテムが完璧に動作するわけではありません。基本的にはサーバ側のバージョンの制約内でクライアントが動作します。大規模なマルチプレイサーバを運営するとどうしても統合版を視野に入れる必要があるため、そのような場合にはリバースプロキシが必要です。

なお、リバースプロキシのサーバを建てなくても、クライアント側に Mod としてリバースプロキシ機能を導入することで、好きな Minecraft のクライアントで任意のバージョンのサーバに接続することができます。

![figure10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/e779c62c-2985-f26f-9fd4-2af5ef15fa9a.png)

## サーバロードバランサ（負荷分散装置）
SLB などと呼びます。高いです。買うと数十万円から数百万円します。リバースプロキシはクライアントが自分でワールドを選択してサーバ間を移動するのに対して、SLB はインターネット上を流れるパケットを自動で各サーバに振り分ける機能を持っています。そのため、ロビー・サバイバル・ミニゲームといった機能の異なるサーバにプレイヤーを分散するというよりは、同じ機能を持った複数のサーバにプレイヤーを分散するために利用されます。

![figure11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/1961b5cb-5d78-fddc-ad95-fb67df06922f.png)

ソフトウェア（プラグイン機能）やハードウェアで実現することができ、ハードウェアの方がより高速に動作します。Minecraft は別のワールドに行くと、別のワールドのプレイヤーとは一緒に遊ぶことができないため、あくまでもシングルプレイとして遊んでも違和感が無いワールドにプレイヤーを分散させるために利用されます。ソフトウェア（プラグイン機能）を使う場合にはパーティーを作成するプラグインを使うことで、パーティー単位で同じサーバに負荷分散（ログイン）させることもできます。

MMO サーバのようにプレイヤーのパラメータを別のサーバでも引き継いで利用したい場合には、Mammoth のように外部のデータベースにプレイヤーのデータを保存して、別のサーバで引き継いで利用するプラグインが必要となります。このようなプラグインは通常は存在しないため、必要に応じて自分で用意してください。Mammoth や MultiPaper サーバは別のサーバにログインしてもワールド（地形やエンティティ）の情報が外部で共有されているため SLB と非常に親和性が高く、大規模なマルチプレイサーバの構築に適しています。また、MultiPaper サーバにはソフトウェアの負荷分散機能が元から内臓されています。

総じて、SLB はサーバの負荷を均等に分散したい場合に利用します。「均等」の考え方は色々あるため、接続数、サーバの応答時間などどうすれば綺麗にサーバの負荷を分散できるのかを考えて導入する必要があります。

SLB の設置個所はクライアントとリバースプロキシの間、または、リバースプロキシとサーバの間の 2 パターン考えられます。前者の場合には、リバースプロキシ自体の負荷を分散させることができます。後者の場合には、資源ワールドだけを負荷分散したり、サバイバルワールドだけを MultiPaper サーバに置き換えたりといった使い方ができます。

### ワールドデータの共有
負荷分散装置を使ったスケールアウトの考え方は、可用性（システムが安定稼働するための能力）の観点では重要ですが、保守性（ワールドの修正などのメンテナンスのしやすさ）が落ちることはなるべく避けなければいけません。ワールドをコピーして増やせば増やすほど小さな修正作業の手間が増えていきますし、どのサーバを修正したのかも覚えていられないかもしれません。

そこで、Hypixel のチームが作った Minecraft のワールドデータを外部のデータベースに格納して利用する SlimeWorldManager という仕組みがあります。これは Hypixel のミニゲームサーバのように内容が変化しないワールド（アドベンチャーモードのワールド等）をデータベースに格納して、それを全てのサーバで使う仕組みです。これによって保守性を維持したまま可用性を上げることができます。

## 広域負荷分散（GSLB / DNS バランシング）
大規模なマルチプレイサーバを安定して稼働させるためには非常事態に備えておく必要があります。例えば、停電や地震などの災害です。最近はクラウドが広域負荷分散を備えているため、自分で広域負荷分散を実現する必要は無くなりましたが、それでも広域負荷分散を意識しておく必要はあります。

クラウドではリージョン（特定の地理に存在するデータセンターのグループ）を２つ以上使うことで、停電や地震に備えることができます。日本は地震が発生しやすいため、地震が発生する岩盤でリージョンを分けたり、単純に国内と国外の２つにサーバを分散させたりといった考え方で災害に備えることができます。

GSLB の負荷分散を利用することで、非常事態以外にもサービスの負荷を分散させることができるようになります。クライアントの最寄りの地域のサーバに通信させるようにしたり、負荷の多いリージョンへの分散を避けたり、このときあたかも同じ Minecraft サーバに接続しているように見せかけるにはサーバのドメイン（hogefugapiyo.minecraft-server.com などの Minecraft サーバの名前のこと）によって接続できるサーバを国内や国外に自動的に切り替える必要があります。この仕組みを DNS バランシングなどと呼びます。DNS というのはサーバの名前と実際の IP アドレスを関連付ける仕組みのことです。

当たり前ですが、負荷分散、広域負荷分散ともにプレイヤーのデータを外部において全サーバで共有するようにしなければ、MMO のようなマルチプレイは実現できません。ワールド（地形、エンティティ）の情報連携だけでよければ MultiPaper を利用することができます。

Hypixel などの世界的に有名なマルチプレイサーバの場合には GSLB を利用しているかもしれませんね。

## おまけ
これまでは Minecraft が動いているサーバの話をしてきましたが、大規模なマルチプレイサーバの運営を行うためには、サーバが正しく動作しているかを監視する仕組みも必要となります。24時間365日サービスを提供するためには必須となります。

![space_kanseishitsu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/31e80adc-4d6d-b570-bad3-e1ae7e48324d.png)

実は Minecraft サーバは障害が発生しても自分自身で悲鳴を上げることができません（受動監視ができない）。そのため、悲鳴を上げるための仕組みを自作するか、外部から能動的に監視をする監視サーバが必要となります（能動監視）。監視が面倒な場合には、数台程度サーバが停止してもサービスが停止せず稼働できる仕組みを作って放っておくという方法もあります。負荷分散装置や広域負荷分散がその方法となりますが、厄介なのはサーバの半死と呼ばれる状態です。

通常、停止したサーバは負荷分散装置から自動で切り離されますが「俺はまだ生きてるからプレイヤーをもっとよこせ」と高負荷でもギリギリ生きているサーバがあると、そのサーバにログインしようとするプレイヤーが快適に遊べずに不幸になります。そのため、半死に対応するには監視サーバを用意し、様々な方法でサーバを能動監視することで負荷分散装置から強制的にサーバを切り離すような仕組みを用意することになります。

# まとめ
以下の方式を組み合わせて1台のサーバのログイン人数を一定に保つことで、大規模マルチプレイサーバの環境を実現することができます。サーバのスペックをあげること（スケールアップ）ができなくても、サーバの台数は資金がある限り増やすこと（スケールアウト）ができます。

- Bungeecord、Velocity、Waterfallなどのリバースプロキシを使ってサーバを機能毎に分割することでログイン人数を分散する
- 負荷分散機能を使って同一機能のサーバを複数に分割してログイン人数を分散する
  - データを複数のサーバで共有するためにはデータベースにプレイヤーの情報を書き出す必要がある
- DNS バランシングや SLB を使ってリバースプロキシ自体を負荷分散させる
- Mammoth、MultiPaper、Folia などの多人数が入れるサーバをリバースプロキシの先に置くことでログイン人数を増やす
  - データを複数のサーバで共有するためにはデータベースにプレイヤーの情報を書き出す必要がある

# さいごに
書き殴ったので謎の文章になってたりするかもしれません。最後まで読んでくれた人ありがとうございました。

このコラム（うんちく）を読んだからといっていきなり大規模サーバが建てられるわけじゃありませんが、察しが良い人ならここはこうすれば良いのね、みたいな事は感じ取って貰えたと思います。