アプリが遅いときに考えること

Railsが遅いと言われたときにやること完全ガイド 🔗

APM (アプリケーションパフォーマンスモニタリング) とは何ですか? 🔗

SKYLIGHT

ログイン後の画面遷移が遅いと、ユーザーとしては少し不安になります。結論から言うと、原因はデータベース(MySQL)だけでなく、アプリケーション(Rails)側、あるいは外部サービスとの連携など、複数の可能性が考えられます。

まずは「どこで時間がかかっているか」を特定するのが解決への近道です。以下のステップで確認を進めてみてください。

1. ログ(development.log / production.log)を確認する

Railsのログには、処理時間の内訳が記録されています。ログイン時のリクエストを探し、以下の数値を確認してください。

  • Completed 200 OK in XXXms (Views: XXms | ActiveRecord: XXms)
    • ActiveRecord の数値が大きい場合:MySQLのクエリ(検索や更新)に時間がかかっています。
    • Views の数値が大きい場合:遷移先画面のレンダリング(HTML生成)が重いです。
    • それ以外(コントローラ内での処理) が大きい場合:外部API呼び出しや、パスワードのハッシュ化、複雑なロジックが原因です。

2. 確認すべきコードの箇所

① SessionsController#create(ログイン実行メソッド)

ログインボタンを押した直後に動くコードです。

  • パスワード検証: user.authenticate(params[:password]) は意図的に負荷をかける処理ですが、極端に遅い場合はサーバーのスペック不足の可能性があります。
  • 外部通信: ログイン時に「外部サービスへ通知」や「SNS連携のデータ同期」などを同期処理(非同期ではなく)で行っていませんか?

