japan.internet.comThe Internet & IT Network
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2008年9月6日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
デベロッパー2006年9月12日 11:00

ASP.NETにおけるHTTPデータの取得とキャッシュ

海外海外internet.com発の記事
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • Buzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!

はじめに

 最近はWebサービスやRSSフィードが特別なことでなくなり、どこか他の場所からデータを収集することが当たり前となっているようです。幸い、ASP.NETのおかげで、リモートサーバーからHTTPを介してデータを取得することは簡単に行えるようになっています(もしかしたら、簡単すぎると言えるかもしれません)。多くのアプリケーションがこれを利用しているのは、1つの要求を受け取るたびに複数の要求が出されるからです。

 私がリモートサーバーからデータを取得して表示する必要があると初めて思ったのは、ある顧客のためにWebサイトを作成していて、その顧客がホームページに株価情報を表示したいと言ってきたときでした。彼らを失望させたくなかったので(何しろ、株式を公開するほど大きな顧客だったのです!)、どう取り組むべきか厳密に考えてみることにしました。そして、どうにかスクリプトを動かすことに成功しましたが(簡単な作業ではありませんでした――Internet Transfer ControlとWinInetのことをご記憶の方にはご理解いただけるでしょう)、その遅さにはがっかりしました。この遅さに加え、要求が出されたときWebサーバーがクラッシュしがちなことや、当時はダイヤルアップを通じてまだ多くの作業を行っていたことなどの理由から、株価情報をかなり長い期間にわたってキャッシュするようにしていました。

HTTPを介してリモートサーバーのデータを取得する

 当時、私はHTTPデータを取得するために.NET以前のASPで何年も同じスクリプトを使用していて特別困ったことはありませんでした。そのため、.NET版を書くことになったとき、現在のスクリプトを書き換えてそのまま使えばよいだろうと考えていました。

 .NET以前のASPに興味がある方は、数年前に書いた短い記事『A Simple Method for Caching HTTP Requests』をご覧ください。

 ところで、当のスクリプトには変更すべき部分が少なからずあることが判明しました。COM Componentの代わりに.NET Frameworkを使うことになったのでHTTPセクションの全面変更が必要でした。.NETにキャッシュ機能が組み込まれたのでメモリキャッシュのためにApplication変数を使うことも必要なくなりました。以前のスクリプトを書き換えるだけではもう無理で、そろそろ最初から作り直さなければならないようでした。

 最初のステップは、当然ながら、リモートサーバーからHTTPを介してデータを取得することです。このプロセスは実際それほど複雑でありませんが、多数のオブジェクトが関係するので複雑に見えるかもしれません。

http.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
    Sub Page_Load(Src as object, E as EventArgs)
        Dim strRssFeedText As String

        ’ Call the GetWebPageAsString function to retrieve
        ’ the 15 Seconds RSS feed as text.
        strRssFeedText = GetWebPageAsString( _
            "http://www.15seconds.com/dyna/15secs_rss.asp")

        ’ HTMLEncode the RSS feed and display it in the browser.
        litTextRetrieved.Text = Server.HTMLEncode(strRssFeedText)
    End Sub

    Function GetWebPageAsString(strURI As String) As String
        ’ Declare our variables.
        Dim objWebRequest As WebRequest
        Dim objWebResponse As WebResponse
        Dim objStream As Stream
        Dim objStreamReader As StreamReader
        Dim strResponseText As String

        ’ Create a new request.
        objWebRequest = WebRequest.Create(strURI)

        ’ Get the response to our request as a stream object.
        objWebResponse = objWebRequest.GetResponse()
        objStream = objWebResponse.GetResponseStream()

        ’ Create a stream reader to read the data from the stream.
        objStreamReader = New StreamReader(objStream)

        ’ Copy the text retrieved from the stream to a variable.
        strResponseText = objStreamReader.ReadToEnd()

        ’ Close our objects.
        objStreamReader.Close
        objStream.Close
        objWebResponse.Close

        ’ Set return value.
        GetWebPageAsString = strResponseText
    End Function
</script>
<html>
<head>
<title>HTTP Request Sample</title>
</head>
<body>

<pre>
<asp:Literal id="litTextRetrieved" runat="server" />
</pre>

</body>
</html>

 上記のスクリプトを実行すると、http://www.15seconds.com/dyna/15secs_rss.aspに対して要求が出されます(ここではサイト「15 Seconds」のRSSフィードのアドレスを使用しています)。このフィードの一番下にサーバーの現在時刻を示すコメントがあり、大抵数分ずれています。

