web-dev-qa-db-ja.com

PHPセッションのUbuntuのガベージコレクションcronジョブの実行には25分かかりますが、なぜですか?

Ubuntuには、古いPHPセッションを探して削除するcronジョブがセットアップされています。

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] \
   && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir \
   fuser -s {} 2> /dev/null \; -delete

私の問題は、このプロセスの実行に非常に長い時間がかかり、大量のディスクIOが発生することです。これが私のCPU使用率グラフです。

CPU usage graph

クリーンアップの実行は、ティールスパイクで表されます。期間の初めに、PHPのクリーンアップジョブはデフォルトの09分と39分にスケジュールされました。 15:00に、39分の時間をcronから削除したので、サイズの2倍のクリーンアップジョブが半分の頻度で実行されます(ピークの幅が2倍、頻度が半分になることがわかります)。

IO時間に対応するグラフは次のとおりです。

IO time

そしてディスク操作:

Disk operations

約14,000セッションがアクティブであったピークでは、クリーンアップが25分間実行され、CPUの1つのコアの100%とディスクの100%と思われるものを使用しているようですIO期間全体。なぜリソースを大量に消費するのですか?セッションディレクトリのls/var/lib/php5はほんの一瞬です。では、なぜ古いセッションをトリミングするのに25分もかかるのでしょうか。これをスピードアップするために私にできることはありますか?

このデバイスのファイルシステムは現在ext4であり、Ubuntu Precise 12.04 64ビットで実行されています。

編集:負荷は異常なプロセス「fuser」が原因であると思われます(単純なrmは、私が見ているパフォーマンスよりも高速であると予想されるため)。フューザーの使用を削除して、何が起こるかを確認します。

13
thenickdude

fuserの削除が役立つはずです。 このジョブは、見つかったすべてのセッションファイルに対してfuserコマンドを実行します(ファイルが現在開いているかどうかを確認します 。これは、14kセッションのビジーシステムでは数分かかることがあります。これは Debianのバグでした (UbuntuはDebianに基づいています)。

Memcachedの代わりに、tmpfs(メモリ内のファイルシステム)をセッションファイルに使用することもできます。 memcachedのように、これは再起動時にセッションを無効にします(これは、このディレクトリをシャットダウンスクリプトのどこかにバックアップし、スタートアップスクリプトで復元することで回避できます)が、セットアップははるかに簡単です。しかし、それはfuser問題には役立ちません。

9
Tometzky

人気のWebサイトがあり、仮想マシン上で常に実行し続けることができたことをお祝いします。

1日に200万ページビューを実際に取得している場合、PHPセッションのLOTをLOTに積み上げ、それらに長い時間がかかります。 fuserまたはrmを使用するか、掃除機を使用するかに関係なく、削除してください。

この時点で、セッションを保存する別の方法を検討することをお勧めします。

  • 1つのオプションは memcachedにセッションを保存する です。これは非常に高速ですが、サーバーがクラッシュまたは再起動すると、すべてのセッションが失われ、全員がログアウトされます。
  • セッションをデータベースに保存することもできます。これはmemcachedよりも少し遅くなりますが、データベースは永続的であり、単純なSQLクエリで古いセッションをクリアできます。ただし、これを実装するには、 カスタムセッションハンドラーを記述 する必要があります。
9
Michael Hampton

したがって、ここでユーザーが提案するMemcachedオプションとデータベースセッションストレージオプションはどちらも、パフォーマンスを向上させるための優れた選択肢であり、それぞれに独自の利点と欠点があります。

しかし、パフォーマンステストによって、このセッションメンテナンスの莫大なパフォーマンスコストは、ほぼ完全にcronジョブのfuserの呼び出しにあることがわかりました。これは、古いセッションをトリムするためにrmではなくfuserを使用するNatty/Oneiric cronジョブに戻した後のパフォーマンスグラフです。切り替えは2:30に行われます。

CPU usage

Elapsed IO time

Disk operations

UbuntuのPHP=セッションクリーニングによって引き起こされる定期的なパフォーマンスの低下がほぼ完全に削除されていることがわかります。ディスクオペレーショングラフに表示されるスパイクの大きさがはるかに小さくなり、このグラフと同じくらい細い以前のサーバーパフォーマンスが25分間大幅に低下した小さな短い中断を測定して示すことができます。余分なCPU使用率は完全に排除され、これは現在、IOにバインドされたジョブです。

(無関係なIOジョブは05:00に実行され、CPUジョブは7:40に実行され、どちらもこれらのグラフに独自のスパイクを引き起こします)

現在実行中の変更されたcronジョブは次のとおりです。

09 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && \
   [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 \
   | xargs -n 200 -r -0 rm
4
thenickdude

セッションに関する調査をしているときにこの投稿に出くわしました。受け入れられた答えは非常に良いです(そして、fuserコールはしばらくの間gcスクリプトから削除されています)他の誰かが同様の問題に遭遇した場合、他のいくつかの考慮事項に注意する価値があります。

説明したシナリオでは、OPはext4を使用していました。 ext4のディレクトリは、htreeデータベース形式でファイルデータを格納します。つまり、複数のディレクトリにファイルを分散する場合と比較して、単一のディレクトリに多数のファイルを保持する場合の影響はごくわずかです。これはすべてのファイルシステムに当てはまるわけではありません。 PHP=のデフォルトハンドラーを使用すると、セッションファイルに複数のサブディレクトリを使用できます(ただし、制御プロセスがそれらのディレクトリに再帰していることを確認する必要があります-上記のcronジョブでは確認できません)。

(fuserの呼び出しを削除した後の)操作のコストの多くは、まだ古くなっていないファイルを調べることから発生します。 (たとえば)単一レベルのサブディレクトリを使用し、各サブディレクトリ(0 /、1 //、... d /、e /、f /)を検索する16個のcronジョブを使用すると、発生する負荷の増加をスムーズにすることができます。

より高速なサブストレートでカスタムセッションハンドラーを使用すると効果的ですが、インターネットで公開されているものの品質の範囲は別にして、(memcache、redis、mysqlハンドラーソケット...)から選択できることがたくさんあります。デフォルトのハンドラーと比較してセマンティクス(特にロック)の処理に頻繁に違いがあることを忘れないように、アプリケーション、インフラストラクチャ、およびスキルに関する要件。

1
symcbean

そのようなトラフィックでは、disにセッションを置くべきではありません。 memcacheなどを使用する必要があります。あなたがしなければならないすべてはphpのセットアップであり、コードの変更は必要ありません。例を見る

http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/

非常に時間がかかるのは、削除できるファイルを確認するために並べ替える必要があるファイルの量が膨大なためです。 Memcacheは、コードで設定したセッションの長さを前提として、これらを自動的に期限切れにすることができます。

0
Mike