② ログイン後のリダイレクト先(home#index など)

「ログイン処理」自体ではなく、**「ログインした後に表示する画面」**に原因があるパターンが多いです。

  • N+1問題: ログイン後のトップ画面で、ユーザーの投稿、コメント、フォロー状況などを一気に取得していませんか?
  • 重い集計クエリ: データベースで COUNT や SUM などを大量に実行している場合は、MySQL側にインデックスが貼られているか確認が必要です。

③ ApplicationController の before_action

ログイン後に必ず動く共通処理(current_user の取得や権限チェック)で、重いクエリが走っていないか確認してください。

3. ボトルネックを特定するツール

コードを目で追うよりも、以下のツールを使うと一発で原因がわかります。

  • rack-mini-profiler: 開発環境の画面左上に、その画面を表示するのにかかった時間(SQLの発行回数や時間)を表示してくれます。Railsエンジニアの必須ツールです。
  • bullet: N+1問題が発生している場合に警告を出してくれます。

まとめ:チェックリスト

まずはこれを確認してみてください。

確認項目チェック内容
SQLログ同じような SELECT 文が大量に発行されていないか?(N+1)
インデックス検索(email など)に使っているカラムに index は貼ってあるか?
外部通信API連携などを delay(非同期)にせず実行していないか?

まずは開発環境のログで “ActiveRecord” の数値がどれくらい占めているか見てみませんか?もしその数値が大きければ、具体的なSQLのチューニング(インデックス作成など)をお手伝いできますよ。

ファイアウォールが原因で「遅く」なる唯一のケース:外部通信のタイムアウト

結論から言うと、「ログインボタンを押した後に時間がかかる」という状況において、ファイアウォールが原因である可能性はかなり低い

ファイアウォールが原因であれば、通常は「遅い」のではなく、接続そのものが拒否されて**「タイムアウト(接続不可)」**になるか、最初から画面が表示されないはずだからです。

ただし、1点だけ「ファイアウォール(またはネットワーク設定)が原因で遅くなる」例外的なパターンがあります。

Railsアプリがログイン処理の最中に、「自分以外のサーバー」に通信しようとして、それをファイアウォールがブロックしている場合です。

  1. ユーザーがログインボタンを押す。
  2. Railsが「ログイン完了」を記録しようとする。
  3. その際、コードの中で「認証ログを外部のログサーバーに送る」や「外部APIに通知する」といった処理が走る。
  4. **ファイアウォールがその外部通信を遮断(Drop)**していると、Railsは「応答がないな…」と数秒〜数十秒待ち続け(タイムアウト待ち)、その間ユーザーの画面は止まったままになります。
  5. 最終的に通信を諦めてから、ようやく画面が遷移する。

もし心当たりがあれば、config/environments/production.rb やコントローラ内で、外部サービス(分析ツール、メール配信、Slack通知など)を呼び出していないか確認してみてください。

これらが**「同期処理(レスポンスを待ってから次に進む設定)」**になっていると、外部サーバーの応答待ち時間がそのまま画面遷移の遅延(数秒〜タイムアウトまで)に繋がります。

1. 認証・セキュリティ系

最も可能性が高いのがこれらです。

  • OAuth / SNSログイン (Google, LINE, GitHubなど):
    • ユーザーがボタンを押した後、Rails側から各プラットフォームのAPIを叩いて「このアクセストークンは正しいか?」を確認しに行きます。相手方のサーバーが重い、またはネットワーク経路で詰まると遅延します。
  • ReCAPTCHA (Google):
    • ボット対策で導入している場合、フロントエンドだけでなくバックエンド(Rails)からも「このユーザーは人間か?」という判定リクエストをGoogleに送ります。
  • IPアドレスによる位置情報特定:
    • ログイン元の国や地域を特定するために、geocoder などのライブラリを使って外部のIPデータベースAPIに問い合わせている場合があります。

2. 通知・ログ送信系

「ログインした」というイベントをきっかけに動く処理です。

  • メール送信 (SendGrid, Amazon SESなど):
    • 「新しいデバイスからログインがありました」といった通知メールを非同期(SidekiqやActive Job)にせず、その場で送ろうとすると、メールサーバーとの通信が終わるまで画面が切り替わりません。
  • チャット通知 (Slack, Discord, Microsoft Teams):
    • 管理用チャットに「ユーザーAがログインしました」と通知を飛ばすWebHook処理です。
  • アクセス解析・CRM (HubSpot, Salesforce, Mixpanelなど):
    • マーケティングツールに「ログイン日時」を同期する処理がコントローラに書かれている場合です。

3. インフラ・ネットワーク関連(APIではないが似た挙動)

  • ストレージ (Amazon S3):
    • ログイン直後にユーザーのアイコン画像などをS3から取得し、その「署名付きURL」を発行する処理が重い、あるいは通信がブロックされているケース。
  • DNS解決の遅延:
    • データベース(RDSなど)への接続にホスト名を使っている場合、DNSサーバーの応答が遅いと、接続のたびに数秒待たされることがあります。

確認する方法:コードのどこを見るべきか?

Railsで外部通信が発生しているか調べるには、以下の単語でプロジェクト内を検索(Grep)してみてください。

  1. HTTParty / Faraday / Net::HTTP: これらはRubyで外部通信を行う際によく使われるライブラリです。
  2. deliver_now: メールの送信メソッドです。これがあると、メール送信が終わるまで処理が止まります(deliver_later なら非同期なので速いです)。
  3. Devise のコールバック: after_set_user や after_authentication といったメソッドが config/initializers/devise.rb や User モデルに定義されていないか確認してください。

次のステップへの提案

もし外部APIの関与を疑うなら、**「意図的にネットワークをオフにした状態で、ローカル環境でログインを試す」**のが一番手っ取り早いです。

もしネットワークオフでエラーが出たり、逆にサクサク動いたりするなら、そこがボトルネックです。一度、**Gemfile に入っている通信系のGem(octokit, rest-client, sendgrid-ruby など)**をチェックしてみませんか?

データベース(MySQL)周りで確認すべきコード

ファイアウォールでないとすれば、やはり「データ量」や「クエリの書き方」が怪しいです。以下のコードをチェックしてみてください。

1. インデックスの有無(db/schema.rb)

ログイン時は通常 email などでユーザーを検索します。そのカラムにインデックスがないと、ユーザー数が増えた時に激重になります。

Ruby

# db/schema.rb 内で email に index があるか確認

t.string

“email”, default: “”, null: false

t.index [

“email”], name: “index_users_on_email”, unique: true # これがあるか!

2. N+1 問題(app/controllers/sessions_controller.rb)

ログイン後にリダイレクトする先の「トップ画面」のコントローラを見てください。

Ruby

# ダメな例:Viewで投稿者の名前を表示するのに、投稿数分だけSQLが走る

@posts

= Post.all

# 良い例:一括で取得する

@posts = Post.includes(:user

).all

まずは**「ローカルの開発環境でも同じように遅いか」**を確認してみてください。

  • 開発環境でも遅い場合: コード(SQLやロジック)の問題です。
  • 本番環境だけ遅い場合: データベースのスペック不足、ネットワーク(前述の外部通信ブロック)、または本番特有のデータ量の多さが原因です。

まずは開発環境のログに表示される ActiveRecord: XXms の数値が何秒くらいになっているか、見てみてもらえますか?そこが 100ms を超えているようなら、SQLの改善ポイントを絞り込めます。

あなたのプロンプト

どのような外部APIへのアクセスが考えられますか

More Reading

Post navigation

Leave a Comment

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です