2
0

More than 1 year has passed since last update.

ElasticBeanstalkでのPuma, Rails, MySQLの接続など

Last updated at Posted at 2022-06-13

ElasticBeanstalkで動いているRailsアプリでPumaのワーカー、スレッド、DBへの接続などの動きを把握した際の記録

環境

  • ElasticBeanstalk Ruby2.7 Amazon Linux2

Pumaの特徴

マルチスレッドである

  • スレッドプールを使ってリクエストを処理する
  • 各リクエストは別々のスレッドで処理される
  • 複数のリクエストに対して、あるスレッドがブロックされリクエスト処理中の場合、別のスレッドで新しいリクエストを並行処理(concurrency)できる

クラスターモード

  • マスタープロセスからworker(子プロセス)をforkするクラスターモードがある
  • workerはそれぞれ独自のスレッドプールをもつ
  • これにより並列処理(parallel)が可能になるが、forkはメモリ空間全体を複製するため、より多くのメモリを消費することになる
  • アプリケーションの並行処理数(concurrency)は、最大で threads * workers となる
  • 例えばスレッド数最小8,最大32,ワーカー数3で起動する場合
puma -t 8:32 -w 3
  • Puma はトラフィックの量に応じて、最小値から最大値に達するまでスレッド数を自動的に調整する

Puma.stats

Pumaには状態を出力する標準インターフェースPuma.statsが用意されている。現在のワーカー数、スレッド数、処理待ちのリクエスト数(backlog)など。

Railsにおける処理の流れ

puma-flow.png

  • PumaはWebサーバとしての機能を兼ねることもできるが、通常の本番運用ではPumaはアプリケーションサーバとしての機能に特化させて、NginxやApache等のWebサーバを前段におくことが多い
  • HTTP リクエストを web サーバーである NginxやApacheで受け取り、Nginx はそのリクエストを Puma に Socket 通信で渡し、Pumaはそのリクエストを Rackに渡し、最終的に Railsのrouterに渡される。

Railsのデータベースコネクション

この辺の話。Railsガイド - データベース接続をプールする

コネクションプール

Active Recordではコネクションプールが提供されている。リクエストを処理するときにDB接続・切断を毎回行うのではなく、処理が終わっても接続を保持しておき、以降のリクエストではコネクションプールから接続を使い回す。そのため、単純にリクエストが増えたからといってDBへの接続数は増えたりしない。

The basic idea is that each thread checks out a database connection from the pool, uses that connection, and checks the connection back in. -ActiveRecord::ConnectionAdapters::ConnectionPool

コネクションがすべて使われていて、さらに他のスレッドが接続を取得しようとした場合、他のスレッドが接続を返却するまで待ちが発生する。

if all connections have been checked out, and a thread tries to checkout a connection anyway, then ConnectionPool will wait until some other thread has checked in a connection.

コネクションプール数の設定

Railsはワーカー単位でコネクションプールを保持する。database.yml内のpoolはワーカーごとのプールが管理できる最大接続数を設定する。アプリケーションがマルチプロセスで動作している場合、それぞれのプロセスでデフォルトでは最大5つの接続を持つことになる。RAILS_MAX_THREADSが設定されていれば、ワーカーあたりのMAXのスレッド数 = ワーカーあたりの最大接続数となる。

config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

実際に適用されている値をrails cで確認したい場合

irb(main):002:0> Rails.application.config.database_configuration

コネクションプールの使用状況はstat()で確認できる

irb(main):002:0> ActiveRecord::Base.connection_pool.stat
=> {:size=>5, :connections=>0, :busy=>0, :dead=>0, :idle=>0, :waiting=>0, :checkout_timeout=>5.0}

利用可能な数を超えるコネクションを使おうとすると、Active Recordはコネクションをブロックし、プールのコネクションが空くのを待つ。コネクションを取得できない場合はActiveRecord::ConnectionTimeoutErrorが発生する。

まとめると、DBの最大接続数を確認しておき

SHOW GLOBAL VARIABLES LIKE 'max_connections';

その上で以下を維持する必要がある

ワーカー数 * コネクションプール設定数 * インスタンス台数 <= DBの最大接続数

ElasticBeanstalkでのPumaの設定値

デフォルト設定

デフォルトではElasticBeanstalkが生成する/opt/elasticbeanstalk/config/private/pumaconf.rbが参照され、Railsのディレクトリ内のconfig/puma.rbは参照されない。詳細はこちら参照

[ec2-user@ip-xxx-xx-xx-xx ~]$cd /opt/elasticbeanstalk/config/private/
[ec2-user@ip-xxx-xx-xx-xx private]$cat pumaconf.rb 
directory '/var/app/current'
threads 8, 32
workers %x(grep -c processor /proc/cpuinfo)
bind 'unix:///var/run/puma/my_app.sock'
stdout_redirect '/var/log/puma/puma.log', '/var/log/puma/puma.log', true

ワーカー数を確認する

  • ワーカー数はインスタンスのコア数とイコールになるよう設定されている
  • 以下の通りlinuxにおいてCPU情報が格納されている/proc/cpuinfoを参照してワーカー数を決定している
  • 私の環境ではコア数2なのでワーカーが2個起動している
    スクリーンショット 2022-06-11 17.31.02.png
  • 最大スレッド数は2workers×32threadsで64threadsということになる

ワーカー内のスレッド数を確認する

ワーカーごとのプロセスIDを確認し、それをもとにprocfsを参照する

[ec2-user@ip-xx-x-x-xxx ~]$ps auxf | grep puma
webapp    5950  0.0  0.4 289928 33016 ?        Ss    6月10   0:09 puma 5.6.4 (unix:///var/run/puma/my_app.sock) [current]
webapp    6183  1.0  6.9 3301504 548528 ?      Sl    6月10  31:13  \_ puma: cluster worker 0: 5950 [current]
webapp    6184  1.0 13.5 3338368 1068240 ?     Sl    6月10  30:37  \_ puma: cluster worker 1: 5950 [current]
[ec2-user@ip-xx-x-x-xxx ~]$grep Threads /proc/6183/status
Threads:        17

psコマンドでスレッド情報をつけてみることもできる。-LをつければOK。LWP(Light Weight Process)がスレッドID、NLWP(Number of LWPs)がスレッド数なのでNLWPの数がプロセス内のスレッド数。(※head -1~の部分はpsの結果をgrepするとヘッダ行が入らなくて見づらいので入れてる)

ps auxww -L |head -1 && ps auxww -L |grep puma: |grep -v grep

スクリーンショット_2022-06-12_15_54_28.png

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0