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アプリがログイン処理の最中に、「自分以外のサーバー」に通信しようとして、それをファイアウォールがブロックしている場合です。
- ユーザーがログインボタンを押す。
- Railsが「ログイン完了」を記録しようとする。
- その際、コードの中で「認証ログを外部のログサーバーに送る」や「外部APIに通知する」といった処理が走る。
- **ファイアウォールがその外部通信を遮断(Drop)**していると、Railsは「応答がないな…」と数秒〜数十秒待ち続け(タイムアウト待ち)、その間ユーザーの画面は止まったままになります。
- 最終的に通信を諦めてから、ようやく画面が遷移する。
もし心当たりがあれば、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)してみてください。
- HTTParty / Faraday / Net::HTTP: これらはRubyで外部通信を行う際によく使われるライブラリです。
- deliver_now: メールの送信メソッドです。これがあると、メール送信が終わるまで処理が止まります(deliver_later なら非同期なので速いです)。
- 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へのアクセスが考えられますか
Leave a Comment