70

私の質問はどんどん長くなっているので、質問全体を書き直して、より良く、より短くすることにしました。

私は自分のウェブサイトを8GBのメモリを備えた専用サーバーで実行しています。php.ini設定のメモリ制限を上げる必要があることを十分に認識しています。128Mから256M、そして-1に設定しました。それでも問題は持続性です。

致命的なエラー:81行目のD:\ www \ Football \ views \ main.phpのメモリ不足(786432が割り当てられています)(24576バイトを割り当てようとしました)

メモリ不足は、786432バイトのみが割り当てられ、さらに24576バイトが必要であると述べているため、意味がありません。

786432バイトはわずか768キロバイトで、かなり小さいです。

ヒント

  • エラーは非常にランダムな行で発生します。行番号81で常にエラーになるとは限りません。
  • ピーク時には、Apacheは約500MBのメモリしか使用しません。まだ6GBの余裕があります。
  • 無限ループはありません。
  • スクリプトは1,042,424バイトかかります。からこの番号を取得するecho memory_get_peak_usage();
  • MySQLからの結果セットは小さいです(最大12行、純粋なテキスト、blobデータなし)
  • 重要)2日に1回Apacheを再起動すると、エラーはなくなります。これは通常、Apacheが2日以上実行されている場合に発生します。
  • スクリプトのプロファイリングを含めました。ここで入手できます。
  • この専用サーバーは、純粋に1つのWebサイトのみを実行するために使用されます。このウェブサイトは、毎分平均1,000人の訪問者がいるトラフィックの多いウェブサイトです。ピーク時には、1,700〜2,000人の訪問者が同時にアクセスします。

サーバー仕様

OS:Windows 2008 R2 64ビット
CPU:Intel Core i5-4コア
RAM:8 GB
Apache 2.2
PHP 5.3.1
ストレージ:2 x 1 TBハードドライブ
帯域幅:1か月あたり10 TB

解決

私はついに問題を調整して修正しました。ここで、改善のために行ったことを共有したいと思います。

  1. favicon.ico私のルートエンジンを台無しにする行方不明でした。私のルートエンジンは非常に小さいですが、を含めるfavicon.icoことで、ルートエンジンを実行しないことで、メモリ使用量を減らすことができます。私のウェブサイトのほとんどはそれを持っていて、私はこの新しいセクションのためにそれを置くのを忘れました。
  2. 制限MaxRequestPerChildが役立ちます。私の他の専用サーバーでは、MaxRequestPerChild制限があります。このサーバーでは、0に設定しました。各スクリプトは分離されていると常に思っていました。スクリプトの実行に800kbかかる場合を考えてみましょう。完了すると、ApacheまたはPHPは800kbのメモリを解放する必要があります。このようには機能しないようです。Limitedは、Limitedの後に新しいプロセスを作成し、古いプロセスが停止MaxRequestPerChildすることで、メモリリークを防ぐのに役立ちます。MaxRequestPerChildこれが私の新しい設定です。

    ThreadsPerChild      1500
    MaxRequestsPerChild  10000 
    
  3. ob_flush();わずかに多くのメモリを削減します。それはあまり役に立ちませんが、最適化のあらゆるビットが役立ちます。

  4. xdebugこの質問に答えようとする人々によって提案されたように、私はこれまで使用したことがないものを使用しました。私はそれが素晴らしいツールであると言わなければなりません、そして私はそれがわずかに速く動くようにいくつかのものを最適化しました。
  5. いくつかの不要なApacheモジュールを無効にしました。私はそれを一つずつ無効にしようとしています、そして私が別のものを無効にする前にそれが完全に機能することを確認するためにそれを数日間テストしておきます。私は今、すべての不要なPHP拡張機能を無効にしています。
  6. このサーバーのほとんどのスクリプトは、従来の方法(テンプレートなし、データベースレイヤーなし、純粋なPHP、HTML、およびレガシーmysql_ *関数)を使用していました。正直なところ、それは非常に高速に実行され、非常に小さなメモリを使用しました。ただし、Webサイトが長くなっているため、スクリプトの保守はそれほど簡単ではありません。私はウェブサイトのいくつかの部分を適切なフレームワーク(私自身の小さなフレームワーク)に変換しようとしました。自分のフレームワークを使用した理由は小さいためです(フレームワーク全体で3kbで、必要なものだけが含まれています)。
  7. この問題を完全に解決するIIS7.5に切り替えます。
4

20 に答える 20

31

スワップを使用しようとすると、サーバーが停止するという同じ種類の問題に遭遇しました。これは、mod_php がメモリを解放しないためです。そのため、Apache プロセスは成長し続け、apache または PHP のメモリ制限に達するか、制限がない場合はサーバーをクラッシュさせます。

