IIS Insider

2005 年 7 月

IIS Insider

Internet Information Services に関してよく寄せられる質問と答え

By Chris Adams

トピック
マウントされたボリュームのためのルート パーティションの属性を変更するマウントされたボリュームのためのルート パーティションの属性を変更する
IIS 6.0 でデータ マイニングを減らすための集中ログ管理IIS 6.0 でデータ マイニングを減らすための集中ログ管理
ASP.NET ページのアウトプット キャッシングのトラブルシューティングASP.NET ページのアウトプット キャッシングのトラブルシューティング

マウントされたボリュームのためのルート パーティションの属性を変更する

Q

Windows Server 2003 にマウントされたボリュームがあります。そしてサイトのパスをその場所 (たとえば C:\Web) に指しています。クライアントが、完全修飾ドメイン名 (FQDN) のみを使用して (または仮想ディレクトリで) リクエストをした場合に、エラー メッセージ 404 を受け取ります。しかし、ファイルに直接リクエストすることは、ページを供給することです。ファイル名が含まれていない場合に、どうしてエラー メッセージ 404 が出るのでしょうか?

A

標準外のディスク構成の通常とは異なる構成が問題です。なぜなら、マウントされたディスクのルート パーティションは IIS などのサービスに対しオペレーティング システムによって表される方法だからです。

例として、このシナリオを考えてください。

Disk 1: 20 GB NTFS Volume (C:\)
Disk 2: 80 GB NTFS Volume

皆さんは、すべての Web コンテンツのための、シングル ディスク 1 と C:\Web のパスを使用して Web 環境をすでに設定していると考えてください。Web アプリケーションを再試行するためのオーバーヘッドを避けるために、ストレージを拡大させたいと思っています。しかし、皆さんはこの変更を、Web アプリケーションのコードに対する最小限の変更で行ないたいと思っています。

ですから、Disk 2 の構成を作成し、すでに作成した C:\ のボリュームの一部として保存します。この場合、他のボリュームの別の実際のディレクトリに置くために、このボリュームのルート パーティションを再度書き入れています。まぎらわしい様ですが、多くの Web 管理者にとっては、ありがちな設定です。

問題に戻りましょう。リクエストした際に、クライアントが IIS にフェッチするための実際のファイルを提供しなかった場合、IIS は異常終了します。このシナリオでは、既定のドキュメントをもとにしたドキュメントを提供するために、クライアントは IIS サーバーに依存しています。
既定のドキュメントのリストは仮想ディレクトリの "Documents" のタブで見つけることができます。そして通常、default.htm、default.html、default.aspx などのような項目を含んでいます。
IIS が特定のファイルを含まないリクエストと提供された場合、"documents" のリストを実行して、ファイルを開こうとします。特定の API – CreateFile を呼び出す際に、IIS はこれを独自の方法で行います。
CreateFile コールは、ドライブのルート パーティションを検索しようとするもので、リクエストされた Web サイトのパスを適切なドキュメントと共に付け加えます。

たとえば、既定のサイトがこの構成であると仮定してください。

Path: C:\inetpub\wwwroot

DefaultDoc: index.htm

このサイトへのリクエストが行なわれ、ファイルが特定されなかった場合、IIS は API を呼び出し "\\?\inetpub\wwwroot\index.htm." のファイルをリクエストします。
ほとんどのシナリオでは、これは完全に受け入れられることですが、既存のドライブへパーティションをマウントした独自の構成ではそうではありません。
IIS 6.0 は通常、一般的なパーティションのルート パーティションが隠れているという事実を見落とします。しかし、マウントされたボリュームの場合は違います。この通常とは異なるシナリオでは、Windows Server 2003 のディスクの動作のために、ルート パーティションの検索は失敗します。

問題の実質的な理由は、そのエラーが、ルート パーティションを隠している、マウントされたパーティションの既定の動作により起こったということです。
IIS 6.0 (そして前のバージョン) は、隠れたファイルの真の目的に反するものなので、隠れたコンテンツを一般的に提供しません。
例外は、ルート パーティションです。IIS は C:、D: などの標準のルート パーティションを見落とします。そしてルート ボリュームを隠す通常のオペレーティング システムの動作を処理します。
一方で、マウントされたボリュームは異なります。なぜなら、それらは、リダイレクトであるためです。そして IIS はルート パーティションが隠れているという事実を見落とさないからです。

