私の仕事では、C# 2003 で記述された 6 つの Windows サービスを担当しています。これらの各サービスには、約 1 分ごとに起動するタイマーが含まれており、ここで作業の大部分が行われます。
私の問題は、これらのサービスが実行されると、実行する意味のある作業がなくても (つまり、単にアイドリングしてデータベースを調べているだけである場合でも)、ループの反復ごとに CPU 時間を消費し始めることです。何かをするために)。起動時に、各サービスは 4 つの CPU の平均 (約) 2 ~ 3% を使用しますが、これは問題ありません。24 時間後、各サービスはループの実行中にプロセッサ全体を消費します。
誰でも助けることができますか?何が原因なのか途方に暮れています。私たちの現在の解決策は、サービスを 1 日 1 回再起動することです (サービスは自動的にシャットダウンし、スクリプトはサービスがオフラインであることを認識し、午前 3 時頃に再起動します)。しかし、これは長期的な解決策ではありません。私の懸念は、サービスが忙しくなるにつれて、1 日に 1 回再起動するだけでは十分ではないかもしれないということです...しかし、サービスが忙しくなるにつれて、かなりの起動ペナルティがあるため (それらはすべてデータ アクセスに NHibernate を使用します)、まさに私たちがしていないことです。やりたいことは、より頻繁に再起動することです。
@akmad: 確かに、それは非常に難しいです。
- はい、分離して実行されているサービスは、時間の経過とともに同じ症状を示します。
- いいえ、そうではありません。私たちはそれを見てきました。これは、午前 10 時または午後 6 時、または真夜中に発生する可能性があります。一貫性がない。
- 私たちはそうします。そして彼らは。サービスは本来あるべきことを正確に行っており、それ以外には何もしていません。
- 残念ながら、それには、サービスが CPU を使い果たす正確な時期を事前に把握しておく必要があります。これは、予測不可能なスケジュールで発生し、すぐに発生することはありません... これにより、状況が二重に難しくなります。デバッグの問題を考えずに問題を解決します。
- いいえ、かなり一貫した量の RAM を使用しています (マシンの 4GB のうち、それぞれ約 60 ~ 80MB)。
良い提案ですが、ご安心ください。通常のトラブルシューティングをすべて試しました。私が望んでいるのは、これが誰かが知っているかもしれない .NET の問題であり、私たちが解決に取り組むことができるということです。私の上司の解決策 (これは絶対に実装したくありません) は、日中にサービスを再起動するために複数回保持するフィールドをデータベースに配置することです。 . 私は必死に本当の問題の原因を探しています。なぜなら、その解決策は約 6 か月で大惨事になるからです。
@Yaakov Ellis: それぞれ異なる機能を持っています。1 つは、オフサイトのどこかにある Oracle データベースからレコードを読み取ります。別のものはそれらの記録を処理し、それらの記録に属するファイルを私たちのシステムに転送します。3 つ目は、これらのファイルをチェックして、期待どおりであることを確認します。もう 1 つは、ディスク容量 (十分な容量があること) などを常にチェックし、他のサーバーが稼働していることを確認するためにポーリングする保守サービスです。1 つは、これらの他のすべてが実行され、ジョブを実行していることを確認するためだけに実行され、エラーを監視および報告し、システム全体を 24 時間稼働させ続けるために失敗したものはすべて再起動します。
したがって、あなたが何を求めていると思うかを尋ねているのであれば、いいえ、これらすべてのサービスが行う共通のこと (NHibernate を介したデータベース アクセスを除く) は、潜在的な問題として指摘できるものではありません。残念ながら、それが実際の問題であることが判明した場合 (それほど驚くことではありません)、全体が台無しになる可能性があります。最終的には、単純な SQL ですべてを書き直すことになります。ガベージ コレクターの問題か、NHibernate よりも扱いやすいものであることを願っています。
@ジョシュダン:秘密はありません。私が言ったように、私たちはすべての通常のトラブルシューティングを試みました. プロファイリングは役に立ちませんでした。使用しているプロファイラーは、CPU 使用率が高いときに実際に実行されていたコードを指すことができませんでした。これらのサービスは、この問題を探して約 1 か月前にバラバラになりました。コードのすべてのセクションを分析して、コードに問題があるかどうかを突き止めました。私は宿題をしていないので、ここで尋ねているわけではありません。これが、サービスが予想よりも多くの作業を行っているという単純なケースであれば、それは捕らえられていたでしょう.
ここでの問題は、ほとんどの場合、サービスがまったく何もしていないにもかかわらず、4 つの CPU コアの 25% 以上を消費していることです。実行する作業が見つからず、ループを終了して待機しています。次の繰り返し。これは文字通り、CPU 時間をほとんど消費しないはずです。
これは、2 日間 (変化のない環境で) 行う作業がないサービスで、私たちが目にしている動作の例です。これは先週キャプチャされました:
1 日目、午前 8 時: 平均 CPU 使用率は約 3%
1 日目、午後 6 時: 平均。CPU 使用率は約 8%
2 日目、午前 7 時: 平均 CPU 使用率は約 20%
2 日目、午前 11 時: 平均。CPU使用率約30%
これについて考えられるありふれた理由をすべて検討した結果、ここでこの質問をしたのは、(当然のことながら、結果的には) もっと革新的な答え (Ubiguchi のようなもの)、または私が持っていなかったものへのポインタが得られるだろうと考えたからです。 tは考えました (Ian の提案のように)。
では、CPU スパイクは、タイマー コールバックの直前、タイマー コールバック内、またはタイマー コールバックの直後に発生しますか?
勘違いしている。これはスパイクではありません。もしそうなら、問題はありません。私はスパイクを扱うことができます。しかし、そうではありません... CPU使用率は一般的に上昇しています。サービスが何もしていないときでも、次のタイマー ヒットを待ちます。サービスが起動すると、物事は素晴らしく穏やかで、グラフは期待どおりに見えます...通常、使用率は0%で、NHibernateがデータベースにヒットするか、サービスが些細な量の作業を行うと、10%に急増します. しかし、これは、プロセスの実行中は常に全体で 25% (やりすぎるとそれ以上) の使用量に増加します。
これにより、Ian の提案が論理的な特効薬になりました (NHibernate は、ユーザーが見ていないときに多くのことを実行します)。悲しいかな、私は彼のソリューションを実装しましたが、効果はありませんでした (これを証明するものはありませんが、実際には事態が悪化したと思います...平均的な使用法でははるかに速く上がるようになりました)。NHibernate の「セクション」を削除することは (推奨されるように) 実行できないことに注意してください。これは、サービス内のコードの約 90% を削除することになり、タイマーを問題として除外できるようになるためです (私は絶対にそうするつもりです)。試してみてください)、しかし、問題として NHibernate を除外することはできません。NHibernate がこれを引き起こしている場合、実装されている危険な修正 (以下を参照) は、The Way The System Works になる必要があるためです。私たちはこのプロジェクトで NHibernate に大きく依存しているため、PM はそれが解決できない構造上の問題を引き起こしていることを受け入れません。
質問に絶望感を感じました - 小さな奇跡がなければ、あなたの問題は続くでしょう
そのように外れることを意味しないでください。現時点では、サービスは毎日再起動されています (1 日の任意の時間数を入力してシャットダウンして再起動するオプションがあります)。これにより問題にパッチが適用されますが、運用マシンに移行すると長期的な解決策にはなりません。そして忙しくなり始めます。私が修正するか、PM がこの制約を維持するかにかかわらず、問題は継続しません。明らかに、私は実際の修正を実装したいと考えていますが、最初のテストではその理由が明らかにならず、サービスはすでに広範囲にレビューされているため、PM は修正に時間を費やすよりもむしろ複数回再起動することを望んでいます。 . それは完全に私の手に負えないことであり、あなたが話していた奇跡を、それ以外の場合よりも重要なものにしています.
これは非常に興味深いものです (プロファイラーを信頼している限り)。
私はしません。しかし、これらは Windows 2000 マシン上で実行される .NET 1.1 で記述された Windows サービスであり、危険な Nant スクリプトによってデプロイされ、データベース アクセスに古いバージョンの NHibernate を使用します。そのマシンには、私が実際に信頼していると言えるものはほとんどありません。