マストドンを運用する

マストドンは主に3つの機能から成り立っています。

  • Webアプリケーションサーバ (Rails)

  • WebSocketストリームサーバ (Node.js)

  • 非同期処理ワーカー (Sidekiq)

マストドンを実行するには、これらのプロセスを動かさなければなりません。

また、ミドルウェアとして

  • PostgreSQL

  • Redis

を利用します。

手っ取り早くdockerで

簡単に実行するならdockerが一番よいでしょう。 また、docker-compose.ymlを読めば個別に起動するときの参考にもなります。

$ cp .env.production.sample .env.production

いくつかある *SECRET* という名前の環境変数に、 rake secret で作った文字列を入れておきます。 データベースを永続化するには db: volumes のコメントアウトを外しておきましょう。

$ docker-compose run --rm web rake db:migrate
$ docker-compose run --rm web rake assets:compile

で準備をしたら、

$ docker-compose up

で起動します。 PostgreSQLやRedisも同時に起動されます。

これで http://localhost:3000 でマストドンにアクセスできます。 あとはフロントにNginxなどを立ててリバースプロキシをやらせればいいでしょう。 一般的なRailsアプリの実行方法と一緒です。

ただし、dockerでは本番運用にはほとんど通用しません。

スケールする構成

大規模で運用する場合はdockerを諦めたほうがいいでしょう。 まず、PostgreSQLとRedisは一般的なスケールできる仕組みを使います。 RDSやElastiCacheを利用したり、自前でクラスタリングします。 ここで気をつけるのは、Railsの世界にリードレプリカの概念はないということです。 何も考えずにRDSを使うことを推奨します。

マストドンはSPAなので、Railsの負荷はほぼAPIリクエスト数に依存します。 ひとつひとつの処理はシンプルなのであまり負荷は高くなく、レスポンスタイムも高速です。 一般的なRailsをスケールさせる方法がそのまま使えます。

StreamはWebSocketなのでクライアントは接続を維持します。 タイムラインの種類ごとに接続するので、ユーザ数 * 4〜5本くらいのクライアントが繋ぎっぱなしになります。 そういうのはnode.jsがめちゃくちゃ得意なので特に気にしなくていいでしょう。

問題はSidekiqです。 マストドンの重要な処理はほとんどワーカーで行われており、負荷もほとんどワーカーに集中します。 さらに、ワーカーの負荷はユーザの状況によって変化し、予想しづらいという難点があります。 例えば、あるユーザがトゥートすると、フォロワーのホームタイムラインにそのトゥートを送信します。 その場合、フォロワーの数だけ「トゥートを送信する」というジョブが登録されます。 ジョブはその性質から、またデータベースから find しなければならないので、結構重い処理です。 人気のあるユーザがトゥートすると、数千回 Status.find(id) が走るということになります。 これは結構大変なコストです。 ただ、データベースさえ詰まらなければプロセス数を増やしたぶんだけ綺麗にスケールしてくれます。 今のところ、CPUのコア数と同じ数のプロセスを立ち上げ、それぞれのプロセスでは concurrency の設定を 40スレッド にしておくと、最良なパフォーマンスが得られるとされています。

とにかくSidekiqをどれだけ用意するか、そしてデータベースはそのコネクション数に耐えられるか、が肝になります。 RailsやNodeは1台あたり数コネクションしか消費しませんが、Sidekiqは大量のコネクションを消費します。 例えば8コアCPUのマシンをSidekiqに使うと、1台あたり320コネクションも使うことになります。 実際に運用してみると、おそらく ジョブの消化が間に合わない という問題に当たります。 ジョブの消化に十分なワーカー数 を確保し、そこから 必要なデータベースインスタンスの性能 を導くことになると思います。

Last updated