Mastodon
  • Mastodonの使い方
    • Signing up for an account
    • Setting up your profile
    • Posting toots
    • Using the network features
    • Dealing with unwanted content
    • Promoting yourself and others
    • Set your preferences
    • その他の設定
    • Using Mastodon externally
    • Moving or leaving accounts
  • Mastodonの構築
    • マシンの準備
    • ソースからインストール
    • 環境設定
    • オプションのインストール
      • 全文検索
      • 秘匿サービス
      • シングルサインオン
    • セットアップを完了する
    • 開発者向けコマンドラインを利用する
    • 新しいバージョンへアップグレード
    • サーバのバックアップ
    • 新しいマシンへの移行
    • サーバーのスケールアップ
    • モデレーション
    • トラブルシューティング
  • アプリケーションの開発
    • Getting started with the API
    • Playing with public data
    • Obtaining client app access
    • ログイン
    • ガイドラインとベストプラクティス
    • ライブラリ等
  • コントリビューション
    • 技術的情報
    • 開発環境のセットアップ
    • ソースコードの構造
    • ルーティング
  • スペック
    • ActivityPub
    • WebFinger
    • Security
    • Microformats
    • OAuth
  • REST API
    • OAuthスコープ
  • API一覧
    • apps
      • oauth
    • accounts
      • bookmarks
      • favourites
      • mutes
      • blocks
      • domain_blocks
      • filters
      • reports
      • follow_requests
      • endorsements
      • featured_tags
      • preferences
      • suggestions
    • statuses
      • media
      • polls
      • scheduled_statuses
      • streaming
    • timelines
      • conversations
      • lists
      • markers
    • notifications
      • push
    • search
    • instance
      • trends
      • directory
      • custom_emojis
    • admin
    • proofs
    • oembed
  • APIエンティティ
    • Account
    • Activity
    • Admin::Account
    • Admin::Report
    • Application
    • Attachment
    • Card
    • Context
    • Conversation
    • Emoji
    • Error
    • FeaturedTag
    • Field
    • Filter
    • History
    • IdentityProof
    • Instance
    • List
    • Marker
    • Mention
    • Notification
    • Poll
    • Preferences
    • PushSubscription
    • Relationship
    • Report
    • Results
    • ScheduledStatus
    • Source
    • Status
    • Tag
    • Token

サーバーのスケールアップ

並行処理能力の向上

Mastodonのプロセスには3つの種類があります。

  • Web (Puma)
  • Streaming API
  • バックグラウンド (Sidekiq)

環境変数は.env.productionで編集します。環境設定(.env.production)を参照してください。

Web (Puma)

Webプロセスはほとんどのアプリケーションに使われる個々のHTTPリクエストを処理します。以下の環境変数の数値を調節してください。

  • WEB_CONCURRENCYでワーカープロセスの数を設定できます。
  • MAX_THREADSでプロセスあたりのスレッド数を指定できます。

スレッドは親プロセスとメモリーを共有します。異なるプロセスには別のメモリーを割り当てますが、コピーオンライトを介していくつかのメモリを共有します。
スレッドの数が多いとCPU資源が不足し、プロセスの数が多いとRAMが不足する可能性があります。

これらの値は同時にいくつのHTTPリクエストを捌けるかに関わります。

スループットの観点では、スレッドよりもプロセスの方が優れています。

Streaming API

持続的なHTTPとWebSocketコネクションを処理します。クライアントはリアルタイムにアップデートを受信できます。 以下の環境変数の数値を調節してください。

  • STREAMING_CLUSTER_NUMでワーカープロセスの数を設定できます。
  • STREAMING_API_BASE_URLでStreaming APIのベースURLを指定できます。

ひとつのプロセスでたくさんの接続を処理できます。たとえば、接続をプロキシするNginxのオーバーヘッドを回避する場合は、Streaming APIを別のサブドメインでホストできます。

バックグラウンド (Sidekiq)

Mastodonの多くの処理はバックグラウンドに回されます。HTTPリクエストを高速化し、HTTPリクエストの中止がこれらのタスクの実行に影響を与えないために重要です。Sidekiqは単一のプロセスで、スレッドの数を設定できます。

スレッド数

Webプロセスのスレッド数が多くなれば、自インスタンスのユーザーからのアクセスに対する反応が速くなり、バックグラウンドのスレッド数が多くなれば投稿を他のユーザーやサーバーに届けたり、メールを送信したりするのが速くなります。

スレッド数は環境変数ではなく、Sidekiqの呼び出しにおけるコマンドライン引数によって制御されます。

bundle exec sidekiq -c 15

Sidekiqを15スレッドで開始します。各スレッドはそれぞれデータベースに接続できる必要があります。つまり、データベースプールはすべてのスレッドを処理するのに十分な量である必要があります。データベースプールのサイズはDB_POOL環境変数で制御され、少なくともスレッド数と同じでなければなりません。

