35

トラフィックがほとんどない私のウェブサイトをホストしているサーバーがあります。
毎日数人(<20)がサイトにアクセスし、数人のRSSリーダーが私たちが出すいくつかのフィードを購読しています。

ほぼ毎晩、RSSリーダーが深夜に私たちを襲い、接続のタイムアウトのためにWebサイトがSQLServerに接続できないという例外が発生します。詳細は非常に奇妙なので、どこから始めればよいのかわからないので、何が問題になるのかについて助けを求めています。

Windows Server2008ではなくASP.NetMVC、Entity Framework、およびSQL Server 2008を使用しています。このマシンは、厳密には一流ではないプロバイダーから入手した専用のボックスであるため、最適に構成されていない可能性があります。そうしないと。
ボックスもかなり小さく、RAMは1Gbしかありませんが、今のところある種の負荷がかかるはずです...

以下の完全な呼び出しスタックをコピーしていますが、最初に、私たちが知っていることのいくつか:

  • iTunesが私たちのサイトにクエリを実行しているときは常にエラーが発生します。これは何の関係もないはずだと思いますが、本当はiTunesからしか入手できません。私の推測では、これは、他の誰も私たちを攻撃していない夜のその時間にiTunesだけが私たちに問い合わせをするために起こると思います。
  • 私たちの理論の1つは、SQL ServerとIISがメモリをめぐって争っていて、そのうちの1つが使用されていない状態でディスクにページングされており、誰かが「ウェイクアップ」すると、ディスクからすべてを読み取るのに時間がかかりすぎるというものです。メモリに。これは潜在的に起こり得ることですか?(可能であれば、SQL Serverの設計上の問題のように思われるので、これを破棄します)
  • また、EFエンティティを適切に処理していない可能性があるため、接続がリークしている可能性についても考えました(ここでの私の質問を参照してください)。これは私が問題をグーグルで検索することによって見つけることができた唯一のものです。負荷が非常に低いため、これを破棄します。
  • これは常に一晩で発生するため、しばらくの間何も起こらなかったという事実に関連している可能性が非常に高いです。たとえば、これらのリクエストがヒットすると、Webサーバープロセスがリサイクルされ、すべてが起動/再JITされると確信しています。ただし、再JITはSQLタイムアウトを説明しません。

更新:提案どおりにプロファイラーをアタッチしましたが、新しい例外が発生するまでにかなりの時間がかかりました。これは私たちが知っている新しいものです:

  • プロファイラーをアタッチすることで、発生するエラーの数を大幅に減らすことができました実際、通常は1日に数回摂取した後、これが1回発生するまで3〜4日待たなければなりませんでした。プロファイラーを停止すると、通常のエラー頻度(またはさらに悪い頻度)に戻りました。したがって、プロファイラーには、この問題をある程度隠す効果がありますが、完全ではありません。
  • IIS要求ログの横にあるプロファイラートレースを見ると、要求とクエリの間に1対1の対応が予想されます。ただし、IISログとの相関関係がまったくないクエリが実行されているのを時々目にします。実際、実際のバグがログに記録される直前に、3分間で750のクエリが発生しましたが、これらはすべてIISログとはまったく関係がありませんでした。クエリテキストは、EFが生成する読み取り不可能ながらくたのようなもののように見えますが、すべて同じではなく、Webサイトからのクエリ(同じApplicationName、Userなど)のように見えます。これがいかにばかげているかを知るためにつまり、このサイトは2日間で約370のIISリクエストを受け取り、DBにヒットしました。
  • これらの説明のつかないクエリは、以前のWebサイトのクエリと同じClientProcessIDからのものではありませんでしたが、その間にプロセスがリサイクルされた場合は、まだWebサイトからのものである可能性があります。最後に説明されたクエリと最初の説明されていないクエリの間に、ほぼ1時間のアクティビティがありませんでした。
  • どこから来たのかわからないこれらの長い一連のクエリの1つは、ログに記録されたエラーの直前に発生したため、これが私たちが従うべき手がかりだと思います。
  • 当初予想したように、エラーをスローしたクエリが実行されたとき、それは前のクエリとは異なるClientProcessIDからのものでした(前の原因不明のクエリより8分遅れ、前のIISのものよりほぼ正確に1時間遅れています)。これは、私にとって、労働者のプロセスが実際にリサイクルされたことを意味します。
  • これは私が絶対に理解していないことです。IISログには、エラー要求の1分前に、4つが完全に処理されたことが示されていますが、それらのクエリはトレースにまったく表示されません。実際、これらの4つがうまくいった後、4つの例外がすばやく連続してスローされ、それらの4つもトレースに表示されません(接続にタイムアウトがあった場合、クエリは実行されないはずなので、これは理にかなっています。しかし、トレースに接続の試行も表示されません)

