ASP テクノロジでのコンポーネントのトラブルシューティング

J.D. Meier
Microsoft Corporation

October 25, 1999

この記事は、もともと MSDN Online Voices のコラム "Servin' It Up" に掲載されたものです。

目次
はじめに
コンポーネントが失敗する理由
コンポーネントが ASP 向けに設計されていない
セキュリティ問題
スレッディング問題
こまごました部品の不足と DLL HELL
まとめ

はじめに

Active Server Pages (ASP) テクノロジ下の COM コンポーネント問題の診断は、システム管理者だけでなく、多くの開発者にとっても難題です。実働環境でしか発生しないらしい幽霊のようなエラーに悩まされるとしても、開発中にあなたの目の前で発生する問題に悩まされるとしても、問題の分析が難しいことに変わりはありません。この記事では、コンポーネント問題の特定と修正に役立つテクニックをいくつかご紹介します。

一般的なシナリオ

ASP テクノロジを使ったことがある人は、おそらく次のような状況に陥ったことがあるでしょう。

  • コンポーネントは Visual Basic® (またはその他のデスクトップ クライアント) では動作するが、ASP 実装の下では動作に失敗する。
  • コンポーネントは設計時には動作するが、実行時には動作しない。
  • コンポーネントが断続的に失敗する。
  • コンポーネントは、あるマシンでは動作するが、別のマシンでは動作しない。

あなたには、なじみのある話ですか? では、続けてお読みください。

コンポーネントが失敗する理由

コンポーネントが ASP 実装下で失敗するには、さまざまな原因があります。最も一般的な原因は、次のとおりです。

  • コンポーネントが ASP テクノロジ向けに設計されていない。 これは典型的なビジネス環境ではごく一般的なことであり、既存のアプリケーションをインターネットやイントラネットに移植する場合、アプリケーションのコンポーネントそのものが ASP テクノロジを念頭において設計されていません。
  • セキュリティ コンテキスト。 これがおそらくナンバーワンの殺し屋です。
  • スレッディング問題。 本当は COM スレッディングの複雑さ (threading COMplications) と言いたいところです。なぜなら、COM スレッディング モデルは、ループのために多くの分岐をスローして、アプリケーションのパフォーマンスとスケーラビリティにばく大な影響を与えることがあるからです。
  • こまごました部品の不足と Dynamic Link Library (DLL) HELL。 分散アプリケーションは素晴らしいものですが、ときには、Humpty Dumpy を組み立てているつもりが、結局は Mr. Potato Head になってしまうことがあります。

この 4 つの理由が、ASP テクノロジでのコンポーネントの失敗の中核を占めています。これらの問題の背景にある原理を知ることで、幅広い問題を診断できるようになります。

コンポーネントが ASP 向けに設計されていない