apache を再起動すると、新しい新しいスリム プロセスが生成されますが、時間の経過とともに PHP スクリプトを実行すると、問題が発生するまで成長します。

解決策は、特定の数のクエリが提供された後にプロセスを強制終了するようにApacheを作成して、新しいプロセスを作成することです(それに関連する質問がいくつかあります) MaxRequestsPerChild構成オプションを100としましょう(デフォルトは1000)。

もちろん、これにより、新しいプロセスを強制終了して生成するためにリソースが必要になるため、サーバーのパフォーマンスが低下する可能性がありますが、少なくともサイトは機能し続けます. パフォーマンスを高く保つために、実行中のプロセスの数を増やしたくなるかもしれません。PHP (または apache) のメモリ制限 x プロセスの最大数がサーバーの物理 RAM を超えないようにしてください。

これが私の経験です。

于 2012-08-29T12:42:31.577 に答える
15

まず、memory_get_peak_usage()ここでは役に立ちません。割り当てられたメモリの量のみを返します。これは、エラーの原因となったのと同じ数です。

memory_get_usage呼び出されたときに割り当てられているアクティブなメモリ量を返します。

ini_set('memory_limit', '256M');システムのメモリ上での PHP のフットプリントの最大許容量を設定します。768K で OOM を取得している場合、それを上げても問題は解決しません。

どのバージョンの PHP を使用しているかはわかりませんが、すぐにアップグレードすることをお勧めします。Zend のメモリ マネージャがメモリの割り当て解除に失敗するバグがいくつかあり、まったく同じ問題が発生します。

ローカル サーバーと運用サーバーの両方で、同じバージョンの OS、同じロング ビット、同じバージョンの PHP を実行していますか? 答えはノーです。

malloc()それがサブドメインであり、おそらくVirtualHost内にあり、768kしか割り当てられていないため、Windowsの問題とは関係がない場合、ほとんどOSの問題のように聞こえます.

tasklistスクリプトにアクセスするときに、コマンド プロンプトから実行します。追加の Apache スレッド、またはプロセス全体でのメモリ使用量の急増が見られますか?

最後のアイデアは、テーブルの行/列の各ループの後にflush()and/orを実行することです。ob_flush();これにより、バッファがクリアされ、問題が発生している場合に備えてメモリが節約されます。

于 2012-08-28T16:17:29.483 に答える
8

一部のアプリケーションでは最大 50% 高速であるため、PHP を 5.4+ にアップグレードすることから始めます。彼らは多数のメモリリークを修正しました。becnhamrks を参照してください: http://news.php.net/php.internals/57760

于 2012-08-27T08:55:59.530 に答える
7

Out of memoryエラーはであり、ではないことに注意してくださいAllowed memory size [..] exhausted

したがって、メモリリークはシステムの他の場所にあります。mysqlサーバーは、この重いクエリの後に大量のシステムメモリを使用し、apache/phpを物理的およびスワップなしで残す可能性があります。

これは、常に同じ行(および/または同じスクリプト)でエラーを説明する必要があります。

于 2012-08-29T09:34:38.793 に答える
6

xdebug をインストールし、プロファイラー トリガーを有効にします。それでも問題の原因がわからない場合は、プロファイラー ファイルを生成してから、cachegrind ファイルを投稿してください。

編集: もちろん、メモリ リークが発生するページのプロファイラー ファイル!

于 2012-08-27T09:10:35.697 に答える
4

権限を編集していないphp.iniか、PHP や Web サーバーを再起動していない可能性があります。

phpinfo.phpdocroot にコンテンツを含むページを作成して<?php phpinfo();、正しいphp.ini. php.iniWeb サーバーが使用しているファイルの場所に加えて、許容される最大スクリプト メモリも示されます。

次に、スタック トレースをページに追加して、これにつながった一連のイベントを確認できるようにします。次の関数は、致命的なエラーをキャッチし、何が起こったかについての詳細情報を提供します。

register_shutdown_function(function()
{
    if($error = error_get_last())
    {
        // Should actually log this instead of printing out...
        var_dump($error);
        var_dump(debug_backtrace());
    }
});

個人的には、Nginx + PHP-FPM は、低速の Apache から離れてから何年も使用してきたものです。

于 2012-08-29T19:32:01.283 に答える
3

私のサーバーでも同じ問題が発生しました。私はちょうど次のことを変更しました:

に変更php.ini...

memory_limit = 128M

に追加しますhttpd.conf

RLimitMEM 1073741824 2147483648

Apacheを再起動してエラーを削除しました:

于 2012-09-01T06:07:40.257 に答える
3