HTTPを介してリモートサーバーのデータをキャッシュする

 キャッシュがどれほど偉大な技術かを初めて知ったのは、古いコンピュータをアップグレードしようとしたときでした。私は新しいディスクドライブを手に入れ、それまでのデータをコピーするために、古いコンピュータに追加装着しました。古い起動ディスクを使ってマシンを起動し、XCopyを用いてファイルをドライブ間で転送したのですが、驚くほど処理が遅いのです。あまりに遅いので、新しいディスクドライブに問題があるに違いないと考えました。数時間かけて問題を探り、何件か電話した後、SMARTDriveが高速化に非常に大きな貢献をしていることを発見しました。以来、私はキャッシュの熱烈な愛好者になりました。

 HTTP要求をキャッシュすることがなぜ重要なのでしょうか。HTTP要求は、Webサーバーに対する要求の中でも特に遅いからです。HTTP要求は大抵のデータベース要求よりも時間がかかります。データベースはローカルディスクに置かれるのが一般的ですが、HTTP要求はインターネットを流れ、失敗の可能性を含む多数の処理を経てやっと応答が届きます。まず、DNS経由で接続する相手のサーバーのIPアドレスを解決する必要があります。次に、要求をサーバーに到達させる必要があります。その後、サーバーが応答し、その応答を最終的に受け取る必要があります。我々はインターネットの信頼性が向上したおかげで多数のステップを経てHTTP要求が成功するのは当たり前と思っていますが、応答が到達するまでには多くの処理を経る必要があり、それらは必ずしも瞬時に起こるとは限りません。

http_cached.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
    Sub Page_Load(Src as object, E as EventArgs)
        Dim strRssFeedText As String

        ’ Retrieve the entry from the cache
        strRssFeedText = Cache("15SecsRssFeedText")

        ’ If the data retrieved is null then we
        ’ get it from the remote server and insert
        ’ it into the cache for future calls.
        If strRssFeedText = Nothing Then
            ’ Call the GetWebPageAsString function to retrieve
            ’ the 15 Seconds RSS feed as text.
            strRssFeedText = GetWebPageAsString( _
                "http://www.15seconds.com/dyna/15secs_rss.asp")

            ’ Insert the text into the cache. I’m setting it
            ’ to expire 15 minutes from when we add it.
            Cache.Insert("15SecsRssFeedText", strRssFeedText, _
                Nothing, DateTime.Now.AddMinutes(15), _
                System.Web.Caching.Cache.NoSlidingExpiration)
        End If

        ’ HTMLEncode the RSS feed and display it in the browser.
        litTextRetrieved.Text = Server.HTMLEncode(strRssFeedText)
    End Sub

    Function GetWebPageAsString(strURI As String) As String
        ’ Declare our variables.
        Dim objWebRequest As WebRequest
        Dim objWebResponse As WebResponse
        Dim objStream As Stream
        Dim objStreamReader As StreamReader
        Dim strResponseText As String

        ’ Create a new request.
        objWebRequest = WebRequest.Create(strURI)

        ’ Get the response to our request as a stream object.
        objWebResponse = objWebRequest.GetResponse()
        objStream = objWebResponse.GetResponseStream()

        ’ Create a stream reader to read the data from the stream.
        objStreamReader = New StreamReader(objStream)

        ’ Copy the text retrieved from the stream to a variable.
        strResponseText = objStreamReader.ReadToEnd()

        ’ Close our objects.
        objStreamReader.Close
        objStream.Close
        objWebResponse.Close

        ’ Set return value.
        GetWebPageAsString = strResponseText
    End Function
</script>
<html>
<head>
<title>Cached HTTP Request Sample</title>
</head>
<body>

<pre>
<asp:Literal id="litTextRetrieved" runat="server" />
</pre>

</body>
</html>

 上記リストの太字の行に注目してください。これらの行がキャッシュの処理に関係します。1行目で、キャッシュ内のデータを取得します。2行目で、戻り値のデータがあるかを確認します。戻り値のデータがある場合は、そのデータを用いてページを作成し、リモートサーバーにはHTTP要求を出しません。データがキャッシュにない場合は、リモートサーバーにデータを要求します。3行目で、将来のページ要求のためにデータをキャッシュに保存します。

 ASP.NETのキャッシュエンジンは堅牢にできており、キャッシュ項目の有効期限を何通りもの方法で指定できます。そのせいでCache.Insertメソッドは複雑に見えます。上の例では次の構文のメソッドを使用しています。