だから、要するに、私はこれについて完全に無知です。何百ものクエリが連続して実行される理由はわかりませんが、それらは問題と関係があるに違いないと思います。
また、接続の問題を診断する方法もわかりません...
または、IISによると正常に処理されたクエリがプロファイラートレースで欠落している可能性があります...

何か案は?


これは例外情報です:

System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

System.Data.EntityException: The underlying provider failed on Open. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   --- End of inner exception stack trace ---
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.Open()
   at System.Data.Objects.ObjectContext.EnsureConnection()
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
   at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at MyProject.Controllers.SitesController.Feed(Int32 id) in C:\...\Controller.cs:line 38
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

どんなアイデアでも大歓迎です。

4

4 に答える 4

56

メモリーが充分ではありません

これはメモリの問題である可能性が非常に高く、おそらく他の要因によって悪化または引き起こされますが、それでも本質的にメモリの問題です。他に 2 つの (可能性は低い) 可能性があり、最初にチェックして排除する必要があります (そうするのは簡単なので):

簡単に確認できる可能性:

  1. 「自動クローズ」が有効になっている可能性があります。自動クローズはまさにこの動作を行うことができますが、オンになることはめったにありません。これを確認するには、SSMS でアプリケーション データベースを右クリックし、[プロパティ] を選択してから、[オプション] ペインを選択します。「Auto Close」エントリを見て、False に設定されていることを確認します。tempdb も確認してください。

  2. SQL エージェント ジョブが原因である可能性があります。エージェントの履歴ログをチェックして、イベント中に一貫して実行されているジョブがあるかどうかを確認します。インデックスの再構築などは、実行中のパフォーマンスの問題として頻繁に挙げられるため、メンテナンス ジョブも忘れずに確認してください。これらは、通常は Profiler の影響を受けないという理由だけで、今のところ候補にはなりません。

メモリの問題のように見える理由:

これらに何も表示されない場合は、メモリの問題を確認する必要があります。あなたの場合、メモリが原因であると思われます。

  • 1 GB のメモリがあります: これは技術的には SQL Server の最小値を上回っていますが、SQL Server の推奨値をはるかに下回っており、私の経験では、負荷の軽いサーバーであっても運用環境で許容できる値をはるかに下回っています。

  • IIS と SQL Server を同じボックスで実行している: これは、主にメモリの競合が発生するため、単独では推奨されませんが、メモリが 1 GB しかないため、IIS、アプリ、SQL Server、 OS およびその他のタスクおよび/またはメンテナンスはすべて、ごくわずかなメモリを求めて戦っています。Windows がこれを管理する方法は、非アクティブなプロセスからメモリを積極的に奪うことによって、アクティブなプロセスにメモリを与えることです。SQL Server のような大規模なプロセスが、この状況で要求を完全に処理できるように十分なメモリを取り戻すには、数秒または数分かかる場合があります。

  • プロファイラーは問題の 90% を解決しました: これは、メモリが問題である可能性が高いという大きな手がかりです。通常、プロファイラーのようなものは、この特定の問題に対してまさにこの効果があるためです: プロファイラー タスクは、SQL Server を少しアクティブに保ちます。当時の。多くの場合、これは OS の「スカベンジャー」リストから除外するか、少なくとも影響を軽減するのに十分なアクティビティです。