MySQLと開いている接続の数に問題がある可能性があるため、数日ごとに再起動すると問題が解決するのはなぜですか. それらはスクリプトのシャットダウン時に自動的に閉じますか?

于 2012-08-29T14:07:14.517 に答える
2

要約すると(元の質問からかなり離れた場所にこの回答を追加しています):

  • PHP が少量と思われるメモリを割り当てることができない
  • エラーが発生した時点での現在のメモリ使用量 + 要求された量が現在有効なメモリ制限より少ない
  • これが発生した場合、システムには PHP が使用できる 6Gb があります。
  • 問題はApacheを再起動することで解決されるため、PHPがメモリを使用できないようにしているのはApacheです

これらがすべて有効である場合、考えられる唯一の説明は、6Gb が非常に断片化されているということです。これは少しありそうにないと思います。PHP が Apache からどのように呼び出されるかについては言いませんでした - mod_php ですか? fpm? FCGI?

上記の各述語、特に空きメモリの述語を調べることから始めます。エラーが発生したときに6Gb の空き容量があることをどのように確認できますか? より可能性の高い原因は、気付いていないメモリ リークが発生していることです。

Apache の構成方法の詳細を提供していません。また、MaxRequestsPerChild と MaxMemFree を減らすことも検討したいと思います。(これがスレッドごとに適用されるワーカーApacheにはあまり詳しくありません-実際にはプロセスごとに制限が必要です)。Apache 構成からコア設定を提供した場合は、さらに提案を行うことができます。

Ajax を頻繁に使用している場合を除き、キープアライブ時間が 2 以下であることを確認してください。

于 2012-08-31T12:57:31.923 に答える
1

これは数日前に私に起こりました。新規インストールを行いましたが、それでも発生しました。誰もが見る限り、サーバーの仕様に基づいています。ほとんどの場合、それは無限ループです。PHPコード自体ではなく、Apacheへのリクエストにある可能性があります。

この URL http://localhost/mysite/page_with_multiple_requestsにアクセスしたとしましょう

複数のリクエストを受信する場合は、Apache のアクセス ログを確認してください。その要求を追跡し、システムに「ボトルネック」を引き起こす可能性のあるコードを調べます (sendmail を使用する場合の私の exec())。私が話しているボトルネックは、「無限ループ」である必要はありません。完了するまでに時間がかかる機能である可能性があります。または、php の「プログラム実行関数」の一部かもしれません。

ajax リクエスト (ページの読み込み時に実行されるリクエスト) も確認する必要がある場合があります。その ajax リクエストが同じ URL にリダイレクトされる場合

例: httpx://localhost/mysite/page_with_multiple_requests

リクエストをもう一度「やり直す」

スクリプトが終了する場所にランダムな行またはコード自体を投稿すると、「ループ」コードがどこかにある可能性があります。私見phpは、ランダムな行を無料で呼び出すだけではありません。

http://blog.piratelufi.com/2012/08/browser-sending-multiple-requests-at-once/

于 2012-08-30T07:34:46.153 に答える
1

次の 2 つの事実は、間違いなくメモリ リークを示しています。

  1. エラーはコードの別の行に表示されます。
  2. このエラーは、比較的小さなメモリ割り当てを報告しています。

最初に PDO を選択し、他のすべての拡張機能を無効にして、Siege / Apache Bench (ab) などを使用して一晩実行します。インターフェイスを使用して実行することもできcliます (同じメモリ制限を維持していることを確認してください)。

スクリプトの最後で関数を使用して、memory_get_peak_usage()PHP が使用していると考えているメモリ量を確認できます。

あなたのコメントから、それは 800 kB です。これで問題ありません。間違いなく、メモリ不足を引き起こす膨大な量のメモリではありません;-)

最後に、現時点で 5.4 にアップグレードすることはお勧めしませんが、5.3.1 以降に対処された複数の脆弱性とリークがあるため、最新の 5.3.x にアップグレードすることはおそらく価値があります。

于 2012-08-27T09:17:37.287 に答える
1

これは、Windows 用の PHP v 5.2 の既知のバグです。少なくともバージョン 5.2.3 には存在します: https://bugs.php.net/bug.php?id=41615

提案された修正はどれも役に立ちませんでした。PHP を更新する必要があります。

于 2013-09-26T08:51:41.760 に答える
1

PHPでも同様の問題がありました:

1) エラー ログを確認します。続行する前に、すべてのエラーを排除してください。2) Apache の構成を変更して、未使用のモジュールを削除することを検討してください。これにより、PHP に必要なフットプリントが削減されます。これについては、ここにすばらしいリンクがあります。これは Wordpress に固有のものですが、それでも非常に役立つはずですhttp://themefoundry.com/blog/optimize- Apache-ワードプレス/