Insert(key As String, value As Object, dependencies As CacheDependency, _
    absoluteExpiration As DateTime, slidingExpiration As TimeSpan)

 引数keyvalueの意味はすぐに分かるでしょう。keyはキャッシュするデータの識別情報で、valueはキャッシュする実際のデータです。dependenciesは、キャッシュを別のオブジェクト(通常はファイル)に依存させる場合に使用します。今回は使用していないのでNothingです。absoluteExpirationでは、キャッシュの期限を指定します。上の例では、キャッシュ後15分でデータを期限切れにするように設定してあります。slidingExpirationは、一定期間使われない場合に限ってキャッシュからデータを削除するよう指示するものです。キャッシュが使われるたびにリセットされるカウントダウンタイマのようなものです。リセットされずにゼロになったとき初めてキャッシュが削除されます。

 CacheオブジェクトのInsertメソッドの詳細については、MSDNドキュメントのCache.Insertメソッドの説明を参照してください。このメソッドはオーバーロードされ、今回の例では第3版(有効期限を設定できるバージョン)を使用しています。

 キャッシュ版のスクリプトを実行すると、サイト「15 Seconds」のRSSフィードが再び表示されます。今回は、更新しても一番下のタイムスタンプは変化しません。毎回新しいデータを取得するのではなく、キャッシュされたデータを表示しているからです。しかし、15分待ってからページを更新すると、新しいタイムスタンプが取得され、次の15分間はこれが返されます。

結論

 ASP.NETではオブジェクトを簡単にキャッシュできることが分かりました。この強力な組み込みキャッシュ機能をいろいろな場面で使うとよいと思いますが、中でもHTTP要求については、ぜひこれでキャッシュすることをお勧めします。サイトが高速になるだけでなく、ネットワークトラフィックが削減され、リモートサーバの負荷も減ります。さて、残る問題はキャッシュの有効期限をどれくらいに設定するかです。これはキャッシュの内容に依存し、キャッシュごとに変化しますが、1分程度キャッシュするだけでも多忙なサイトでは大きな効果があります。

著者紹介

John Peterson(John Peterson)
関連テーマ
最新トップニュース
データメーション
【データメーション】
OSについて気に入らないこと(9月5日)
ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」
【ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」】
「導入期〜成長期へ!一歩一歩と前進を目指す『Annoii(アノイ)』」/maka hou,Inc.(9月5日)
最新テクノロジーの意外な処方箋
【最新テクノロジーの意外な処方箋】
グリッドコンピューティング技術でETに遭遇(9月5日)
Graphic Design Forum
【Graphic Design Forum】
古い Emigre を探して (9月3日)
エンジニアの独り言
【エンジニアの独り言】
データをローカルに保存するWebアプリケーション(8月22日)
デスマーチからの脱却
【デスマーチからの脱却】
30min. iPhoneアプリリリース(8月18日)
最新ハイテク講座
最新ハイテク講座
なぜ勝った? 世界No.1シェアをつかんだ“Windows”(9月5日)
developer.com
developer.com
デザインパターンの使い方: Composite(9月5日)
最新アフィリエイト事例にみる成功の法則
最新アフィリエイト事例にみる成功の法則
コンバージョンレートを高めよう!(9月5日)
百式のネットビジネス研究
百式のネットビジネス研究
ガジェット購入時に将来の買取保証プランを提供する「TechForward」(9月5日)
週刊-サイト別アクセス状況データ
週刊-サイト別アクセス状況データ
ビデオリサーチインタラクティブ調査(月間インターネットオーディエンスデータ)(9月4日)
「IT の耳」
「IT の耳」
【書評】『検索にガンガンヒットさせる SEO の教科書』――SEO テクニックで効果的に PR する(9月4日)
検索エンジンマーケティング
検索エンジンマーケティング
果たしてモバイル SEO は必要なのか?(9月4日)
Eメールマーケティング事情
Eメールマーケティング事情
読者が迷惑メールと認識する時…(9月3日)
日本と韓国のインターネットビジネス最新動向調査
日本と韓国のインターネットビジネス最新動向調査
日本と韓国の動画サイト比較1―現状(9月3日)
SNSをビジネスに活用しよう
SNSをビジネスに活用しよう
「しまじろう」に学ぶ企業内コミュニティの活性化のポイント(9月2日)
海外のインターネットコムアメリカ韓国ドイツトルコ
Copyright 2008 Jupitermedia Corporation All Rights Reserved.http://www.internet.com/