これを修正するために、1 度限りのスクリプトを書いてマウントされたボリュームのルート パーティションの属性を変更するか、その代わりに、処理の前にリクエストを再度マッピングするために、ISAPI フィルタを書くことができます。
最初の選択である属性の変更は、より効果的で、効率的です。それは、ランタイムや運用システムに影響しないからです。1 度行なわれるだけです。ファイルの属性を変更するには、C コードで何行か書き、コンパイルして完了です。

みなさんを正しい方向へ導くために使用するため、サンプルのスクリプトを含みました。

#include "precomp.hxx"

extern "C" INT
__cdecl
wmain(
    INT argc,
    PWSTR argv[]
)
{
    if (argc != 2)
    {
        printf("Usage: %S <mount-directory-name>\n", argv[0]);
        return 1;
    }

    PWSTR pszDir = argv[1];
    DWORD cchDir = wcslen(pszDir);

    if (pszDir[cchDir - 1] != L'\\')
    {
        printf("The mount-directory-name should terminate with a \\\n");
        return 1;
    }

    WCHAR pszVolumeName[50];
    if (!GetVolumeNameForVolumeMountPoint(pszDir,
                                          pszVolumeName,
                                          sizeof(pszVolumeName)/sizeof(WCHAR)))
    {
        printf("The directory %S does not seem to be a root mount point\n", pszDir);
        return 1;
    }

    if (!SetFileAttributes(pszDir,
                           FILE_ATTRIBUTE_NORMAL))
    {
        printf("SetFileAttributes failed - error %d\n", GetLastError());
        return 1;
    }

    return 0;
}

オプション 2 に興味がある場合、 IIS SDK (英語情報) を読んでください。それは、みなさんが IIS のハンドラに渡す前にリクエストを変更するために設計された ISAPI のフィルタの構築方法を理解するのに役立ちます。

ページのトップへページのトップへ

IIS 6.0 でデータ マイニングを減らすための集中ログ管理

Q

会社で、比較的大きな共有の IIS サーバーを使用しています。1000 以上のログ ファイルを処理するのはある意味面倒なので、ログ ファイルの管理を簡素化することが可能な場所を設置しようとしています。最新の更新プログラムを適用した Windows Server 2003 を実行しています。

A

Windows Server 2003 は使用において新しい機能を提供しています。それはとても強力な Centralized Binary Logging (CBL) です。

CBL は HTTP.sys (IIS 6.0 の一部) の一部です。Windows Server 2003 では、ODBC のログ以外のすべてのログが HTTP.sys のカーネル ドライバによって行なわれます。
つまり、IIS 6.0 は、前のバージョンで行なわれていたように、リクエストごとに正確なログ データをディスクに書き込む責任をもはや担っていません。
CBL は非常に最適化されたログ形式で、すべてのリクエスト データがバイナリでひとつのファイルにログされます。
このフォーマットされていないバイナリのデータは動作には適していますが、みなさんのような管理者にとっては大変です。実際、そのままでは、独自のプログラムを C++ 言語で書かない限りは、CBL を使用して作成されたログ ファイルを読むための効果的なメカニズムはありません。

Log Parser 2.2 日本語版 は、優れたコマンドラインのユーティリティで、データの読み取りおよびフォーマットの両方に使用できます。CBL ログを持つログ パーサーの使用についての詳細情報は、次の Web キャスト TechNet Webcast: The Ins and Outs of Centralized Binary Logging in IIS 6.0 (英語) をご覧ください。

皆さんへのすばらしいニュースとしては、Service Pack 1 の HTTP.sys に実装された新しい機能です。この機能は、高い機能性であるにもかかわらず管理しやすいログのメカニズムを作成するために、2 つのログ フォーマットをひとつにしたものです。

これは、W3C の集中ログと呼ばれます。この機能の鍵となるのは、サイト、ディレクトリおよびファイルで独自のログ ファイルが管理できない場合に、「集中」ログ ファイルを活用することです。