キュー

Sidekiqは様々な重要度のキューを様々な処理に使います。重要度は、それが機能しなかった場合にサーバーのローカルユーザーのUXにどの程度影響するかの度合いが高い順に定義されます。

キュー名 重要性
default ローカルユーザーに影響する全て
push 他のサーバーにデータ(ペイロード)を送信
mailers メールの配信
pull 他のサーバーからデータを取得

defaultキューについては、config/sidekiq.ymlにその重要性が記されていますが、Sidekiqのコマンドラインによって上書きできます。

bundle exec sidekiq -q default

これは defaultキューだけを実行するものです。

Sidekiqのキューの処理法では、最初のキューのタスクを最初にチェックし、タスクがない場合は次のキューをチェックします。つまり、最初のキューがいっぱいになると、以降のキューの実行が遅れるということです。

それを防ぐためには、たとえば異なる引数を使用してSidekiqの複数のsystemdサービスを作成することにより、キューに対して異なるSidekiqプロセスを開始して、並列実行させるなどが考えられます。

pgBouncerによるトランザクション処理のプール

pgBouncerによるトランザクションのプールについて説明します。

なぜpgBouncerが必要なのか

使用可能なPostgres接続数が不足し始めた時(デフォルトは100)、pgBouncerはそれを解決するいい方法です。このドキュメントではいくつかのよくある間違いと標準的なMastodon向けの適切な設定について説明します。

管理者はWebUIの設定からPgHeroでPostgresの現在の接続数を確認できます。通常、Mastodonは、PumaやSidekiq、ストリーミングAPIを合わせたスレッド数と同数の接続を使用します。

pgBouncerのインストール

DebianやUbuntuでは、

sudo apt install pgbouncer

pgBouncerの設定

パスワード設定

まず、Postgresのmastodonユーザーにパスワードが設定されていない場合、設定する必要があります。

パスワードをリセットするには

psql -p 5432 -U mastodon mastodon_production -w

