今回の記事では、SQL Server データアクセスを行うアプリケーションについて、その実体の配置場所によって処理の遅延が発生し、接続処理がタイムアウトしたという事例について紹介いたします。もし、身近に同様の事例や、経験をお持ちの方は、以下の内容がご参考になれば幸いです。
事例 : 「ファイル共有に配置したADO から ADO.NET アプリケーションに移行したら遅くなった」
ADO 経由で SQL Server に接続しデータアクセスを実行するアプリケーション(*.exe)を共有フォルダ上に配置し、クライアントには共有フォルダ上のアプリケーションのショートカットをダブルクリックしてアプリケーションを実行していたシステムを、.NET Framework で再構成し、ADO.NET 経由で SQL Server に接続するようにマイグレーションしたところ、SQL Server への接続が高確率でタイムアウトするようになった。
接続文字列で、"Connection Timeout" プロパティを 120 秒程に延長してみたが、状況は改善しなかった。処理の序盤ではタイムアウトせず、だんだんタイムアウトしていく確率が上がっていくような動きになっている。そこでアプリケーションをクライアント ローカルもしくは SQL Server と同じ環境に配置したところ、タイムアウトは一切発生しないことがわかった。 検証結果から、アプリケーションの配置場所がローカルか、リモートかという違いのみ、動作に影響しているようであるが、以前の ADO 経由のアプリケーションでは問題が発生しなかった。
発生例) Visual Basic 6.0 アプリケーションから Visual Basic (.NET Framework ベース) に移行した場合など
この事例での対処
この問題は障害ではなく、以下の二つの要因により接続処理のすべてのフェーズが接続タイムアウト期間中に完遂していない可能性が高いという判断に至りました。このため、この件ではアプリケーションの配置を各ローカルに変更することにより、問題を解消することができました。
1. 非同期で読み込まれていくアプリケーション実行関連のファイル(DLL、EXE、ini、config ファイルなど)のネットワーク伝送およびネットワーク伝送処理における IO のオーバーヘッド
2. .NET Framework に搭載されたコード アクセス セキュリティの監査の影響
もし、本記事をご覧いただいている方が同じ同様の構成で同様の状況が発生しているのであれば、アプリケーションの配置をローカルにしていただき、状況が改善するか確認してみてください。ローカル配置で状況が改善するのであれば、アプリケーションの配置場所や、配布方法の見直しをしていただくことをお勧めします。
図 : クライアント コンピュータからサーバーの共有フォルダに配置した実行ファイル (exe) を実行し、さらに SQL Server に接続を行うパターン
SQL Server へのセッションは三つのフェーズをすべて時間内に成功して初めて確立される上、各フェーズ毎に実際には何回もパケットがやり取りされている。
その為、プロセスの SQL Server への接続以外の処理が入ると、プロセスの全体的な動作が遅延しタイムアウトしてしまうことなどがある。 ファイルロード処理はプログラムのメインの処理と非同期に行われることもあるが、IO の状況などによってはメインの処理(たとえば、SQL Server への接続など)が待たされるということも有り得る。
図 : クライアント コンピュータローカルに配置した実行ファイル (exe) から SQL Server に接続を行うパターン
プログラムに実行するためのファイルはローカルの HDD からロードされる。従って、ネットワーク経由での起動と異なりネットワーク伝送のオーバーヘッドも、コードアクセスセキュリティの制限対象外になるため、検証のオーバーヘッドもない。
どのような調査をしたか
クライアント - SQL Server 間でネットワーク トレースを採取したところ、以下の状況が把握できました。
このため上記の見解となりました。
・多数のプログラム関連のファイル読み込みの処理が実施されている合間で SQL Server へのネットワーク伝送処理が行われている
・SQL Server へのセッション確立関連のパケット送出がプログラム上での SqlConnection.Open() から数十秒経過してから開始されている
・.NET Framework のセキュリティの仕組み上、リモートに配置されたアセンブリはローカルに配置されたアセンブリと異なり、完全に信頼されるものとはみなされず、また、アセンブリが配置されている場所に応じたアクセス制限を設定することが可能となっている。この仕組みのため、リモートに配置されアプリケーションの実行は、ローカルに配置されたアプリケーションに比べて実行時のオーバーヘッドが存在する
Visual Basic 6.0 と .NET Framework の違いについて
Visual Basic 6.0 設計時よりも、セキュリティについての重要性が格段に増している現代において設計された .NET Framework ベースのアプリケーションの設計思想のうち最も重要なコンセプトのひとつがセキュリティです。
.NET Framework では、Code Access Security (CAS) と呼ばれるセキュリティの仕組みが導入されており、実行しようとしているプログラムが、どこに配置されているものか、デジタル署名がなされているかなどといった情報をもとに、信頼された安全なプログラムであるか検証することが可能です。アプリケーションが実際に実行するマシンからみてどこに配置されているものかという情報については、ローカル マシン上、イントラネット上の共有フォルダー、インターネット上といった区別に応じて、プログラムが実行できる処理内容を細かく制限できるような機能が提供されるようになりました。これにより、例えば、フィッシング等により、ユーザーが意図せずインターネット上の危険なプログラムを実行した場合でも、システム フォルダーへの書き込みや、レジストリの変更などは行えないように保護する、といった設定が可能となっています。
図 : ローカル外の環境から実行するファイルの安全性は必ず保障できるわけではない
.NET Framework では、対象のプログラムの配置場所にも応じたセキュリティの機能を提供している関係で、セキュリティ機能を持たない Visual Basic 6.0 アプリケーションと比較して安全である反面、各種検証処理のためにパフォーマンス的には不利な面が出てくることになります。このため、環境のリソース使用状況や、性能などによって必ずしも発生するとは限りませんものの、出来る限りパフォーマンスを重視するシステムや、今回のようにタイムアウト期間中に一連の処理を完了しなくてはいけないような処理を実装する場合においては、このような機構的な問題があり得るため、共有フォルダに .NET アプリケーションを配置して運用することは推奨できません。
.NET Framework の CAS の機能の詳細につきましては、以下のドキュメントをご参照ください。
.NET Framework 2.0 でのコード アクセス セキュリティの新機能の探索
http://msdn.microsoft.com/ja-jp/magazine/ee177036.aspx
なお、上記ドキュメントのとおり、.NET Framework 2.0 の CAS の構成は非常に複雑であり、導入・運用上の負担が大きいものでした。このため、.NET Framework 4 では本機能が大幅に変更・簡略化されております。ただし、セキュリティ関連のチェック処理を搭載していなかった Visual Basic 6.0 のレベルまで簡略化されていることを意味するものではございません。
.NET Framework 4 におけるセキュリティの変更に関しましては、以下のドキュメントをご参照ください。
.NET Framework 4 におけるセキュリティの変更点
http://msdn.microsoft.com/ja-jp/library/dd233103(v=vs.100).aspx
一般的にリモート アクセスにおいてパフォーマンスを両立させたい場合のソリューション
デスクトップ アプリケーションを各端末にインストールする運用では、アプリケーションのバージョンアップや修正が必要となった際のコストが高くなりがちです。一方、Web アプリケーションの場合はバージョン アップ時などの展開にかかるコストは抑えられる反面、デスクトップ アプリケーションと比較してリッチな描画や応答性の面で劣り、ローカルリソースへのアクセスも制限されるといったデメリットがあります。このように、デスクトップ アプリケーションと Web アプリケーションではトレードオフとなる部分があります。
また、このトレードオフの打開策として、デスクトップアプリケーションを共有フォルダーに配置して、リモートから実行するというソリューションが考えられますが、前述のとおり、こちらの方法は推奨されません。
マイクロソフトでは、この問題に対する解決策の 1 つとして、ClickOnce というデプロイメント テクノロジーを提供しています。ClickOnce では、通常のデスクトップ アプリケーションをローカルで実行可能なため、リッチな描画や応答性を維持することが可能であり、かつ、バージョンアップ時にはインストール ポイントに配置された資源をアップデートするだけで、ユーザーが特別な操作を行わなくても、アプリケーションの更新が自動的に実行されます。
管理者権限が必要な処理は行えないなどといった制限もあるため、必ずしも ClickOnce が配布に関する全ての問題を解決できるわけではありませんが、アプリケーションの展開方法の 1 つとして検討していただければ幸いです。
配置ストラテジの選択
http://technet.microsoft.com/ja-jp/subscriptions/index/e2444w33(v=vs.100).aspx
ClickOnce と Windows インストーラの使い分け
http://msdn.microsoft.com/ja-jp/library/ms973805.aspx
ClickOnce によるクライアン�� アプリケーションの配置の紹介
http://msdn.microsoft.com/ja-jp/library/ms996413.aspx