コンポーネントがデスクトップ クライアントから動作するという事実は、ASP から呼び出すことができる、あるいは ASP から呼び出すべきだということとイコールではありません。ASP から呼び出せるかどうか、どうしたらわかるでしょうか? そのためには、以下のことを調べる必要があります。

  • コンポーネントは IDispatch をサポートするか?

    IDispatch は、ASP スクリプトがそれを通じて自動化を行う COM インターフェイスです。

    COM コンポーネントが Visual Basic で作成された場合は、基本的にIDispatch をサポートしています。

    COM コンポーネントが Visual C++®で作成された場合は、それをチェックする必要があります。OLE Viewer を使用すると、コンポーネントのタイプ情報をすばやくチェックすることができます。OLE Viewer は Visual Studio® に含まれています。または、Microsoft の COM サイトからダウンロードすることができます https://www.microsoft.com/com/default.mspx Non-MSDN Online link)。

  • コンポーネントのスレッディング モデルは何か?

    これは、インプロセス コンポーネントに適用されます。

    コンポーネントは、アパートメント スレッドか、Both としてマークされて、フリースレッド マーシャラを集成すべきです。コンポーネントは、シングル スレッドまたはフリー スレッドであってはなりません。これは、Windows NT 4 Option Pack ドキュメンテーションに説明があります。このトピックの詳細については、George Reilly の「Server Performance and Scalability killers」を参照してください。IIS 5 では、Windows 2000 COM+ ソリューションとして、ニュートラル スレッディングが推奨されています。詳細については、"COM+ Programming Overview" (https://msdn2.microsoft.com/en-us/library/ms679171.aspx) を参照してください。

スレッディング モデルを調べる方法

  • レジストリでコンポーネントのスレッディング モデルをチェックします。Regedit を使用して、コンポーネントの LocalServer32 キーの ThreadingModel 値を調べます。

    Visual Basic で、[プロジェクトのプロパティ] でスレッディング モデルを設定します。

  • コンポーネントはホスト コンテナを必要とするか?

    Microsoft Foundation Classes (MFC) で書かれたものなど、ActiveX® コントロールはホスト コンテナの存在を前提としています。したがって、ASP スクリプトがコントロールのコンテナでないことに注意してください。

  • コンポーネントはメッセージ ボックスを表示させるか?

    ASP コードはサービスの下で実行するので、コンポーネントはデスクトップ アプリケーションでのようにダイアログをポップアップすることはできません。実際、これらのメッセージ ボックスは System デスクトップ上にあるのであなたの目には見えませんが、システムをハングさせることがあります。

  • コンポーネントは特定のユーザー コンテキストを必要とするか?

    実行時、ASP コードはセキュリティ コンテキストに応じて、一部のリソースへのアクセスを持ちません。たとえば、コンポーネントは HKEY_CURRENT_USER (HKCU) レジストリ ハイブを使用するべきではありません。HKCU は、現在ログオンしているユーザーに対応します。実働環境では、コンポーネントはログオン ユーザーとして実行すべきではなく、結果的にHKCU ハイブへのアクセスは失敗するでしょう。

  • コンポーネントはスレッド対応か?

    コンポーネントは、複数のスレッドから安全に呼び出すことができますか? ASP はマルチスレッドの COM クライアントです。

    アパートメント スレッド Visual Basic コンポーネントであれば、基本的にスレッド対応です。

    Visual Basic コンポーネントでない場合は、オリジナルの作成者またはベンダに問い合わせる必要があるでしょう。コンポーネントをスレッド対応に改造するのは非常に難しいことです。コンポーネントは最初からスレッド対応として設計されていることがベストです。

コンポーネントを継承したり、サードパーティ ベンダから購入して、コンポーネントに関する情報が限られている場合には、次のようにします。

  • コンポーネントが ASP 実装向けに設計されたかどうかを調べます。コンポーネントの作成者またはベンダは、これに答えることができるはずです。
  • レイト バインディングを使用して、Visual Basic からコンポーネントを呼び出します。レイト バインディングは、DimObject として使用するときです。これによって、IDispatch インターフェイスをテストするだけでなく、コンポーネントが必要な依存性を持っていることを確認できます。

上記の質問に答えることで、ASP スクリプトからコンポーネントを呼び出せることがわかるかもしれませんが、そうすべきだという意味ではありません。コンポーネントが ASP 実装を想定して設計されていなかった場合には、本来、ASP テクノロジの下で使用すべきではありません。経験に基づいて、私は ASP テクノロジの下であなたのコンポーネントを使用すべきかどうかを決める際には、以下のガイドラインに従うことをお勧めします。

  • スレッド ローカル ストレージ (TLS) に依存するコンポーネントの作成や使用を避けます。 たとえば、Visual Basic では、これは .BAS ファイル内のパブリック変数に等しいです。TLS とは、それぞれのスレッドがデータのコピーを持つことを意味します。Web では、これは予測不能な結果を持つことがあります。同じスレッド上のクライアントがデータを共有して、互いのメモリを潰し合う可能性があります。一方、異なるスレッドによって処理されるクライアントは、同じ変数に対して異なる値を持つかもしれません。
  • コンポーネントはステートレスであるべきです。 ページごとに作成と破壊が可能なように、1 つのメソッド コールから別のメソッド コールへ状態を維持する必要があってはなりません。コンポーネントはアプリケーションまたはセッション範囲で格納される必要があり、コンポーネントがアパートメント スレッドの場合には、赤信号は消えるはずです。
  • イベントを待つコンポーネントは、直接呼び出さないようにします。 ASP スクリプトから呼び出されたコンポーネントは、できるだけ速く ASP スクリプトに制御を返すべきです。これは、設計不良の多くの Web アプリケーションのボトルネックの原因です。時間がかかる操作を行う必要があるコンポーネントや、重要なイベントを待つコンポーネントがある場合は、Microsoft Message Queue Server (MSMQ) を使用することを考慮してください。
  • ASP テクノロジのデフォルトが変更されることを前提としているコンポーネントに注意します。 一部のサードパーティ製コンポーネントは、ScriptingTimeouts やその他の ASP スクリプト設定をデフォルトから変更することを必要とする場合があります。デフォルトの変更は必ずしも悪いことではありませんが、サーバーでの影響をきちんと調べるべきです。
  • ラップされているレガシー コンポーネントに注意します。 もともとデスクトップ アプリケーション用に書かれた多くのコンポーネントを COM ラッパーを使用して ASP テクノロジ下でホストすることは可能ですが、その意味合いを考慮する必要があります。コンポーネントはステートを必要としたり、ASP 実装向きの適切なスレッディング モデルを持っていない可能性があります。それをするなと言うつもりはありません。多くの開発者は、ソリューションの構築時にさまざまな制約を受けているのが現実だからです。私が言いたいのは、上記の ASP テクノロジ ガイドラインを考慮に入れてほしいということだけです。

セキュリティ問題

セキュリティ コンテキスト問題をよりよく理解するのには、Internet Information Service (IIS) のセキュリティを簡単に調べる必要があります。IIS 4.0 は、以下の認証方式を備えています。

  • NT 暗号化 (NTLM)。 このオプションはイントラネットに最適ですが、Netscape Navigator ではサポートされません。また、アクセスはサーバー マシンに限定され (リモート コンピュータ上の UNC 共有にアクセスすることはできません)、非認証プロトコル (ソケット) を使用する必要があります。
  • 基本認証。 これは Netscape Navigator によってもサポートされており、リモート マシンへのアクセスが可能であり、ドメインの境界を越えることもできます。基本認証では、ユーザーは資格証明の入力を要求され、アカウント情報はクリアテキスト (Base64 エンコード) として転送されます。
  • 匿名を許可。 このオプションは、IUSR_<machinename> アカウントが使用されることを意味します。

IIS 5.0 では、Windows 統合認証が導入されています。これは IIS 4.0 の Windows NT 暗号化に代わるものであり、アクセスをサーバー マシンに限定しません。

疑問が残ります。コンポーネントのセキュリティ コンテキストはどのように決まるのでしょうか。セキュリティ コンテキストは、プロセス セキュリティ、コンポーネント、およびコンポーネントの Web アプリケーション設定の組み合わせによって決まります。セキュリティ コンテキストがどのように決まるかがわかっていれば、セキュリティ問題の診断やセキュリティ問題の対処が容易になります。以下のルールは、セキュリティ コンテキストの組み合わせのカンニング ペーパーの役目を果たします。

  • シングル スレッドおよびフリー スレッド コンポーネントは、ローカルのシステム アカウントとして実行します。すでに述べたように、シングル スレッドまたはフリースレッド コンポーネントを ASP スクリプトから呼び出すべきではありません。
  • Web アプリケーションの [別メモリ領域で実行する] がチェックされていない場合、Apartment または Both としてマークされているインプロセス コンポーネント (DLL) は、IUSER_<machinename> を偽装します。匿名アクセスを許可している場合は、デフォルトでこのようになり、IIS 認証が使用される場合は、コンポーネントは認証されたアカウントを偽装します。
  • Web アプリケーションの [別メモリ領域で実行する] がチェックされている場合、Apartment または Both としてマークされているインプロセス コンポーネント (DLL) は、IWAM_<machinename> を偽装します。匿名アクセスを許可している場合は、デフォルトでこのようになり、IIS 認証が使用される場合は、コンポーネントは認証されたアカウントを偽装します。
  • MTS Library パッケージ内のコンポーネントは、上記のルールに従います。
  • MTS Server パッケージ内のコンポーネントは、コンポーネントのパッケージ プロパティの [ID] タブで指定されたユーザーとして実行します。
  • アウトオブプロセス コンポーネント (EXE) は、デフォルトでは、起動ユーザーのコンテキストを偽装します。[別メモリ領域で実行する] がチェックされていない Web アプリケーションによって起動された EXE の場合、EXE は System として実行します。Web アプリケーションの [別メモリ領域で実行する] がチェックされていた場合は、デフォルトでは IWAM として実行します。

これらのルールはコンポーネントのセキュリティ コンテキストについての予測に役立ちますが、それでもセキュリティ コンテキストを調べる上でトラブルを経験するかもしれません。そのようなときには、以下のテクニックが役立つでしょう。

  • コンポーネントの中から GetUserName API を呼び出して、それをファイルまたは NT イベント ログに書き込みます。これは、コンポーネントのセキュリティ コンテキストを返します。Visual Basic を使用している場合は、App.LogEvent を使用して NT イベント ログに書き込むことができます。
  • NT 監査を有効にします。ステップバイステップの詳細については、Knowledge Base (KB) の記事: Q185874 How to Troubleshoot Permissions in Internet Information Server 4.0 を参照してください。
  • https://www.sysinternals.com/ Non-MS link にある NT FileMon、RegMon、および HandleEx を使用します。Excel でこれらのログを開いて、Excel の [データ] メニューの [オートフィルタ] コマンドを使用すると、問題をすばやく見つけることができます。
  • MTS サーバー パッケージのコンポーネントを実行します。このテクニックは、あなたのコンポーネントが実行する特定の ID の設定を可能にすることによって、セキュリティ コンテキスト問題のテストに役立ちます。サーバー パッケージは、パッケージのプロパティの [ID] タブの設定を使用したセキュリティ コンテキストで MTX.exe の新しいインスタンスを起動します。これはトラブルシューティング テクニックとしてだけでなく、セキュリティ コンテキスト問題の効果的な回避策にもなります。ステップバイステップの詳細については、KB の記事: Q223406 HOWTO: Create an Empty MTS Package to Add Components for ASP を参照してください。

IIS 下のコンポーネントのセキュリティ問題についてさらに知りたい場合は、KB の記事 Q172925 INFO: Security Issues with Objects in ASP and ISAPI Extensions を参照してください。

スレッディング問題

スレッディングは複雑な問題であり、パフォーマンスからセキュリティまで、しばしばコンポーネント問題の一因となります。しかし、トラブルシューティングの見地からは、かなり簡潔に説明することができます。ASP スレッディング問題は、2 つの基本的な部分に分けることによって理解しやすくなります。

  1. ASP 実装でのスレッディング モデルの意味は何か?
  2. ASP テクノロジはスレッドをどのように処理するか?

ASP でのさまざまなスレッディング モデルの意味合いについては、「コンポーネントが ASP 向けに設計されていない」のセクションですでに述べたので、ここでは、ASP によるスレッドの処理について説明します。

ASP スレッディングの概要

一般に考えられていることに反して、ASP テクノロジは独自のスレッドを処理するわけではありません。ASP スクリプト スレッドは、実際には IIS のメイン スレッド プールの外側にある別のプールで MTS によって管理されます。このことを念頭に置いた上で、ASP スレッドについて知っておく必要があるポイントを以下に述べます。

  • ASP テクノロジは、デフォルトでは、プロセッサあたり 10 個のスレッドを MTS によって割り当てられます。ユーザーのすべての要求はこの 10 個のスレッドによって処理されるため、これらのスレッドの取り扱いが重要です。言い換えると、STA オブジェクトをセッションに格納しないことです。そのようにすると、Web アプリケーション全体がそのユーザーセッションの単一スレッドにロックダウンされてしまいます。任意のスレッドが任意の要求を処理できれば、ASP コードの効率は大幅に向上します。

  • それぞれのアウトオブプロセス Web アプリケーション ([別メモリ領域で実行する] がチェックされている) は、デフォルトで 10 個のスレッドプールを個別に持ちます。

  • プロセッサあたりの ASP スレッドの数は、次のレジストリ キーによって制御されます。

    ProcessorThreadMax

    Regedt32 を使用して、HKEY_LOCAL_MACHINE\
    SYSTEM\
    CurrentControlSet\
    Services\
    W3SVC\
    ASP\
    Parameters に移動します。

    まだ存在しない場合は (デフォルトでは存在しません)、DWORD 値 ProcessorThreadMax を追加します。IIS 5.0 では、これは metabase 設定の、w3svc/AspProcessorThreadMax です。この数を変更した方がよい場合もありますが、通常は変更する必要はありません。実際、問題解決のためにスレッド数を増やしても、コンテキスト スイッチングの回数が増えるので、状態が悪化することがあります。このパラメータの調整については、「Tuning Internet Information Server Performance Non-MSDN Online link」を参照してください。

スレッディング問題を分析するときには、以下のことを念頭においてください。

  • ASP サーバーサイドのデバッグを無効にします。さもなければ、ASP コードは単一のスレッドにロックダウンします。
  • Visual Basic IDE は、セキュリティまたはスレッディング問題の診断には適していません。このデバッガは、インタラクティブ ユーザーとして実行する単一の実行スレッドを使用します。
  • NT パフォーマンス モニタでは、次の 3 つのカウンタがあなたのベスト フレンドになります。
    • ASP の Requests Executing。このカウンタは、進行中の現在の要求数を示し、いくつのスレッドが同時に実行しているかを見るのに最適です。
    • ASP の Requests Queued。このカウンタは、ASP キューに入っている現在の要求数を示します。
    • ASP の Requests Per Second。このカウンタは、1 秒間に実行された ASP ページ数を示します。これは、アプリケーションのボトルネックを識別するのに役立ちます。
    • System の Context Switches/sec。これが 2~3,000 以上の場合は、おそらくコンポーネントに「ホット ロック」があります。ASP スレッドがすべてキューに入れられ、コンポーネント内の共有リソースへの排他アクセスの取得を待っています。
  • コンポーネントから GetCurrentThreadId() API を呼び出すと、スレッド ID を吐き出させることができます。これは、直列化などの一般的な問題の確認と診断に役立ちます。
  • 同じユーザー セッションからの同時要求は直列化されます。このことを念頭に置いて、新しいプロセスでブラウザを起動するように設定して、クッキーを無効にしない限り、ブラウザをテストに使用しないでください。これらのオプションを設定すると、ASP スクリプトはそれぞれの要求を新しいセッションとして扱います。これらのオプションを設定しなかった場合、ブラウザの [更新] を続けざまにクリックするなど (標準的な ASP テスト)、前の要求が完了する前に新しい要求を同じセッションから送信すると、直列化が発生します。その結果、スレッドが使用可能な場合でも、ASP の Requests Queued が増加します。
  • Web Application Stress Tool (「I Can't Stress It Enough - ASP アプリケーションのロード テスト」を参照) を使用して、複数クライアント アクセスをシミュレートします。2 人のユーザーだけで再現される問題など、限られたトラブルシューティング以外にはブラウザを使用しないでください。

ASP スクリプトのスレッド パフォーマンスの分析については、何冊も本を書くことができます。実際、そのような本が書かれています。追加情報の優れた情報源は、IIS 4.0 Resource Kit です。

こまごました部品の不足と DLL HELL

私は一番よい問題を最後まで残しておきました。あなたが別のマシンにコンポーネントを置いたところ、重要な部品が不足しているか、他に依存している物のバージョン不一致のために、コンポーネントが動作しません。あなたはすでに「セキュリティ問題」で説明したテクニックを使用して、セキュリティ問題を取り除きました。

これは実際に最悪の問題の 1 つです。なぜなら、このような場合の診断は、干し草の山から針を見つけるようなものだからです。踏んだり蹴ったりなことに、別のマシンではコンポーネントが問題なく動作することがわかっています。この特定のマシンに問題があると考えがちです。

この問題に対する最良のアプローチは回避です。あなたのソリューションを導入して、顧客から料金を受け取り、逃げろ、という意味ではありません。このジレンマがなるべく発生しないように、予防措置を講じてください。以下のテクニックは、問題の頻度と重大度の軽減に役立つことがわかっています。

  • ハードウェアとソフトウェアなど、導入ターゲットをミラー化します。これは高くつくように見え、実際、通常は高くつくのですが、システムダウンが発生した場合の方がさらに高くつきます。

  • Visual Basic を使用している場合は、パブリック インターフェイスが固まるまで、プロジェクト互換性のあるコンポーネントを開発してください。

    パブリック インターフェイスが固まったら、バイナリ互換性のあるプロジェクトを構築します。

    導入ターゲットを詳細に制御できる場合以外は、パブリック インターフェイスを変更しないでください。古いバージョンのコンポーネントが新しいバージョンに上書きされるおそれがあります。潜在的に、新しいインターフェイスを予期しているクライアントは、存在しないメソッドを呼び出すでしょう。その代わりに、新しいインターフェイスを持つ新しいコンポーネントを作成してください。詳細については、"Building, Versioning, and Maintaining Visual Basic Component." を参照してください。

  • コンポーネントのための包括的で堅牢なエラー処理、エラー ロギング、およびイベント ロギングを含めてください。いつか、こうしておいてよかったと思うときが来るでしょう。

  • DLL の手動インストールを行ってください。これはシステムに衝撃を与えるのを防止し、インストール中に問題が発生しても回復することができます。手動インストールを行うには、RegSvr32.Exe を使用して、新しい DLL を登録します。DLL を置き換える場合は、まず、RegSvr32.Exe に /u パラメータを使用して古い DLL を登録解除して、.old などの拡張子を追加することによって DLL の名前を変更します。次に、新しい DLL を追加して、RegSvr32.Exe に登録します。

問題を回避するには手遅れだという場合もあります。問題を訂正するために何ができるでしょうか? 以下のテクニックは、積み重なっている問題の層を減らす上で役に立ちます。

  • Dependency Walker ツール (depends.exe) を使用します。
  • Visual Basic テスト EXE から呼び出して、対象となるコンポーネントの中核機能をテストできる単純なメソッドをコンポーネント内に作成します。このテストは重要です。インスタンス化、セキュリティ、および依存性問題のすべての診断を迅速に行うことができるからです。
  • 同様に、OLE Viewer を使用して、そもそもコンポーネントがインスタンス化できるかどうかを調べることもできます。これにより、ASP の機能性だけを取り出して、問題の複雑さを軽減することができます。ASP スクリプトからコンポーネントを呼び出すためには、OLE Viewer からコンポーネントをインスタンス化できる必要があります。
  • 「セキュリティ問題」ですでに述べたように、NT FileMon、NT RegMon、および NT HandleEx を使用します。

まとめ

これだけの知識があれば、ASP での広範囲のコンポーネント問題を特定し、診断できるはずです。この能力であなたの友人たちを感嘆させることはできないかもしれませんが、あなたの Web アプリケーションの健康を保ち、顧客を幸せにしておく上で役立つでしょう。

J.D. Meier は米国東海岸で生まれて育ちました。Horace Greeley の助言に従って、MTS および ASP 技術を含むサーバー側コンポーネントと Windows DNA アプリケーションを専門とするデベロッパ サポート エンジニアとして働いています。