を実行し、(“password"をパスワードにはしないとは思いますが)パスワードを設定する例です。

ALTER USER mastodon WITH PASSWORD 'password';

終わったら \qと打って終了します。

userlist.txtの編集

/etc/pgbouncer/userlist.txtを編集します

後でpgbouncer.ini内でユーザー/パスワードを指定するならuserlist.txtの値は実際のPostgreSQLのロールに対応している必要はありません。ユーザーとパスワードを任意に定義できますが、簡単にするために「実際の」資格情報を再利用できます。userlist.txtにmastodonユーザーを追加します。

"mastodon" "md5d75bb2be2d7086c6148944261a00f605"

ここではmd5を使っています。md5のパスワードはmd5文字列を前に付けたpassword + usernameです。例えば、mastodonユーザーのパスワードがpasswordならば、

# ubuntu, debian, etc.
echo -n "passwordmastodon" | md5sum
# macOS, openBSD, etc.
md5 -s "passwordmastodon"

として、初めにmd5と付ければ完了です。

pgbouncerというAdminユーザーをpgBouncerのAdminデータベースにログインするため作成します。userlist.txtの例です。

"mastodon" "md5d75bb2be2d7086c6148944261a00f605"
"pgbouncer" "md5a45753afaca0db833a6f7c7b2864b9d9"

passwordをパスワードにした場合の例です。

pgbouncer.iniの設定

/etc/pgbouncer/pgbouncer.iniを編集します。

接続するPostgresデータベースを[databases]の下に追加します。pgBouncerが同じユーザー名、パスワードとデータベース名を使用して、基礎となるPostgresデータベースに接続するようにします。

[databases]
mastodon_production = host=127.0.0.1 port=5432 dbname=mastodon_production user=mastodon password=password

listen_addrとlisten_portはpgBouncerが接続を受け入れるようにアドレス/ポートを入れます。デフォルト値で問題ありません。

listen_addr = 127.0.0.1
listen_port = 6432

auth_typeとしてmd5を入れます。(userlist.txtでmd5形式を使っているとしています)

auth_type = md5

pgbouncerをAdminにします。

admin_users = pgbouncer

**これは大事な設定です!**標準のプールモードはセッションをもとにしていますが、Mastodonではトランザクションをもとにしています。つまり、Postgresはトランザクションによって接続され、それが完了されると接続も破棄されます。よって、pool_modeはsessionからtransactionに変更します。

pool_mode = transaction

そして、max_client_connでpgBouncer自身の最大接続数を定義し、default_pool_sizeでpgBouncer下のPostgres接続数を制限します。 (PgHeroはpgBouncerの存在を関知しないので、pgBouncerを導入した場合「Postgresの現在の接続数」は常にdefault_pool_sizeの値を表示します)

初期値でも問題ありません。この値はいつでも変更可能です。

max_client_conn = 100
default_pool_size = 20

変更後はpgbouncerの再読込や再起動をお忘れなく。

sudo systemctl reload pgbouncer

すべてが機能するかをデバッグする

Postgresと同じようにpgBouncerに接続できるはずです。

psql -p 6432 -U mastodon mastodon_production

そしてパスワードを使ってログインします。

pgBouncerのログを確認します。

tail -f /var/log/postgresql/pgbouncer.log

MastodonがPgBouncerと接続するように設定

.env.productionでまずこれが設定されていることを確認してください。

PREPARED_STATEMENTS=false

トランザクションベースのプーリングを使用しているため、準備済みのステートメントを使用できないからです。

そして、Postgresの5432ポートから、pgBouncerの6432番ポートに変更します。

DB_HOST=localhost
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=password
DB_PORT=6432

注意 pgBouncerを使ってdb:migrateはできません。しかし、これは簡単に回避できます。もし同一ホストにpgBouncerがあるなら、DB_PORT=5432とRAILS_ENV=productionの後に付けるだけです。 RAILS_ENV=production DB_PORT=5432 bundle exec rails db:migrate (DB_HOSTなども自由に指定できます)

pgBouncerの管理

再起動する

sudo systemctl restart pgbouncer

pgBouncerのAdminユーザーを設定している場合、Adminとしてログインし、

psql -p 6432 -U pgbouncer pgbouncer

再読込します。

RELOAD;

完了後、\qで終了します。

Redisの分離

Redisはアプリケーション全体で広く使用されていますが、一部重要なものも含まれています。ホームフィード(各ユーザーのホームタイムライン)、リストフィード(各ユーザーのリストのタイムライン)、Sidekiqキュー、およびストリーミングAPIはRedisによってサポートされており、それは失うべきでない重要なデータです。(PostgreSQLデータベースの損失とは異なり、失っても復元可能ですが、もちろん失ってはいけません。)ただし、Redisは一次的なキャッシュにも使用されます。スケールアップ段階で、Redisがすべてを処理できるかどうか不明な場合は、キャッシュに別のRedisデータベースを使用できます。環境設定でCACHE_REDIS_URLやCACHE_REDIS_HOST, CACHE_REDIS_PORTを個別に指定するなどができます。未指定であれば、キャッシュプレフィックスがない場合と同じ値にフォールバックします。

Redisデータベースの設定に関するものは、再起動時にデータが失われるかどうかは関係なくディスクI/Oを保存できるため、基本的にディスクへのバックグラウンド保存を回避することができます。最大メモリ制限とキー削除ポリシーを追加することもできます。詳しくはこのガイドを参照してください: Using Redis as an LRU cache

リードレプリカ

PostgreSQLサーバーの負荷を軽減するには、ホットストリーミングレプリケーション(リードレプリカ)をセットアップすることをお勧めします。 参照次の方法で、Mastdonのレプリカを使用できます。

  • ストリーミングAPIサーバーは書き込みが発生しないため、レプリカに直接接続できます。しかし、そもそもデータベースを頻繁にクエリすることはないため、効果はほとんどありません。
  • WebおよびsidekiqプロセスでMakaraドライバーを使用して、書き込みがmasterデータベースに、読み取りがレプリカに行われるようにします。以下ではこれについて書きます。

config/database.ymlを編集して、次のようにproductionセクションを置き換える必要があります。

production:
  <<: *default
  adapter: postgresql_makara
  prepared_statements: false
  makara:
    id: postgres
    sticky: true
    connections:
      - role: master
        blacklist_duration: 0
        url: postgresql://db_user:db_password@db_host:db_port/db_name
      - role: slave
        url: postgresql://db_user:db_password@db_host:db_port/db_name

URLがPostgreSQLサーバーを指していることを確認してください。レプリカは複数追加できます。でローカルにインストールされたpgBouncerは、データベース名に基づいて2つの異なるサーバーに接続する設定をすることで使用することができます。たとえば、「mastodon」がマスターに、「mastodon_replica」がレプリカに行くため、両方のURLでローカルpgBouncerが指すようになります。ユーザー、パスワード、ホスト、ポートは同じですが、データベース名が異なります。これをどのようにセットアップできるかはまだ未知数です。Makaraの詳細については、ドキュメント.を参照してください。

Sidekiqは「ちゃんと」リードレプリカを使用できません。レプリケーションにかかるほんの数ミリ秒のラグが、キューに入れられたレコードが見つからないという理由でジョブを失敗させるからです。

最終更新 February 12, 2020 · このページを改善する
他の言語: English

Merch

Tシャツとステッカー(英語)

Mastodonに参加しよう · ブログ · ·

ソースコード · CC BY-SA 4.0 · インプリント