W3C の集中ログと共に、管理者は W3SVC のディレクトリで作成されたログ ファイルを確実にひとつ得ることになります。このファイルは W3C 規格に沿っており、標準のプロパティと拡張されたプロパティのログを有効にするもので、IIS に出された Cookies やエラー コード Win32 のようなものです。これらの「拡張された」プロパティは CBL のユーザーには利用できません。

皆さんの場合、W3C の集中ログへ切り替えることにより、独自のロール オーバーのメカニズムに基づき、1 日、1 時間ごとに、1 つのログ ファイルを管理できるようになります。これは、IIS 6.0 に関して、ひとつのディレクトリに数個のファイルのアプローチよりもさらに良いものです。
さらに、データを表示するために Log Parser 2.2 のような特別なツールは必要ありません。データは好きなテキスト エディタで表示することが可能です。しかし、注意すべきなのは、ファイルは通常かなり大きいので、メモ帳 テキスト エディタは十分でないかもしれません。
残念なことに、W3C の集中ログを有効にするには、ユーザー インターフェイスのチェック ボックスよりも、設定により時間がかかります。CBL と同様に、W3C の集中ログは IIS マネージャでは利用できません。そして直接にメタ ベースで編集しなければなりません。これを行なうには、下記のように、CentralW3CLoggingEnabled のプロパティを修正するだけです。

cscript adsutil.vbs set w3svc/CentralW3CLoggingEnabled 1

この値を有効にしたら、IIS サービスを再起動できます。そして、その後、IIS はテキスト エディタで読み取ることのできる、フォーマットされたファイルを 1 つ使用して、すべてのサイトに全リクエストのログを記録しています。

Figure 1: W3C Centralized logging has been enabled

図 1: 有効にされた W3C の集中ログ

ページのトップへページのトップへ

ASP.NET ページのアウトプット キャッシングのトラブルシューティング

Q

新しい ASP.NET のアプリケーションのストレス テストの際、開発者は、カーネルにこの動的なリクエストを保存するために ASP.NET の出力キャッシュの機能(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp03282002.asp) (英語) を使用しているので、パフォーマンスの向上を見なければならないと話しました。我々のテストでは、そのように動作していないようです。出力キャッシュを有効にした後も失敗しています。何が不足しているのでしょうか?

A

新しいカーネル ドライバの HTTP.sys は、とても強固です。このドライバは、カーネル モードからユーザー モードへの必要な移行を避けます。そしてパフォーマンスを顕著に向上させます。多くの場合、ユーザー モードでアイテムをキャッシュする 4 倍まで速くなります。

問題に対する鍵となるのは、この動作に関連する比較的重要でない内容に上手く従うかどうかです。この回答の中で、見逃されてしまう可能性のある詳細をできるだけ提供するつもりです。しかし、みなさんの問題には多くの異なる理由があるかもしれません。

最初のステップは、ASP.NET のアプリケーションが、カーネルによってキャッシュされることができるいくつかの必要なルールに従ったものであることを確認してください。これらは、IIS 6.0 のドキュメントおよびマイクロソフト技術情報 817445で説明されています。

ASP.NET のアプリケーションがこの基準を満たすものであると確認できたら、インストールしたすべてのフィルタに対する正しい設定をしていることを確認してください。ISAPI のフィルタはサーバーに対するリクエストと、サーバーにより送られた応答を変更するように設計されました。

この基準により、カーネル キャッシュが問題になります。それは、リクエストが決して IIS によって処理されないからです。従って、カーネル キャッシュを効果的に動作させるためには、管理者はインストールされた IIS 6.0 の ISAPI のフィルタが True (または、ゼロ以外) に設定された FilterEnableCache のメタベースのプロパティを持っていることを確認する必要があります。
皆さんのサーバーまたはサイトに現在ダウンロードされている ISAPI フィルタのリストを見つけるには、以下を行なってください。

コマンドラインのユーティリティである adsutil.vbs または、IIS 6.0 のリソース キット ツールのユーティリティ Metabase Explorer (図 2 参照) を使用してください。

Figure 2: FilterEnableCache in the IIS Metabase Explorer

図 2: IIS Metabase Explorer のFilterEnableCache