犯人としてメモリをチェックする方法:

  1. プロファイラーをオフにする: 問題にハイゼンベルグ効果があるため、オフにする必要があります。そうしないと、問題を確実に確認できなくなります。

  2. 別のボックスからシステム モニター (perfmon.exe) を実行し、SQL Server と IIS が実行されているボックスのパフォーマンス コレクション サービスにリモート接続します。これを最も簡単に行うには、最初に 3 つの既定の統計情報 (ローカルのみ) を削除してから、必要な統計情報 (以下) を追加します。ただし、最初のドロップダウンでコンピューター名を変更して SQL に接続するようにしてください。箱。

  3. perfmon で「カウンター ログ」を作成して、収集したデータをファイルに送信します。これに慣れていない場合、おそらく最も簡単な方法は、Excel で開いて分析できるタブまたはカンマ区切りのファイルにデータを収集することです。

  4. ファイルに収集するように perfmon をセットアップし、次のカウンターをファイルに追加します。

    -- Processor\%Processor Time[Total]

    -- PhysicalDisk\% Idle Time[各ディスクの]

    -- PhysicalDisk\Avg. ディスクキューの長さ[各ディスクの]

    -- メモリ\ページ/秒

    -- メモリ\ページ読み取り/秒

    -- メモリ\利用可能なメガバイト

    -- Network Interface\Bytes Total/sec[使用中の各インターフェイスについて]

    -- Process\% Processor Time[下記参照]

    -- Process\Page Faults/sec[下記参照]

    -- プロセス\ワーキング セット [下記参照]

  5. プロセス カウンター (上記) には、sqlserver.exe プロセス、IIS プロセス、および安定したアプリケーション プロセスを含める必要があります。これは「安定した」プロセスでのみ機能することに注意してください。必要に応じて継続的に再作成されるプロセスは、存在する前に特定する方法がないため、この方法ではキャプチャできません。

  6. 問題が最も頻繁に発生する時間帯に、このコレクションをファイルに実行します。収集間隔を 10 ~ 15 秒に近い値に設定します。(これにより多くのデータが収集されますが、個別のイベントを選択するにはこの解像度が必要になります)。

  7. 1 つ以上のインシデントが発生したら、収集を停止し、収集したデータ ファイルを Excel で開きます。おそらく、タイムスタンプ列を再フォーマットして便利に表示し、時間、分、秒を表示する必要があります。IIS ログを使用してインシデントの正確な時間を見つけ、perfmon データを調べてインシデントの前後に何が起こっていたかを確認します。特に、以前はワーキング セットが小さく、その後は大きく、その間に多くのページ フォールトが発生したかどうかを確認する必要があります。これは、この問題の最も明確な兆候です。

解決策:

IIS と SQL Server を 2 つの異なるボックスに分けるか (推奨)、ボックスにメモリを追加します。最低でも 3 ~ 4 GB は必要だと思います。

その奇妙な EF のことはどうですか?

ここでの問題は、それが周辺的なものであるか、主な問題の唯一の原因である可能性が高いということです。Profiler によってインシデントの 90% が解消されたため、残っているものはの問題であるか、問題を最も深刻に悪化させている可能性があることに注意してください。その動作から、キャッシュを循環させているか、アプリケーション サーバー プロセスのバックグラウンド メンテナンスが行われていると推測できます。

于 2009-09-29T16:21:28.653 に答える
1

タイムアウトのタイムスタンプを夜間バックアップの実行時間と比較します。それらが一致する場合は、RSSフィードをその間静的に設定できます。

試してみるもう1つのことは(正確には答えではありませんが)、タイムアウト例外が発生したときにすぐにsp_whoを実行することです。すべてをキャッチするわけではありませんが(これを実行するまでに問題のプロセスが実行される可能性があります)、幸運になる可能性があります。

また、夜に家に帰ったときにSQL Profilerを起動し、エラーが再度表示された場合は、翌朝アクティビティをステップスルーすることもできます。サーバー自体から実行しないように注意してください(起動時にこれを思い出させると確信しています)。

編集: あなたの更新に対処します。

EFはキャッシュを更新/作成していますか?一度に大量のクエリが発生したことと、後でデータベースにヒットしたクエリがなかった理由を説明できます。

それ以外は、特異なバグがあるようです。私があなたに追加できると思う唯一のことは、(ファイルまたはイベントログへの)より多くのログ記録です。

于 2009-09-14T14:43:43.930 に答える
0

同時に走るクロンの匂いがします。RBarryYoungが言うように、夜間のバックアップか、それとも他の何かである可能性があります。サーバーへのルートアクセス権がありますか?crontabが表示されますか?

問題が発生している時間の近くに再インデックス手順を実行するのは、SQLサーバー上にあるフルテキストインデックスプラグインでしょうか?

于 2009-09-29T15:21:03.110 に答える