BackEnd

【Puma】アプリサーバのチューニング

投稿日:

はじめに

みなさん、アプリサーバのチューニングはどのように行っていますか?
私の場合、使うサーバのスペックがだいたい同じくらいなので、過去の設定ファイルを使いまわしていました。

そんな中、先日本番環境で初めてPumaを使用しましたが時間の都合でチューニングが行えませんでしたので、今回Pumaのパフォーマンスチューニングについて調べてみました。

 

チューニングで注意する項目

アプリサーバのチューニングにおいて注意する項目は下記のとおりです。

  • 子プロセスの数
  • スレッドの数
  • Copy-on-write
  • サーバスペック(メモリ、CPU等)

これらの項目はPumaに限らずUnicornやPassengerなどの他のアプリサーバにも当てはまります。
それでは個別の設定を見ていきましょう。

 

子プロセスの数

Puma(UnicornとPassengerも同様)はforkを使う設計になっており、アプリのプロセス1つから複数のコピー(子プロセス)を作成します。
これにより、例えば2コア4スレッドのマシンなら4つの子プロセスを作成することで大幅にパフォーマンスを向上させることができます。
この子プロセスの数がチューニングにおける最も重要な設定です。

最低3つの子プロセスを割り当てる

1サーバあたり最低3つの子プロセスを割り当てるのとルーティングの効率が良いようで、それに合わせてサーバスペックを調整すると良いです。
最適な子プロセスの数については、CPU使用率や搭載するRAMに合わせて調整します。

最大子プロセス数

最低3つの子プロセスを割り当てれば良いことはわかりました。では、最大でいくつの子プロセスを割り当てることができるでしょうか。
これはRAMとCPUで決まります。

まず、RAMですがサーバのRAMがサポートできる個数を上回る子プロセスを割り当てるとパフォーマンスが低下します。
なので、メモリ使用量には余裕を保つ必要があります。
一つの目安として下記の式を見てください(多くのRubyアプリは1プロセスあたり200MBから400MBのメモリを使います)
(RAM / (プロセスあたりのメモリ使用量 * 1.2))

次にCPUですが、サーバの利用可能なCPUキャパシティを超えないようにする必要があります。
理想的には、CPU使用率100%になる総割り当て時間の5%を超えないことです。

CPUコア数と子プロセス数

一般に「CPUのコア数より多くの子プロセスを1サーバに割り当てるべきではない」と言われますが、多くのアプリケーションではプロセスの数は利用できるハイパースレッドの数の1.25倍から1.5倍に落ち着くようです。

なぜPumaの子プロセス数を増やす必要があるのか

Pumaはマルチスレッドに完全対応したアプリサーバなのに、なぜプロセス数を増やす必要があるのかと疑問を持つかもしれません。
たしかに、JRubyやRubiniusを使用しているのならば、理論上は1つのプロセスで処理することができます。
しかし、MRIにはグローバルVMロック(GVL)という仕組みがあり、一度に1つのRubyプロセスで実行できるスレッドは1つに制限されてしまうためです。

 

スレッド数

次にスレッド数について見ていきます。
並列化によってどの程度スピードが上がるかは、それぞれのアプリケーションの並列化度合いによります。

一般的にはスレッド数は”5”で良い

上述の通り、MRIではGVMの影響でIO待ちのみ並列化できるため、スレッド数を増やすことによる恩恵を受けにくいという特徴があります。
また、MRIではスレッド数を増やす事によりメモリを大幅に消費する場合があります。
スレッド数は現在の設定での測定値を定期的にチェックして設定するのが良いですが、一般的にはスレッド数を5に設定して放置してもたいてい大丈夫なようです。

 

Copy-on-write

あらゆるUnixベースのOSはメモリの挙動がCopy-on-writeで実装されています。
Copy-on-writeとは簡単に説明すると、プロセスがforkして子プロセスができた時点ではメモリを親プロセスと完全に共有していて、子プロセスに変更があった場合に初めてコピーされて子プロセス専用メモリになる方式です

