SQL サーバーがオフラインのときに Web サイトを (丁寧に) 無効にする
-
01-07-2019 - |
質問
私は大学で働いており、学生や出席統計などに関する非常に多くのレポートを含む ASP.NET サイトを開発しています。データの基礎は、学生管理システムのバックエンドである MSSQL サーバー DB です。これには、木曜日の朝に定期メンテナンス期間があり、その期間は不明です (何を行う必要があるかによって異なります)。
ほとんどのスタッフはこのことを認識していますが、定期的に利用しないユーザーはいつまでも私に電話をかけてくるようです。メンテナンス中にサイトを無効にする最も簡単な方法は何ですか? DB クエリを実行してサイトが稼働しているかどうかをテストすることはできますが、たとえばすべてのユーザーを「メンテナンスのため Web サイトが停止しています」というメッセージにリダイレクトする最善の方法がわかりません。ウェブサイトがダウンする前にセッションを開始できたかもしれないことを念頭に置いてください。
うまくいけば、ページごとではなくグローバルに何かを実装できると思います。
解決
エラーが発生した後ではなく、Application_PreRequestHandlerExecute で実行することをお勧めします。一般に、データベースが使用できないことがわかっている場合は、通常の処理を開始しないことをお勧めします。私は通常、以下のようなものを使用します
void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
string sPage = Request.ServerVariables["SCRIPT_NAME"];
if (!sPage.EndsWith("Maintenance.aspx", StringComparison.OrdinalIgnoreCase))
{
//test the database connection
//if it fails then redirect the user to Maintenance.aspx
string connStr = ConfigurationManager.ConnectionString["ConnectionString"].ConnectionString;
SqlConnection conn = new SqlConnection(connStr);
try
{
conn.Open();
}
catch(Exception ex)
{
Session["DBException"] = ex;
Response.Redirect("Maintenance.aspx");
}
finally
{
conn.Close();
}
}
}
他のヒント
「app_offline.htm」という HTML ファイルを仮想ディレクトリのルートにドロップします。そのような単純な。
スコット・ガスリー 件名とフレンドリーなエラーについて。
ログインしているユーザーに「サイトはメンテナンスのため xxx 分後に停止します」というメッセージを表示し、xxx 分後に全員をログアウトするサービスを実行できます。次に、すべてのページがアクセスできる場所にフラグを設定し、すべてのページ (またはテンプレート ページのみ) の上部でそのフラグが設定されているかどうかをテストし、設定されている場合は、メンテナンス ページのためにサイトが停止しているときにリダイレクト ヘッダーを送信します。
サイトがダウンし、誰かがサイトにアクセスしようとするとどうなるでしょうか?ADO.NET は、キャッチして「Web サイトが停止している」ページにリダイレクトできる特定の例外をスローしますか?
「Global.asax」ファイルをプロジェクトに追加し、そのコードビハインドに「Application_Error」イベント ハンドラーを追加できます。Web アプリのどこからでも、例外がスローされてキャッチされないたびに起動されます。たとえば、C# では次のようになります。
protected void Application_Error(object sender, EventArgs e)
{
Exception e = Server.GetLastError().GetBaseException();
if(e is SqlException)
{
Server.ClearError();
Server.Transfer("~/offline.aspx");
}
}
例外の Number プロパティを確認することもできますが、どの数値がデータベース サーバーに接続できなかったことを示すのかはわかりません。ダウン中にこれをテストし、SQL エラー番号を見つけてオンラインで調べて、それが本当にチェックしたいものであるかどうかを確認できます。
編集: あなたの言っていることはわかります、ペテボブ。
ユーザーがすでにサイト内を移動している場合、またはブックマーク/外部リンクから特定のページへのサイトにアクセスしている場合、「offline.html」ページは機能しません。
私が使用する解決策は、同じアドレス (IP またはホスト ヘッダー) を使用して 2 番目の Web サイトを作成し、デフォルトで無効にすることです。Web サイトがダウンすると、スクリプトによって「実際の」Web サイトが非アクティブ化され、代わりに「メンテナンス」Web サイトが有効になります。オンラインに戻ると、別のスクリプトが「実際の」Web サイトに戻ります。
「メンテナンス」Web サイトは別のルート ディレクトリにあり、メッセージ (および必要な画像/CSS ファイル) が含まれる単一ページがあります。
どのページでも同じメッセージを表示するために、「メンテナンス」Web サイトには、すべてのリクエストを同じ「Web サイトはメンテナンスのため停止しています」ページにリダイレクトする 404 エラー ハンドラーが設定されています。
すべてのページでの DB チェックのもう少し洗練されたバージョンは、Global.asax ファイルでチェックを実行するか、他のすべてのページが継承するマスター ページを作成することです。
オンライン サイトとオフライン サイトを設けるという提案は非常に良いものですが、実際に当てはまるのは、サーバー上で管理するサイトの数が限られている場合に限られます。
編集: くそー、ページをロードした後にこれらの提案を含む他の回答が表示されました。返信する前に忘れずに更新する必要があります:)
James コードは接続を閉じるのを忘れます。おそらく次のようになります。
try
{
conn.Open();
}
catch(Exception ex)
{
Session["DBException"] = ex;
Response.Redirect("Maintenance.aspx");
}
finally
{
conn.Close();
}
これまでの返信に感謝します。私はメンテナンスを行っているわけでも、IIS に常にアクセスできるわけでもないことを指摘しておきます。また、他のプログラマーと同じように、私は少し怠け者なので、何もしないオプションを好みます。
すべてのページでフラグをチェックすることが 1 つの方法であることはわかっていますが、それは避けたいと考えています。global.asax ページで何かできないだろうか。実際、投稿することで私の脳は活性化されたと思います。
Application_BeginRequest に SQL 状態をチェックしてリダイレクトするコードを少し追加できると思います。
HttpContext context = HttpContext.Current;
if (!isOnline())
{
context.Response.ClearContent();
context.Response.Write("<script language='javascript'>" +
"top.location='" + Request.ApplicationPath + "/public/Offline.aspx';</scr" + "ipt>");
}
または、私が仕事中でないため、まだテストされていないため、そのようなものは完璧ではない可能性があります。コメントをお待ちしております。