私が見つけたバグの種類について説明すると、Facebook にコンテンツを投稿しようとするコードがいくつかありました。Facebook は API を変更したため、これが壊れました。また、基本的に再試行し続けることを意味する「コンテンツ エクスピレーター」も使用しました。このコンテンツを Facebook に投稿し、大量のオブジェクトをメモリに残します。

于 2012-09-01T13:56:28.820 に答える
1

ほとんどの場合、このようなエラーが発生します。問題はコードにあります。私は、あなたが悪いコードを書いていると言っているのではありません。この量のメモリを使用しているものを注意深く観察する必要があると言いたいのです。

「 PHPのガベージコレクションはかなり悪い」ことを常に覚えておいてください.Javaなどの他の言語とは異なります. gc_collect_cycleを使用してガベージ コレクションを強制する方法がありますが、私の個人的な意見では、それでは問題は解決しません。要求と応答のサイクルが完了すると、PHP はページの実行に使用されたすべてのメモリを解放するため、バックグラウンド スクリプト (Gearman など) のようにスクリプトが長時間実行されている場合、メモリの問題が発生する可能性があります。スクリプトが実行されています。

上記があなたのscr、ptに当てはまらず、あなたが言ったように、そのような大量のメモリを必要とするコードはないとしたら、問題は間違いなくコード自体にあり、PHPのどのバージョンにアップグレードしても解決しません問題。Gearman スクリプトの 1 つに直面したことがありますが、1 つの変数を配列の 1 つに追加するループの 1 つに問題がありました。変数自体が非常に重かった (約 110KB のデータ)。したがって、コードを注意深く検査することをお勧めします。

ラビッシュ

于 2012-09-01T11:02:54.827 に答える
1

fcgid を介して php を実行してみてください。これが役立つ場合があります。

これらは、PHP を Apache モジュールとして実行するときに表示される典型的なエラーです。これらのエラーに何ヶ月も悩まされました。mod_fcgid を使用して PHP を使用するように切り替えると (James が推奨するように)、これらの問題はすべて解決されます。最新の Visual C++ 再頒布可能パッケージがインストールされていることを確認してください。

http://support.microsoft.com/kb/2019667

また、64 ビット バージョンの MySQL に切り替えることをお勧めします。32 ビット バージョンを実行する本当の理由はもうありません。

出典: php5ts.dll 5.5.1.0 の問題による Apache 2.4.6.0 クラッシュ

于 2015-03-19T10:23:12.253 に答える
1

プロファイラーの出力ファイルから、私があまり好きではない/信頼していないいくつかのことに気付き、これらを調べました。

異常を検出するための出力数値の意味やPHPスクリプトの仕組みがわからないことは別として…、これは問題ではありませんか?再帰的なもののように見える同じ main.ph ファイルへのインクルードがありますか?

2121 fl=D:\www\football\views\main.php
2122 fn=include::D:\www\football\views\main.php

ファイルがいくつかの文字列関数を数回使用していることに気づきましD:\www\football\views\main.phpた。クエリによって返されたデータに対してこれらの関数を呼び出していると思います。

strlen
substr
strtotime

C 言語のように、これらの関数で文字列をnull終了する必要がある場合、またはメモリの問題を回避するために別の文字列ターミネータが必要な場合は、クエリによって返される文字列を調べます。

あなたのウェブサイトのURLを投稿できますか?

于 2012-09-01T14:09:28.313 に答える
0

私はそれが古いスレッドであることを知っていますが、これが解決された私の経験です。

私のサーバーは、Apache を実行するホストされたサービスです。

私の制限が 256Mb だったとき、私のスクリプトは 6Mb のメモリ不足でクラッシュしました。

クライアントで実行されているJavaScriptからhttpコールバックを介して同期的に呼び出され、約550回の呼び出し後にクラッシュしました。無能な「エスカレートされたサポート」担当者に多くの時間を浪費した後、私のスクリプトは魔法のように実行されるようになりました。

彼らはphp.iniをリセットするだけだと言いましたが、違いを確認しました: ここに画像の説明を入力

メモリ不足エラーに関係する可能性のある変更はありません。

「エスカレートされたサポート」担当者が php.ini のリセットを装って隠している Web サーバーのメモリ リークが疑われます。そして、実際には、私は陰謀論者ではありません。

于 2020-09-23T00:45:58.477 に答える
0

サーバーの物理/スワップ メモリが不足しているため、PHP が十分なメモリを割り当てることができません。

ここの出力を貼り付けてもらえますfreeか?

于 2012-08-27T21:54:25.143 に答える