効率を高めるために

Copy-on-writeはオフにできるものではありません。
Copy-on-writeの効率を高めるためにはforkの前にアプリを全て読み込む必要があります(設定に関しては後でまとめて記載します)

 

サーバスペック

一般的に、サーバで利用可能なCPUやメモリの使用率は70%から80%に留めるのが良いとされています。
子プロセスの数で書いたとおり、最低でも子プロセスは3つにしたほうが効率が良いため、これを考慮してスペックを決めると良いと思います。

また、ハイパースレッドの数に応じてプロセス数の上限が決まるため、コア数やハイパースレッディングをサポートしているのか等も確認しておくと良いでしょう。

 

設定サンプル

では、実際にPumaの設定ファイルを書いてみましょう。
Pumaの設定ファイルはconfig/puma/に作成します。

  • 子プロセスの数
  • スレッドの数
  • Copy-on-write

上記のポイントを考慮して作成した設定ファイルは下記の通りです。

デーモンとして起動

アプリケーションを長時間バックグラウンドに常駐させるために、デーモンとして起動します。

workerを定期的に再起動させる

Pumaのworkerは起動して暫く経つとメモリの消費が膨れ上がるため、定期的にworkerを立ち上げ直します。
これには、PumaWorkerKillerというGemを利用します。
https://github.com/schneems/puma_worker_killer

 

さいごに

今回いろいろ調べて見ましたが、改めてNginx+Unicornという構成は鉄板なんだなと思いました。
せめてMRIでもフルにスレッドを利用できれば良いのですが、今後に期待します。
Pumaのデプロイ設定に関してはこちらでまとめていますので、よろしければ御覧ください。

 

参考

page_footer_300rect




page_footer_300rect




-BackEnd
-,

執筆者:


comment

メールアドレスが公開されることはありません。

CAPTCHA


関連記事

Go言語

Go言語の基礎〜Go 1.11 開発環境構築とパッケージバージョン管理〜

1 はじめに2 Go言語(Golang)とは2.1 シンプルな構文2.2 コンパイル言語2.3 並行処理2.4 その他の特徴3 Go開発環境の構築3.1 Goのインストール3.1.1 1. homeb ...

Go言語

Go言語、ゴルーチン(goroutine)で並列処理を

1 はじめに2 ゴルーチン2.1 go文2.2 ゴルーチンの終了条件2.3 WaitGroup3 チャネル3.1 チャネルの型3.2 チャネルの生成3.3 チャネルの送受信3.4 チャネルとゴルーチン ...

rails

Rails5.2+Pumaのデプロイ設定

1 はじめに1.1 環境2 Pumaとは?2.1 Unicornとの比較2.2 Pumaのスレッド3 Pumaの使い方4 デプロイ設定4.1 Gemを追加4.2 Capfileの設定4.3 deplo ...

Go言語

Go言語でテスト作成 testifyの基本的な使い方

1 はじめに2 Goテストフレームワークのスター数3 testifyについて3.1 testifyを導入する方法4 assartionについて4.1 assertion紹介4.2 ElementsMa ...

rails

Active Strageを使用してユーザーのアバターを登録、表示する

1 はじめに1.1 環境2 セットアップ2.1 前準備2.2 マイグレーションファイル作成2.3 設定ファイル3 実際に使って見る3.1 モデル3.2 コントローラー3.3 ビュー4 個人的メモ4.1 ...

フォロー

follow us in feedly

AppLink

英語

page_side_300rect

2018年8月
« 7月 9月 »
 1234
567891011
12131415161718
19202122232425
262728293031 

アプリ情報

目標を達成したい方を応援する、TODOアプリもリリースしております。 下記のアイコンから無料でダウンロードできます。

Web版MyCoach

私たちはより広い方にコーチングを知ってもらいたいと考えています。 下記のサイトにて、コーチの方々を紹介しておりますので、よろしければご覧ください。