IIS 6.0 は、既定で ISAPI フィルタが 2 つだけ搭載されています。それは ASP.NET フィルタと、FrontPage ISAPI フィルタです。この両方のフィルタは、「キャッシュ」フレンドリー フィルタで、既定で正しく有効になります。この問題は、ISAPI フィルタ ベースのカスタム アプリケーションを読み込んだ場合、または独自の ISAPI フィルタを書いた場合にのみ起こります。

もし、FilterEnableCache が 0 に設定されていたら、すべてのカーネル キャッシングはオフとなります。しかし、ただ単に 1 (ゼロ以外) に設定すると、キャッシングの開始が直ちにオンとなることが確認されません。それを有効にして、役立てるためには、このプロパティの設定をしたフィルタが特定の動作しないことを確認しなければなりません。
ご存知のように、フィルタはサーバーの動作を変更するために設計されました。これは、サーバーへのリクエストに基づいた動作により行なわれるものです。
HTTP のヘッダーを解析している間に、動作が決定されます。これらが、フィルタがキャッシュを認識できるようにされているという事実を無効にできる可能性のある操作です。たとえば、リクエストされた実際の URL (/vdir1 is "re-mapped" to /vdir2) を変更する可能性のあるフィルタがいくつかあります。または"SF_NOTIFY_SEND_RAW_DATA" (英語) や "SF_NOTIFY_LOG" (英語) の通知をリッスンする可能性があります。もし、これらの動作が行なわれなければ、カーネルのキャッシングは予定通りに行なわれます。

まとめとして、サーバーにどのフィルタが読み込まれ、何をするのかを知ることです。これは、ご質問にあったようなエラーに対するトラブルシューティングに役立ちます。

次のステップで、ASP.NET アプリケーションの開発の側面のさらに詳細を説明します。キャッシングを有効にするために、ページがキャッシュ可能であると特徴付けられるべきです。そして Web のアプリケーションはカーネル キャッシュを使用するために設定されるべきです。

ページ レベルの OutputCache を有効にするために、ページのトップに、次の指示を追加することができます。

<%@ outputcache duration="60" varybyparam="*" %>

この機能を有効にした後、パフォーマンスが少し向上したとわかるはずです。なぜなら、ASP.NET は、ほかのクライアントによってより早く検索されるために、データを内部でキャッシュします。しかし、これはカーネル キャッシングを有効にしないで、依然としてカーネルからユーザー モードへの変更が必要になります。前に述べたように、これは 4 倍遅くなります。

"カーネル モード" で応答をキャッシュさせるために ASP.NET のWeb のアプリケーションを有効にするためには、図 3 に示されているように、AppDomains のルートは、コンテンツ ディレクトリの Web.config のファイルを変更するべきです。

Figure 3: Web Config File Modificationr

図 3: Web 設定ファイルの変更

図 1 に示されているように、ASP.NET には、守らなければならない特別のルールがいくつかあります。

表 1: ASP.NET キャッシュ ルール

キャッシュの機能

... 公開が必要 (<%@ OutputCache Location="Any"%>

追加のキャッシュへの依存性

「NONE」になる

〜により異なる

VaryByHeaders が無いか、または VaryByParams (NONE) になる

キャッシュフィールド

すべてのカスタム キャッシュ フィールドの使用を避ける

検証

「コールバックの無効」にする

動詞の活用

GET 以外の動詞を入れるべきでない

保存なし

設定されていない

期限切れ

固定された間隔で、引き違いをしないように設定

これらの規則に従うことにより、ASP.NET の httpRuntime がコンテンツをキャッシュするための、カーネル ドライバの HTTP.sys を許可できるようになります。

EnableKernelOutputCache の詳細については、http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetchapt06.aspx をご覧ください。

おわかりのように、これは「スイッチを入れる」機能ではありません。それは、動的なアプリケーションが度々動作しているところのいくつかの異なる層だからです。この素晴らしい IIS 6.0 および ASP.NET 機能を活用するために、それぞれの設定が正しいことを確認してください。これが問題解決に役立つことを望んでいます。


関連情報

これまでの IIS Insider コラムの質問と答えの一覧は、ここをクリック してください。

ページのトップへページのトップへ