以下、実施形態について、図面を参照しながら詳細に説明する。まず、図1〜7を参照して、第1実施形態と第2実施形態の共通点について説明する。次に、「iframeストリーミング」または「HTTP(Hypertext Transfer Protocol)ストリーミング」と呼ばれる技術を利用する第1実施形態について、図8〜11を参照して説明する。続いて、「ロングポーリング(long polling)」と呼ばれる技術を利用する第2実施形態について、図12〜16を参照して説明する。その後、その他の変形例について、図17〜19を参照して説明する。
図1は、第1実施形態と第2実施形態に共通のシステム構成図である。図1のシステムは、Webサーバ100とクライアントマシン110とDBサーバ120を含む。Webサーバ100は、換言すれば、アプリケーションサーバである。
また、ファイアウォール130が、クライアントマシン110とDBサーバ120の属するイントラネット140を、外部からの不正なアクセスから保護する。なお、図面では紙幅の都合上、「ファイアウォール」を“F/W”と表記する。
以下では、ファイアウォール130によってイントラネット140と隔てられたネットワークを、「外部ネットワーク150」という。換言すれば、外部ネットワーク150は、イントラネット140の外部のネットワークであり、クライアントマシン110やDBサーバ120にとっては、インターネット側のネットワークである。
具体的には、外部ネットワーク150は、例えば、インターネットを介してイントラネット140と接続された他のイントラネットであってもよい。Webサーバ100は外部ネットワーク150に属する。
例えば、イントラネット140は、ある企業のイントラネットでもよい。また、外部ネットワーク150は、Webサービスを提供するSaaS(Software as a Service)ベンダあるいはASP(Application Service Provider)のイントラネットでもよい。
Webサーバ100は、HTTPサーバソフトウェアがインストールされたサーバマシンであり、Webアプリケーション101を実行する。他方、クライアントマシン110はブラウザ111を実行する。また、DBサーバ120は、Webアプリケーション101が処理に用いる各種のデータを格納するDB121を有する。
Webサーバ100は、DBインタフェイス部102と振り分け部103を含み、振り分け部103はスクリプト生成部104を含む。そして、Webサーバ100は、対応表105と設定ファイル106を記憶している。対応表105と設定ファイル106の具体例は、図2とともに後述する。
Webサーバ100は、Webアプリケーション101を実行するだけでなく、DBアクセスの流れを制御するサーバサイドの制御装置としても動作する。換言すれば、DBインタフェイス部102と振り分け部103(スクリプト生成部104を含む)は、対応表105と設定ファイル106を用いて、制御装置の少なくとも一部として動作する。
DBインタフェイス部102は、Webアプリケーション101に対してDBアクセスのためのインタフェイスを提供する。振り分け部103は、Webアプリケーション101からDB121へのアクセスを中継するために、ブラウザ111からの要求に応じた処理と、DBインタフェイス部102からの要求に応じた処理を行う。振り分け部103の具体的な動作は実施形態に応じて様々に異なるので、振り分け部103についての詳細は、図8〜16とともに後述する。
ブラウザ111が表示するページは、Webアプリケーション101のページを表示するためのインラインフレーム112と、ブラウザ111とWebサーバ100との間のCometコネクションを維持するためのインラインフレーム113を含む。なお、以下では表記の簡略化のため、HTML(HyperText Markup Language)のタグ名を用いて、「インラインフレーム」を単に“iframe”と表記する。
具体的には、iframe113には、DBアクセス代行スクリプト114を含むソースコードが読み込まれる。DBアクセス代行スクリプト114は、Webサーバ100がクライアントマシン110にDB121へのアクセスを代行させるためのスクリプトである。DBアクセス代行スクリプト114は、スクリプト生成部104により生成され、振り分け部103からブラウザ111に送られる。
DBアクセス代行スクリプト114は、例えばJavaScript(登録商標)などのスクリプト言語で書かれたスクリプトである。DBアクセス代行スクリプト114は、1つの<script>ブロックに含まれていてもよいし、iframe113に読み込まれるソースコード内の複数の<script>ブロックに分散していてもよい。
上記のとおり、振り分け部103の具体的な動作は実施形態に応じて様々に異なるが、振り分け部103の動作の概要を説明すれば以下のとおりである。
振り分け部103は、クライアントマシン110から(より具体的にはブラウザ111から)、Webサーバ100上の特定のパスへのアクセスを求める要求(以下「特定要求」という)を受け付ける。そして、振り分け部103は、クライアントマシン110(より具体的にはクライアントマシン110上のブラウザ111)とWebサーバ100との間のコネクションを、特定要求の受付を契機として確立する。
確立されるコネクションは、具体的にはHTTPコネクションであり、より詳細にはTCP(Transmission Control Protocol)コネクション上のHTTPコネクションである。また、確立されたコネクションは、擬似的なサーバプッシュの実現のために使われるので、用途の観点からは「Cometコネクション」とも呼ばれる。
上記の特定のパスは、「Webアプリケーション101によっては使用されない」と予め決められて、予約されている、特殊なパスである。
例えば、Webアプリケーション101が、“http://www.foo.com/”配下のパスで提供されるとする。また、「Webサーバ100のドキュメントルートのディレクトリ内で、アンダスコアから始まるパスは、Webアプリケーション101によっては使用されない」と予め決められているとする。
すると、例えば“/_reservedForComet”というパスが、上記の特定のパスとして利用可能である。この場合、特定要求は、“http://www.foo.com/_reservedForComet”というURI(Uniform Resource Identifier)がリクエストURIとして指定されたHTTP要求であってもよい。つまり、特定要求は、ブラウザ111が、特定のパスにより指定されるページをiframe113に読み込もうとする要求であってもよい。
あるいは、ブラウザ111がiframe113内に読み込んだDBアクセス代行スクリプト114が、XHR(XMLHttpRequest)オブジェクトを用いて特定のパスを含むURIに対してHTTP要求を送信するためのコードを含んでいてもよい。この場合、特定要求は、具体的には、XHRオブジェクトを用いた、特定のパスを含むURIに対するHTTP要求である。もちろん、特定要求は、XHRオブジェクト以外の実装による非同期通信によって実現されてもよい。
詳しくは後述するが、特定要求が上記2通りのいずれであっても、振り分け部103が特定要求の受付を契機として確立したコネクションは、iframe113を用いてブラウザ111とWebサーバ100の間で維持される。維持されるコネクションを介して擬似的なサーバプッシュを実現することが可能である。
このように擬似的なサーバプッシュを実現するために維持されるコネクションは「Cometコネクション」とも呼ばれる。“Comet”は、擬似的なサーバプッシュを実現する技法の総称である。
さて、振り分け部103は、ブラウザ111からの要求を受け付けるだけでなく、DBインタフェイス部102からの要求も受け付ける。
具体的には、DBインタフェイス部102は、Webアプリケーション101がDB121へのアクセスを求める要求(以下「DBアクセス要求」という)をWebアプリケーション101から受け付ける。そして、DBインタフェイス部102は、受け付けたDBアクセス要求を振り分け部103に出力する。つまり、Webアプリケーション101からのDBアクセス要求は、DBインタフェイス部102を介して振り分け部103に中継され、振り分け部103において受け付けられる。
振り分け部103は、以上のようにしてDBインタフェイス部102から受け付けたDBアクセス要求にしたがったDB121へのアクセスを、クライアントマシン110のブラウザ111に代行させるため、スクリプトを送信する。ここで送信されるスクリプトを、以下では説明の便宜上「実行命令スクリプト」ともいう。
実行命令スクリプトは、具体的には、DBアクセス代行スクリプト114の少なくとも一部である。また、実行命令スクリプトは、振り分け部103の指示にしたがってスクリプト生成部104により生成され、振り分け部103からブラウザ111に送信される。
具体的には、実行命令スクリプトは、次のような処理(説明の便宜上「代行処理」ともいう)をクライアントマシン110(具体的にはブラウザ111)に実行させるためのスクリプトである。すなわち、代行処理は、上記のDBアクセス要求にしたがってDB121にアクセスし、DBアクセス結果をDB121から取得し、Webサーバ100にDBアクセス結果を送信する処理である。
なお、振り分け部103は、DBアクセス要求を含む実行命令スクリプトをスクリプト生成部104に生成させてもよい。そして、振り分け部103は、DBアクセス要求を含む実行命令スクリプトを、上記のとおり維持されているコネクションを介して、ブラウザ111に送信してもよい。あるいは、振り分け部103は、上記のとおり維持されているコネクションを介して、DBアクセス要求を、実行命令スクリプトとは別に、ブラウザ111に送信してもよい。
いずれにしろ、維持されているコネクションを介して、DBアクセス要求が、Webサーバ100からクライアントマシン110に擬似的にプッシュされる。そして、振り分け部103は、DBアクセス要求をクライアントマシン110(具体的にはブラウザ111)に送信することで、クライアントマシン110(具体的にはブラウザ111)に代行処理を実行させる。換言すれば、クライアントマシン110のブラウザ111は、振り分け部103からのDBアクセス要求の受信を契機として、代行処理を実行する。
そして、DBアクセス要求の受信を契機としてブラウザ111が代行処理を実行すると、DBアクセス結果がWebサーバ100に送信される。すると、振り分け部103が、DBアクセス結果を受信する。
振り分け部103は、受信したDBアクセス結果をDBインタフェイス部102に出力する。すると、DBインタフェイス部102は、振り分け部103から取得したDBアクセス結果をWebアプリケーション101に出力する。その結果、Webアプリケーション101は、DBアクセス結果を利用した処理(例えば、動的なHTMLページの生成)を行うことができる。
以上のとおり、図1のシステムによれば、インタフェイス・サーバ、中間システム、中継サーバなどの付加的な装置は不要である。それにもかかわらず、図1のシステムによれば、ファイアウォール130によってWebサーバ100とは隔てられたイントラネット140内に保持されるDB121を用いた処理を、Webアプリケーション101が行うことができる。
したがって、図1のシステムによれば、ユーザは、外部ネットワーク150にDB121を保存することによる情報漏洩などを懸念することなく、Webアプリケーション101を利用することができる。
もちろん、Webアプリケーション101は、一時的にDB121のデータの一部を記憶する。例えば、Webアプリケーション101は、DB121に追加するための新たなデータをブラウザ111から受け取り、受け取ったデータをメモリに記憶するかもしれない。あるいは、Webアプリケーション101は、動的にページを生成するために、DB121の既存のデータをDBインタフェイス部102から受け取り、受け取ったデータをメモリに記憶するかもしれない。
しかしながら、Webアプリケーション101は、一時的に利用したデータを外部ネットワーク150内に恒久的に蓄積することはない。換言すれば、Webアプリケーション101によるデータの利用は、部分的かつ揮発的であり、不揮発的にDB121全体の内容が外部ネットワーク150に保存されることはない。よって、外部ネットワーク150からの情報漏洩のリスクは非常に低く、ほとんどゼロと見なしてさしつかえない。したがって、図1のシステムは、ユーザが「外部には秘密にしたい」と考えるデータがDB121に含まれる場合にも、好適である。
さて、図2は、対応表105と設定ファイル106の例を示す図である。対応表105は、コネクションの管理のために使われ、動的に書き換えられる。また、設定ファイル106は、スクリプト生成部104がDBアクセス代行スクリプト114に埋め込む値が予め設定された、静的なファイルである。
図2の対応表105aは、図1の対応表105の具体例である。対応表105aは、1つまたは複数のエントリを含む。各エントリは、セッションを識別するセッションID(identification)と、Cometコネクションを識別するコネクションIDを対応づける。
図2の対応表105aでは、セッションID「A1」とコネクションID「B1」が対応づけられている。同様に、対応表105aでは、セッションID「A2」とコネクションID「B2」が対応づけられており、セッションID「A3」とコネクションID「B3」が対応づけられている。
セッションIDは、Webサーバ100(より具体的には振り分け部103)が、新規セッションを生成するときに発行するIDである。セッションIDは、十分な長さを持つランダムな値であることが望ましい。
コネクションIDは、Cometコネクションを識別することの可能な情報であれば何でもよい。例えば、コネクションIDは、ファイルディスクリプタのIDでもよいし、ハンドルを指すポインタであってもよい。コネクションIDの形式は、Webサーバ100のOS(Operating System)に依存し得る。
なお、振り分け部103が、後述のフローチャートにしたがって対応表105へのエントリの追加と削除を行う。振り分け部103はさらに、セッションタイムアウトが生じると、タイムアウトしたセッションのセッションIDを含むエントリを対応表105から削除してもよい。
また、図2の設定ファイル106aは、図1の設定ファイル106の具体例である。設定ファイル106の他の例については、図17とともに後述する。設定ファイル106aは、ブラウザ111からDBサーバ120にアクセスするためのアドレスを示す「DBアドレス」という項目を含む。
図1に示すとおり、ブラウザ111を実行するクライアントマシン110とDBサーバ120は、同じイントラネット140に属する。したがって、ブラウザ111は、“192.168.123.45”というプライベートIP(Internet Protocol)アドレスを用いてDBサーバ120にアクセスすることができる。
なお、DBサーバ120は、イントラネット140内の他のコンピュータからのDB121へのアクセス要求を、具体的にはHTTPを介して受け付ける。よって、設定ファイル106aには、DBアドレスとして“http://192.168.123.45/”という、イントラネット140内のプライベートIPアドレスを含むURIが設定されている。
なお、DBサーバ120のインタフェイスに応じて、設定ファイル106に設定されるDBサーバ120のアドレスの形式は任意に変更可能である。例えば、プライベートIPアドレスの代わりにFQDN(Fully-Qualified Domain Name)を用いたURIが使われてもよい。また、DBサーバ120のURIがポート番号を含んでもよい。
次に、図1のシステムの利点を明らかにするため、図3を参照して比較例について説明する。図3は、比較例のシステム構成図である。
図3のクライアントマシン110は、図1と同様に、ブラウザ111を実行する。また、クライアントマシン110は、図1と同様に、ファイアウォール130によって外部ネットワーク150と隔てられたイントラネット140に属する。
また、図3の比較例では、外部ネットワーク150内にWebサーバ160とDBサーバ170がある。Webサーバ160は、Webアプリケーション101を実行する点では図1のWebサーバ100と同様である。また、DBサーバ170は、図1のDBサーバ120が保持するのと同様のDB121を保持する。なお、図3において、DBサーバ170がWebサーバ160と同じ外部ネットワーク150内にある理由は、Webサーバ160がファイアウォール130越しにイントラネット140内のコンピュータにアクセスすることはできないためである。
図3の比較例において、Webアプリケーション101は、DBライブラリ161を介してDBサーバ170上のDB121にアクセスする。換言すれば、DBライブラリ161は、Webアプリケーション101に対して、DBアクセス用のAPI(Application Programming Interface)を提供する。
以上のようなシステム構成の図3の比較例における、ブラウザ111とWebアプリケーション101の動作は、次のとおりである。
ブラウザ111が、DB121のデータを用いた動的なページを要求した場合、または、DB121に対するデータの追加、削除、もしくは更新を要求した場合、Webアプリケーション101は、DBライブラリ161を介してDB121にアクセスする。そして、Webアプリケーション101は、DBライブラリ161を介して、データの参照、追加、削除、または更新を行う。
Webアプリケーション101は、DB121へのアクセス結果に応じて、適宜のページを動的に生成してブラウザ111に返すか、または静的に記憶されたページをブラウザ111に返す。すると、ブラウザ111は、Webアプリケーション101から返されたページをディスプレイ上に表示する。
ここで、仮にDB121に格納されるデータが、ユーザにとって秘密にしたいデータ(以下「機密情報」ともいう)であるとする。例えば、企業ユーザにとっての機密情報の例は、顧客情報などである。
ユーザは、「イントラネット140の外部に機密情報を保存したくない」と考えるかもしれない。また、ユーザは、「外部ネットワーク150から機密情報が漏洩するかもしれない」と心配するかもしれない。その結果、ユーザは、Webアプリケーション101を利用しないことに決定するかもしれない。
すなわち、図3の比較例のようなシステムでは、「DB121がイントラネット140の外部に保存されている」という事実が、Webアプリケーション101の利用促進を阻害する要因として働く。他方、図1の実施形態によれば、DB121はイントラネット140の内部にある。つまり、図1の実施形態では、図3の比較例と比べて、機密情報を扱うWebアプリケーション101の利用をユーザが躊躇する要因が、1つ解消されている。したがって、図1の実施形態は、Webアプリケーション101の利用促進のために効果的である。
しかも、図1の実施形態は、Webサーバ100とクライアントマシン110とDBサーバ120のほかの付加的な装置を必要としない。
例えば、図3の比較例を変形して、DBサーバ170を外部ネットワーク150からイントラネット140に移そうとすると、1つの解決策として、一種の「トンネル」機構が考えられる。
具体的には、イントラネット140と外部ネットワーク150にそれぞれ中継サーバが設けられてもよい。2台の中継サーバが、ファイアウォール130を超えた中継サーバ間のコネクションを維持することにより、当該コネクションを介しての、Webアプリケーション101からイントラネット140内のDB121へのアクセスが可能となる。
他方、図1の実施形態は、例えば上記の2台の中継サーバのような付加的な装置を必要としない。そして、付加的な装置を必要としないことは、Webアプリケーション101の導入と運用における手間と金銭的コストを下げる効果がある。つまり、付加的な装置が不要な図1の実施形態は、保守性(serviceability)の観点においても、金銭的コストの観点においても、優れている。
さらに、付加的な装置が必要なシステムにおいては、付加的な装置がシステム全体のSPoF(Single Point of Failure)になるおそれがある。つまり、たとえWebサーバ160とクライアントマシン110が正常でも、付加的な装置が故障することにより、Webアプリケーション101が利用不能になるおそれがある。したがって、付加的な装置が不要な図1の実施形態は、可用性の観点においても優れている。
また、図1の実施形態は、上記のような2台の中継サーバを含むシステムと比べて、セキュリティの面でも優れている。なぜなら、図1のシステムでは、特定要求の受付を契機として確立されたコネクションは、ユーザがブラウザ111を終了すると、切れるからである。
それに対して、2台の中継サーバを用いるシステムにおいては、ブラウザ111の終了後も、2台の中継サーバ間のコネクションが残る。すると、実際にはブラウザ111がWebアプリケーション101を利用していない状況下においても、中継サーバ間のコネクションを介して、Webサーバ160からイントラネット140内のDB121へのアクセスが可能となる。
そして、必要以上のアクセスを許容することは、セキュリティ上、好ましくない。例えば、まれに、Webアプリケーション101とは別のマルウェアがWebサーバ160にインストールされるおそれがある。すると、ブラウザ111の終了後も残っている2台の中継サーバ間のコネクションを介して、マルウェアがイントラネット140内のDB121にアクセスするおそれがある。
したがって、ブラウザ111の終了にともなってコネクションが切れる図1の実施形態は、2台の中継サーバを含むシステムと比べて、セキュリティの面でも優れている。
さらに、図1のシステムは、2台の中継サーバを含む上記システムと比べて、リソースの利用効率の面でも優れている。なぜなら、2台の中継サーバを用いるシステムにおいては、ブラウザ111の終了後も、2台の中継サーバ間のコネクションが残り、結果として、必要以上にネットワークリソースおよびWebサーバのリソースが消費されてしまうからである。
なお、図1のDBインタフェイス部102がWebアプリケーション101に対して提供するインタフェイスは、図3のDBライブラリ161がWebアプリケーション101に対して提供するインタフェイスと同じであってもよい。換言すれば、DBインタフェイス部102は、Webアプリケーション101から利用可能なライブラリの形で実装されてもよい。
すると、図3のようなシステムで使われているWebアプリケーション101のソースコードを変更しなくても、図3のシステムを図1のシステムのように変更することが可能となる。つまり、既存のWebアプリケーション101のソースコードが有効に活用される。
ところで、図1のWebサーバ100とクライアントマシン110とDBサーバ120は、いずれも、例えば図4に例示するようなコンピュータであってもよい。図4は、コンピュータのハードウェア構成図である。
図4のコンピュータ200は、CPU201(Central Processing Unit)とメモリ202とネットワーク接続装置203と入力装置204と出力装置205と記憶装置206と駆動装置207を有する。また、コンピュータ200内の各部は、バス208を介して互いに接続されている。
CPU201は、プログラムをメモリ202にロードし、メモリ202をワークエリアとして用いながら、プログラムを実行する。メモリ202は、例えばDRAM(Dynamic Random Access Memory)である。
プログラムは、記憶装置206に予め格納されていてもよい。あるいは、プログラムは、ネットワーク接続装置203を介してネットワーク220からダウンロードされ、記憶装置206にコピーされてもよい。
または、プログラムは、可搬型記憶媒体210に格納されて提供され、駆動装置207により読み取られてもよい。駆動装置207により可搬型記憶媒体210から読み取られたプログラムは、直接メモリ202にロードされてもよいし、一旦記憶装置206にコピーされ、記憶装置206からメモリ202にロードされてもよい。可搬型記憶媒体210としては、CD(Compact Disc)やDVD(Digital Versatile Disc)などの光ディスク、光磁気ディスク、磁気ディスク、不揮発性の半導体メモリカードなどが利用可能である。
また、ネットワーク接続装置203は、ネットワーク220を介した通信を行うための通信インタフェイス装置である。ネットワーク接続装置203は、例えば、有線LAN(Local Area Network)インタフェイス装置、無線LANインタフェイス装置、またはその組み合わせである。
入力装置204は、例えば、キーボード、マウスやタッチスクリーンなどのポインティングデバイス、マイク、またはそれらの組み合わせである。出力装置205は、例えば、ディスプレイ、スピーカ、またはそれらの組み合わせである。ディスプレイは、タッチスクリーンであってもよい。
記憶装置206は、不揮発性の記憶装置であり、例えば、ROM(Read Only Memory)やフラッシュメモリなどの半導体メモリ、ハードディスク装置、またはそれらの組み合わせである。なお、メモリ202、記憶装置206、および可搬型記憶媒体210は、いずれも、コンピュータ読み取り可能な記憶媒体の例である。これらのコンピュータ読み取り可能な記憶媒体は、有形の(tangible)記憶媒体であり、信号搬送波のような一時的な(transitory)媒体ではない。
ところで、図1のWebサーバ100が図4のコンピュータ200である場合、Webアプリケーション101は、CPU201が実行するプログラムのうちの1つである。また、DBインタフェイス部102、振り分け部103、およびスクリプト生成部104は、CPU201がプログラムを実行することにより実現される。
また、Webアプリケーション101は、ネットワーク接続装置203による通信機能を利用する。そして、振り分け部103の通信機能は、ネットワーク接続装置203によって実現される。
また、Webサーバ100がコンピュータ200である場合、ネットワーク220は、具体的には、Webサーバ100が属する外部ネットワーク150を含む。さらに、ネットワーク220は、外部ネットワーク150と直接的または間接的に接続された他のネットワーク(例えば、インターネットやイントラネット140)も含む。
対応表105は、メモリ202に格納されるが、対応表105の一部が記憶装置206に格納されてもよい。設定ファイル106は、不揮発性の記憶装置206に格納される。
また、図1のクライアントマシン110が図4のコンピュータ200である場合、ブラウザ111は、CPU201が実行するプログラムのうちの1つである。そして、ブラウザ111上で実行されるDBアクセス代行スクリプト114も、CPU201が実行するプログラムのうちの1つである。
また、iframe112内に読み込まれたコンテンツは、ブラウザ111のレンダリング機能によってディスプレイ(すなわち出力装置205)上に表示される。iframe113内に読み込まれたコンテンツも、同様にして出力装置205上に表示されてもよい。しかし、後述のとおりiframe113は不可視であってもよく、その場合、iframe113内に読み込まれたコンテンツは、出力装置205上に表示されない。
なお、ブラウザ111の通信機能は、ネットワーク接続装置203により実現される。DBアクセス代行スクリプト114にしたがって行われる、クライアントマシン110とDBサーバ120の間の通信およびクライアントマシン110とWebサーバ100の間の通信も、具体的には、ネットワーク接続装置203により実現される。
また、クライアントマシン110がコンピュータ200である場合、ネットワーク220は、具体的には、クライアントマシン110が属するイントラネット140を含む。さらに、ネットワーク220は、イントラネット140に直接的または間接的に接続された他のネットワーク(例えば、インターネットや外部ネットワーク150)も含む。
また、図1のDBサーバ120が図4のコンピュータ200である場合、DB121は、記憶装置206に格納される。そして、DBサーバ120とクライアントマシン110の間の通信は、ネットワーク接続装置203により実現される。DBサーバ120がコンピュータ200である場合、ネットワーク220は、具体的には、DBサーバ120が属するイントラネット140を少なくとも含む。
続いて、図5を参照して、ブラウザ111によるDBアクセスの代行について説明する。図5は、DBアクセス代行スクリプト114にしたがってブラウザ111が実行する処理のフローチャートである。
ステップS101でブラウザ111は、Webサーバ100からDBアクセス要求を受信するまで待つ。DBアクセス要求は、具体的には、<script>ブロック内のステートメントの形で、Webサーバ100の振り分け部103から送信されることもある。あるいは、DBアクセス要求は、ブラウザ111が過去にXHRオブジェクトを使って送信したHTTP要求に対するHTTP応答の形で、振り分け部103から送信されることもある。
ブラウザ111が振り分け部103からDBアクセス要求を受信すると、処理はステップS102に移行する。なお、参照の便宜のため、図5には「DBアクセス要求到着」というガード条件も記載されている。他のフローチャートでも同様に、参照の便宜のため、適宜ガード条件が記載されている。
ステップS102でブラウザ111は、DBアクセス代行スクリプト114にしたがって、イントラネット140内のDBサーバ120にDBアクセス要求を送信する。
例えば、DBサーバ120は、イントラネット140内のクライアントマシン110がHTTPを介してDB121にアクセスするためのインタフェイスを提供してもよい。この場合、DBアクセス代行スクリプト114は、XHRオブジェクトを用いてHTTPを介してDBサーバ120にDBアクセス要求を送信する処理を、ブラウザ111に実行させるためのコードを含んでもよい。
なお、DBアクセス代行スクリプト114は、外部ネットワーク150のWebサーバ100で生成されたスクリプトである。そして、外部ネットワーク150とイントラネット140のドメインは異なる。
よって、同一生成元ポリシ(same origin policy)によりクロスドメインの要求が許されない場合、ブラウザ111がDBアクセス代行スクリプト114を実行することによりイントラネット140内のDBサーバ120に要求を送信することは、許されない。しかし、XHRのレベル2の仕様では、DBサーバ120が許可すればクロスドメインの要求が可能になっている。よって、レベル2のXHRを用いることにより、ブラウザ111は、DBアクセス代行スクリプト114を実行することでDBサーバ120にDBアクセス要求を送信することが可能である。
さて、ステップS102でDBアクセス要求を送信した後、ブラウザ111は、ステップS103で、イントラネット140内のDBサーバ120からDBアクセス結果を受信するまで待つ。そして、ブラウザ111がDBサーバ120からDBアクセス結果を受信すると、処理はステップS104に移行する。
例えば、DBアクセス要求が、データの追加、更新、または削除を求める要求である場合、DBアクセス結果は、具体的には、「成功」または「エラー」を示す制御情報であってもよい。逆に、DBアクセス要求がデータの参照を求める要求である場合、DBアクセス結果は、要求されたデータ自体であるか、または「エラー」を示す制御情報である。
また、DBアクセス結果の具体的なデータフォーマットは、実施形態に応じて任意である。DBアクセス結果は、例えば、JSON(JavaScript Object Notation)、CSV(Comma Separated Values)、XML(Extensible Markup Language)などによって適宜に表現されていてよい。
さて、ステップS104でブラウザ111は、Webサーバ100に、DBサーバ120から受信したDBアクセス結果を送信する。ステップS104での送信も、例えば、XHRオブジェクトにより実現可能である。また、DBアクセス結果の具体的な送信先のURIは、DBアクセス代行スクリプト114内に指定されている。
ステップS104での送信後、処理はステップS101に戻る。したがって、Webアプリケーション101があるページを動的に生成するために複数のDBアクセス要求を発行する場合であっても、Webアプリケーション101は、各DBアクセス要求に対するDBアクセス結果を得ることができる。また、Webアプリケーション101の複数のページが次々に呼び出される場合であっても、Webアプリケーション101は、各ページの各DBアクセス要求に対するDBアクセス結果を得ることができる。
続いて、図6のフローチャートを参照して、DBインタフェイス部102の動作を説明する。
ステップS201でDBインタフェイス部102は、Webアプリケーション101からDBアクセス要求を受け取るまで待つ。例えば、DB121がリレーショナルDBの場合、DBアクセス要求は、SQL文(Structured Query Language statement)として表される。よって、DBインタフェイス部102は、Webアプリケーション101からSQL文を受け取るまで待つ。
DBインタフェイス部102がWebアプリケーション101からDBアクセス要求を受信すると、処理はステップS202に移行する。そして、ステップS202でDBインタフェイス部102は、Webアプリケーション101から受け取ったDBアクセス要求を振り分け部103に出力する。
そして、次のステップS203でDBインタフェイス部102は、振り分け部103からDBアクセス結果を受け取るまで待つ。そして、DBインタフェイス部102が振り分け部103からDBアクセス結果を受け取ると、処理はステップS204に移行する。
ステップS204でDBインタフェイス部102は、振り分け部103から受け取ったDBアクセス結果をWebアプリケーション101に返す。そして、処理はステップS201に戻る。
以上のようにDBインタフェイス部102がステップS201〜S204の処理を繰り返すことにより、Webアプリケーション101は、複数のDBアクセス要求を発行する場合であっても、各DBアクセス要求に対するDBアクセス結果を得ることができる。
続いて、図7のフローチャートを参照して、スクリプト生成部104の動作を説明する。
まず、ステップS301でスクリプト生成部104は設定ファイル106からDBサーバ120のアドレスを読み取る。なお、DBサーバ120に実際にアクセスするのは、DBサーバ120と同じイントラネット140内にあるクライアントマシン110上のブラウザ111である。したがって、スクリプト生成部104自体は、ステップS301で読み取ったアドレスへのアクセスが禁止されていても、全く問題ない。
ステップS301の読み取りの後、処理はステップS302に移行する。そして、ステップS302でスクリプト生成部104は、振り分け部103からスクリプトの生成指示を受け取るまで待つ。
スクリプト生成部104がスクリプトの生成指示を振り分け部103から受け取ると、処理はステップS303に移行する。そして、ステップS303でスクリプト生成部104は、生成指示にしたがって適宜スクリプトを生成する。ステップS303で生成されるスクリプトは、DBアクセス代行スクリプト114の一部または全部である。
また、生成指示の内容に応じて、DBアクセス代行スクリプト114は、ステップS301で読み取ったDBサーバ120のアドレスを、ステップS303でスクリプトの中に埋め込むこともある。逆に、生成指示の内容によっては、スクリプト生成部104は、ステップS303ではDBサーバ120のアドレスを使わないこともある。
そして、次のステップS304でスクリプト生成部104は、ステップS303で生成したスクリプトを振り分け部103に返す。その後、処理はステップS302に戻る。
以上、図1〜7を参照して第1実施形態と第2実施形態の共通点について説明した。続いて、第1実施形態と第2実施形態それぞれの詳細を説明する。
第1実施形態では、「iframeストリーミング」または「HTTPストリーミング」と呼ばれる技術がCometコネクションの維持のために使われる。具体的には、iframe113内には、チャンク(chunked)形式のデータが読み込まれる。
つまり、iframe113へのページ読み込みのためのブラウザ111からのHTTP要求に対して、振り分け部103は、Transfer−Encodingヘッダフィールドに“chunked”と指定して、HTTP応答を返す。チャンク形式のHTTP応答のメッセージボディは、任意の個数のチャンクに分けて送信される。チャンクサイズがゼロと指定されるまで、メッセージボディは完了しないので、コネクションは維持される。
第1実施形態では、上記のようにして維持されるCometコネクション(換言すればHTTPコネクション)上で、振り分け部103がDBアクセス要求をブラウザ111に送信する。以下ではより具体的に第1実施形態について説明する。
図8は、UML(Unified Modeling Language)で表した、第1実施形態の一動作例に関するシーケンス図である。また、図9は、第1実施形態でブラウザ111に送信されるソースコードの例を示す図である。
図8のステップS401でブラウザ111は、Webサーバ100に対する初回の要求を送信する。
以下では説明の便宜上、Webアプリケーション101のトップページのURIが、“http://www.foo.com/”であるとする。ユーザは、Webアプリケーション101を利用するために、“http://www.foo.com/”というURIにアクセスするよう、クライアントマシン110の入力装置を操作する。この例では、ステップS401でブラウザ111から送信される要求は、URIとして“http://www.foo.com/”が指定されたHTTP要求である。
Webサーバ100においては、振り分け部103が、ステップS401の要求を受信する。そして、ステップS402で振り分け部103は、新たなセッションを生成し、iframe112とiframe113を要素として指定するページを返す。
なお、以下では説明の便宜上、iframe112とiframe113を要素として含むページを「親ページ」ともいう。また、iframe112とiframe113内にそれぞれ読み込まれるページを「子ページ」ともいう。
図9には、親ページと子ページのソースコードの具体例が示されている。上記のステップS402で返される親ページは、例えば図9の親ページ300である。親ページ300は、<iframe>ブロック301と<iframe>ブロック302を含む。
図9の<iframe>ブロック301は、ブラウザ111に、iframe112の中にWebアプリケーション101のページを表示させるためのHTMLソースコードの例である。また、<iframe>ブロック301は、iframe112の幅と高さがそれぞれ400ピクセルと600ピクセルであること、および、iframe112に読み込む対象のソースの相対URIが“/”であることを示している。
他方、<iframe>ブロック302は、図1に関して説明した「特定のパス」をiframe113のソースとして指定するHTMLソースコードである。換言すれば、<iframe>ブロック302は、図1に関して説明した「特定要求」をブラウザ111に行わせるためのHTMLソースコードである。
なお、図9の例では、<iframe>ブロック302において“src”属性の値が相対パス形式で“/_reservedForComet”と指定されている。よって、Webアプリケーション101のトップページのURIが“http://www.foo.com/”だとすると、特定のパスへアクセスするためのURIは、“http://www.foo.com/_reservedForComet”である。
また、<iframe>ブロック302は、iframe113の幅と高さがいずれも1ピクセルであることを示している。したがって、ブラウザ111のユーザは、ブラウザ111の画面を見ても、iframe113の存在を視認することができない。ユーザは、単にWebアプリケーション101のページだけがブラウザ111に表示されているかのように認識するであろう。
このように、iframe113を実質的に不可視に設定することにより、ユーザの利便性を損なうことなく、イントラネット140内のDB121の利用が可能となる。つまり、iframe113を実質的に不可視に設定することにより、ユーザに「Webアプリケーション101がどこのDBのデータを使うのか」ということを意識させない、透過的なサービスが実現される。
なお、iframe113を実質的に不可視にするためには、<iframe>ブロック302に例示されるように、幅と高さを微小な値(例えば1ピクセルなど)に設定してもよく、“type”属性の値を“hidden”と指定してもよい。
ここで、図8の説明に戻る。ステップS402で親ページ300を受信したブラウザ111は、親ページ300のソースコードから、「親ページ300が2つのiframeを含む」ということを認識する。
なお、図9の親ページ300のようなHTMLソースコードを読み込んだブラウザ111が、iframe112とiframe113にページを読み込む順序は任意であり、決まっていない。しかし、ここでは説明の便宜上、先にiframe113へのページ読み込みが発生するものと仮定する。
図9には、説明の簡単化のため、親ページ300のような単純なHTMLソースコードを例示したが、より複雑なコードを利用することにより、iframe112とiframe113へのページ読み込みの順序を制御することが可能である。したがって、「先にiframe113の読み込みが発生する」という上記の仮定を設けても、第1実施形態は限定されない。
例えば、iframe112のソースとして制御用のダミーページのURIを指定するように、<iframe>ブロック301が変形されてもよい。そして、iframe113の読み込みが完了したときにiframe112内のダミーページから“http://www.foo.com/”へのリダイレクションを行うための、“onLoad”属性を用いたスクリプトが、ダミーページに含まれていてもよい。すると、上記の仮定が成立する。
また、iframe112のソースとしてダミーページのURIを指定するように上記のごとく変形された<iframe>ブロックも、図9に示した単純な<iframe>ブロック301も、以下の点では同じである。すなわち、どちらの<iframe>ブロックも、最終的にはブラウザ111に、iframe112内にWebアプリケーション101のページを表示させるためのコードである点では共通である。
いずれにしろ、図8のステップS403ではiframe113が生成される。そして、ステップS404でブラウザ111は、<iframe>ブロック302に指定されたURIに対するHTTP要求を、Webサーバ100に送信する。すなわち、ブラウザ111は、Cometコネクションを維持するためのページをステップS404で要求する。ステップS404におけるHTTP要求は、上記「特定要求」の具体例である。
振り分け部103は、特定要求の受信にともない、ブラウザ111とWebサーバ100との間のコネクションを確立する。そして、振り分け部103はステップS405で、ステップS402で生成したセッションと、確立したコネクションとを対応づける。具体的には、振り分け部103は、ステップS402で生成したセッションのセッションIDと、ステップS404での要求の受信にともなって確立したコネクションを識別するコネクションIDとを対応づけるエントリを、対応表105に追加する。
そして、ステップS406で振り分け部103は、スクリプト生成部104にスクリプトの生成を指示する。すると、スクリプト生成部104は、スクリプトを生成し、生成したスクリプトをステップS407で振り分け部103に出力する。
そして、ステップS408で振り分け部103は、スクリプト生成部104から取得したスクリプトを含むページをブラウザ111に返す。なお、上記のとおり、ステップS408のHTTP応答のメッセージボディはチャンク形式である。そのため、ステップS408の送信後も、コネクションは維持される。
ここで、再び図9を参照し、iframe113に読み込まれる子ページの例について説明する。
図9の子ページ400は、ステップS408で返されるチャンク401を含む。図9の例では、チャンク401は、<html>要素の開始タグ、<head>要素、および<body>要素の開始タグを含む。そして、<head>要素は<script>ブロックを含み、<script>ブロックは、アドレス代入文402と関数定義403を含む。ステップS406の生成指示にしたがってスクリプト生成部104が生成するスクリプトとは、具体的には、例えばチャンク401内の<script>ブロックである。
また、アドレス代入文402は、具体的には、変数dbAddrに、図2の設定ファイル106aに設定されているDBサーバ120のアドレスを代入する文(ステートメント)である。そして、関数定義403は、図1に関して説明した「代行処理」をブラウザ111に行わせるための関数execute1()の定義である。
なお、図9ではアドレス代入文402が代行処理の関数定義403の外にあり、変数dbAddrがグローバル変数として定義されている。しかし、変数dbAddrは、関数execute1()のローカル変数として、関数定義403の中で定義されてもよい。
また、以下では説明の便宜上、DB121がリレーショナルDBであるとする。したがって、DBアクセス要求はSQL文により表される。そのため、関数execute1()は、DBアクセス要求を示すSQL文を引数sqlとしてとる。
図9の例から理解されるように、図8のステップS408でブラウザ111が子ページ400のチャンク401をiframe113内に読み込んだ時点では、副作用は生じない。つまり、ブラウザ111は、まだDBサーバ120にアクセスしない。
さて、続いてステップS409でiframe112が生成される。そして、ステップS410ではiframe112へのページ読み込みが発生する。すなわち、ブラウザ111は、図9の<iframe>ブロック301に指定されたURIに対するHTTP要求を、Webサーバ100に送信する。
なお、図8の例は、Webアプリケーション101のトップページが静的ページの場合の例である。したがって、ステップS410の要求は静的ページの要求である。
ステップS411では、ブラウザ111からの要求を受信した振り分け部103が、「受信した要求は、Webアプリケーション101の静的なページへのアクセス要求である」と判断する。そして、振り分け部103は、ステップS412で、受信した要求をWebアプリケーション101に出力する。すなわち、振り分け部103はWebアプリケーション101に、ブラウザ111からの要求に対する処理を委譲する。
すると、次のステップS413でWebアプリケーション101は、要求された静的なページをブラウザ111に返す。そして、ブラウザ111は返された静的なページをiframe112の中に表示する。
また、以上のようにして表示された静的なページは、Webアプリケーション101がDB121のデータを用いて動的に生成するページへのリンクを含んでもよい。あるいは、静的なページは、次に動的なページを表示するための入力フォームを含んでもよい。
図9の例は、表示された静的なページに対してユーザが何らかの操作(例えば、リンクのクリック、あるいは入力フォームへの入力など)を行うことで、次に動的なページが要求される場合の例である。
具体的には、ユーザの操作にともなって、ステップS414でブラウザ111は、iframe112に読み込む対象の動的なページに対するHTTP要求を、Webサーバ100に送信する。
すると、ステップS415では、ブラウザ111からの要求を受信した振り分け部103が、「受信した要求は、Webアプリケーション101の動的なページへのアクセス要求である」と判断する。そして、振り分け部103は、ステップS416で、受信した要求をWebアプリケーション101に出力する。すなわち、振り分け部103はWebアプリケーション101に、ブラウザ111からの要求に対する処理を委譲する。
すると、Webアプリケーション101は、要求された動的なページを生成する処理を行う。具体的には、Webアプリケーション101は、ページを生成するために用いるデータをDB121から取得するため、ステップS417でDBインタフェイス部102に対してDBアクセス要求を出力する。
すると、ステップS418でDBインタフェイス部102は、Webアプリケーション101から受け取ったDBアクセス要求を振り分け部103に出力する。
そして、ステップS419で振り分け部103は、DBインタフェイス部102から受け取ったDBアクセス要求に対応するコネクションを照会する。ステップS419の詳細は図10とともに後述するが、振り分け部103は、対応表105を参照することで、ステップS418のDBアクセス要求に対応するCometコネクションを特定することができる。なお、図8の例では、ステップS408でのチャンク形式でのHTTP応答により維持され続けているCometコネクションが、ステップS419で特定される。
また、振り分け部103はステップS420で、ステップS418で受け取ったDBアクセス要求に応じたスクリプトを生成するようにスクリプト生成部104に指示する。すると、スクリプト生成部104は、指示にしたがって、DBアクセス要求を含むスクリプトを生成する。そして、スクリプト生成部104は、ステップS421で、生成したスクリプトを振り分け部103に返す。
すると、振り分け部103は、次のステップS422において、ステップS419で特定したCometコネクション上で、DBアクセス要求を含むスクリプトをブラウザ111に送信する。
上記のとおり、iframe113に読み込まれる対象のページは、チャンク形式で送信される。そして、ステップS408で最初のチャンクが送られた後も、まだHTTP応答が完了していないので、コネクションは維持されている。したがって、ステップS422では、維持されているコネクション上で、次のチャンクが送られる。そして、送信される当該チャンクの中には、DBアクセス要求が埋め込まれる。
ここで再び図9を参照すると、ステップS422で送信されるチャンクは、具体的には例えば、子ページ400における<script>ブロック404である。<script>ブロック404は、具体的には、ステップS420での指示にしたがってスクリプト生成部104により生成され、ステップS422で送信され、iframe113に読み込まれる。
図9の<script>ブロック404は、ステップS408で送信されたチャンク401内で定義された関数execute1()の呼び出しステートメントを含む。そして、<script>ブロック404では、関数execute1()に引数として、“SELECT * FROM purchaseTbl WHERE purchaseNo=12345;”というSQL文が指定されている。
図8のステップS422で送信されるDBアクセス要求は、具体的には、上記のように関数呼び出しステートメントの引数として与えられるSQL文により表される。また、<script>ブロック404の関数呼び出しステートメントは、iframe113に読み込まれ次第、ブラウザ111により実行される。すなわち、<script>ブロック404は、図1に関して説明した「DBアクセス要求を含む実行命令スクリプト」の具体例である。
そして、ステップS423でブラウザ111は、関数execute1()の定義にしたがって、DBサーバ120にDBアクセス要求を送信する。具体的には、ブラウザ111は、レベル2のXHRオブジェクト(図8では簡略化のため単に「XHR2」と表記)を新たに生成し、生成したXHRオブジェクトを用いてDBサーバ120にDBアクセス要求を送信する。
なお、XHRオブジェクトを用いたブラウザ111からDBサーバ120へのHTTP要求は、DBサーバ120のインタフェイスに応じて、GETメソッドでもよいしPOSTメソッドでもよい。GETメソッドが使われる場合は、DBアクセス要求を表すSQL文をクエリ・ストリングとして含むURIが、XHRオブジェクトに対するopen()メソッドの引数として与えられる。また、POSTメソッドが使われる場合は、DBアクセス要求を表すSQL文が、XHRオブジェクトに対するsend()メソッドの引数として与えられる。
いずれにしろ、DBアクセス要求を受信したDBサーバ120は、DBアクセス要求にしたがってDB121にアクセスする。
例えば、図9の<script>ブロック404がステップS422で送信された場合のDBアクセス要求は、具体的にはDB121内の“purchaseTbl”という名前のテーブルに対する参照要求である。よって、この場合、DBサーバ120は、要求されたデータをDB121から抽出する。
そして、ステップS424でDBサーバ120は、DBアクセス要求に応じたDBアクセス結果を、XHRオブジェクトによるHTTP要求に対するHTTP応答として、ブラウザ111に返す。
すると、DBアクセス結果を受信したブラウザ111は、ステップS425で、DBアクセス結果をWebサーバ100に送信する。ステップS425でのDBアクセス結果の送信は、例えば、以下の(A1)〜(A3)のような一連のステップにより実現されてもよい。換言すれば、関数定義403は(A1)〜(A3)のステップの定義を含んでもよい。
(A1)新規XHRオブジェクトを生成するステップ。
(A2)HTTPのPOSTメソッドを引数として指定するとともに、Webサーバ100の特定のパスを含むURIも引数として指定したopen()メソッドを、(A1)で生成した新規XHRオブジェクトに対して適用するステップ。
(A3)JSON、CSV、XMLなどの適宜の形式でフォーマットされたDBアクセス結果を引数として指定したsend()メソッドを、(A1)で生成した新規XHRオブジェクトに適用するステップ。
さて、以上のようにしてステップS425で送信されたDBアクセス結果を受信した振り分け部103は、次のステップS426において、受信したDBアクセス結果をDBインタフェイス部102に出力する。
すると、ステップS427でDBインタフェイス部102は、振り分け部103から取得したDBアクセス結果をWebアプリケーション101に出力する。そして、ステップS428でWebアプリケーション101は、DBインタフェイス部102から取得したDBアクセス結果を用いて動的にページを生成し、生成した動的なページを、ステップS414のHTTP要求に対するHTTP応答としてブラウザ111に返す。すると、ブラウザ111は、動的ページをiframe112の中に表示する。
なお、図8の例は様々な動作例のうちの一つに過ぎない。例えば、ステップS428で動的ページがブラウザ111に返された後、再び別の動的なページが要求されてもよい。複数の動的なページが次々に要求される場合は、ステップS414〜S428の一連の処理が繰り返され、iframe112の中の画面が遷移する。例えば、図9の<script>ブロック405が、2回目の動的なページの要求に応じて、ステップS422と同様にしてブラウザ111に送信され、iframe113に読み込まれてもよい。
あるいは、1つのページの生成が、複数のDBアクセス要求をともなっていてもよい。その場合、ステップS414〜S416と同様の一連の処理が1回行われた後、ステップS417〜S427の一連の処理がDBアクセス要求の数だけ繰り返し行われる。その後、ステップS428と同様にしてWebアプリケーション101がブラウザ111にページを返す。
また、Webアプリケーション101のトップページは、必ずしも静的なページでなくてもよい。トップページが動的なページの場合であっても、iframe112内へのページ読み込みよりも先に、iframe113へのステップS408でのチャンク401の読み込みが行われていれば、問題は生じない。そして、上記のとおり、<iframe>ブロック301を適宜修正するとともにダミーページを用いることにより、「iframe113へのステップS408でのチャンク401の読み込みが先に行われる」ということを保証することができる。
また、図8〜9では説明の便宜上、DBアクセス要求の具体例として、DB121への参照要求(すなわちSELECT文で表される要求)を例示した。しかしながら、DBアクセス要求が、DB121へのデータの追加、DB121内の既存のデータの更新、またはDB121からのデータの削除を求める要求であってもよい。また、DBアクセス要求の種類に応じて、ブラウザ111がステップS414でWebサーバ100に送信するHTTP要求のメソッドも、必ずしもGETメソッドでなくてもよい。DBアクセス要求の種類が何であれ、ステップS414〜S428と同様にして、DBアクセスはブラウザ111によって代行される。
ところで、図5〜7を参照して前述した処理を、図8および図9と対応づけてより詳細に説明すれば、以下のとおりである。
図5に示すように、ブラウザ111は、iframe113に読み込んだDBアクセス代行スクリプト114にしたがって動作する。DBアクセス代行スクリプト114は、図9の例では、具体的には、アドレス代入文402、代行処理の関数定義403、<script>ブロック404、および<script>ブロック405を含む。
ブラウザ111は、図5のステップS101に示すように、Webサーバ100からDBアクセス要求を受信するまで待つ。図8の例では、ブラウザ111は、ステップS408でチャンク401をiframe113に読み込んだ後、ステップS422でのDBアクセス要求の受信まで待つ。
そして、図5のステップS102は、図8のステップS423に対応する。また、図5のステップS103に示すように、ブラウザ111は、DBサーバ120からのDBアクセス結果を受信するまで待つ。図8の例では、ブラウザ111は、ステップS424でのDBアクセス結果の受信まで待つ。
そして、図5のステップS104は、図8のステップS425に対応する。また、図5ではステップS104からステップS101へと制御が戻る。この図5のループにより、複数の動的なページが要求される場合、または1つのページが複数のDBアクセス要求をともなう場合において、それぞれのDBアクセスがブラウザ111により代行される。
以上から明らかなとおり、図9の関数定義403は、図5のステップS102〜S104の動作を定義している。また、定義された関数execute1()の中では、図5のステップS102の処理のために、アドレス代入文402により変数dbAddrに設定されたDBサーバ120のアドレスが参照される。そして、図5のステップS101は、具体的には、<script>ブロック404または405のような、関数呼び出しステートメントを含むチャンクの受信に対応する。
また、図6のステップS201に示すように、DBインタフェイス部102は、Webアプリケーション101からDBアクセス要求を受け取るまで待つ。図8の例では、DBインタフェイス部102は、ステップS417まで待つ。
そして、図6のステップS202は図8のステップS418に対応する。また、図6のステップS203に示すように、DBインタフェイス部102は、振り分け部103からDBアクセス結果を受け取るまで待つ。図8の例では、DBインタフェイス部102は、ステップS426まで待つ。
そして、図6のステップS204は、図8のステップS427に対応する。また、図6ではステップS204からステップS201へと制御が戻る。この図6のループにより、複数の動的なページが要求される場合、または1つのページが複数のDBアクセス要求をともなう場合において、それぞれのDBアクセスが、DBインタフェイス部102と振り分け部103を介して、ブラウザ111により代行される。
なお、図7のステップS301は図8には明示されていない。スクリプト生成部104は、ステップS301の実行後、ステップS302で振り分け部103からスクリプトの生成指示を受け取るまで待つ。図8の例では、スクリプト生成部104は、ステップS406まで待つ。
そして、図7のステップS303でスクリプト生成部104が生成するスクリプトの内容は、生成指示に応じて異なる。例えば、図8のステップS406の生成指示を受け取った場合、スクリプト生成部104は、ステップS301で読み取ったDBサーバ120のアドレスに基づいてアドレス代入文402を生成するとともに、関数定義403も生成する。
また、図8のステップS407は、図7のステップS304に対応する。そして、図7に示すように、処理はステップS304からステップS302に戻る。すると、図8に示すように、スクリプト生成部104は、次のスクリプト生成指示を振り分け部103からステップS420で受け取るまで待つ。
ステップS420での生成指示は、具体的には、関数呼び出しステートメントの生成指示であり、DBアクセス要求を示すSQL文を関数の引数として指定する指示である。したがって、次に図7のステップS303でスクリプト生成部104が生成するスクリプトは、具体的には図9の<script>ブロック404である。そして、次のステップS304は図8のステップS421に対応する。
また、図7の処理はステップS304からステップS302へと再び戻る。したがって、この図7のループにより、複数の動的なページが要求される場合、または1つのページが複数のDBアクセス要求をともなう場合において、それぞれのDBアクセス要求に対応する<script>ブロックがスクリプト生成部104により生成される。また、この図7のループにより、複数のブラウザからの要求に対応するそれぞれのスクリプトがスクリプト生成部104により生成される。
続いて、第1実施形態における振り分け部103の動作について、図10〜11を参照して詳しく説明する。
図10は、第1実施形態において振り分け部103がDBインタフェイス部102からのDBアクセス要求の受付を契機として行う処理のフローチャートである。例えば、図8のステップS418でのDBアクセス要求の受付を契機として、振り分け部103は図10の処理を開始する。
そして、ステップS501で振り分け部103は、スレッドローカルな変数からセッションIDを取得する。詳しくは図11とともに説明するが、振り分け部103は、ブラウザ111からのアクセス要求(具体的にはHTTP要求)をWebアプリケーション101に委譲する場合、スレッドローカルな変数にセッションIDを代入する。そして、DBインタフェイス部102から振り分け部103がDBアクセス要求を受け取るタイミングは、Webアプリケーション101への処理の委譲が起きた後である。したがって、振り分け部103は、ステップS501でスレッドローカルな変数からセッションIDを取得することができる。
そして、次のステップS502で振り分け部103は、取得したセッションIDを検索キーとして用いて対応表105を検索し、取得したセッションIDに対応するコネクションを特定する。ステップS502の例は、図8のステップS419である。
さらに、次のステップS503で振り分け部103は、図10の処理を開始する契機となったDBアクセス要求を含むスクリプトを、スクリプト生成部104に生成させる。ステップS503の例は、図8のステップS420〜S421である。
例えば、図8のステップS418で振り分け部103が受け取ったDBアクセス要求が、図9の<script>ブロック404において関数の引数として与えられているSQL文により表されるとする。この場合、ステップS503において振り分け部103は、SQL文をスクリプト生成部104に対して指定し、スクリプト生成部104に<script>ブロック404を生成させる。
なお、ステップS503の処理はステップS501〜S502の処理とは独立しているので、ステップS501〜S502の処理と並行にステップS503の処理が行われてもよい。あるいは、ステップS503の処理がステップS501〜S502の処理よりも先に行われてもよい。
そして、ステップS501〜S503の実行後、ステップS504で振り分け部103は、ステップS502で特定したコネクションを介して、ステップS503で生成されたスクリプトをブラウザ111に送信する。ステップS504の例は、図8においては、ステップS422である。また、図9の<script>ブロック404は、ステップS504で送信されるスクリプトの一つの例であり、<script>ブロック405は、ステップS504で送信されるスクリプトの他の例である。
スクリプトの送信後、振り分け部103は、ステップS505で、ブラウザ111からDBアクセス結果を受信するまで待つ。ステップS505の例は、図8においては、ステップS422の送信後、ステップS425の受信までの待機である。
そして、振り分け部103がDBアクセス結果をブラウザ111から受信すると、処理はステップS506に移行する。すると、ステップS506で振り分け部103は、ブラウザ111から受信したDBアクセス結果をDBインタフェイス部102に返す。ステップS506の具体例は、図8のステップS426である。
ステップS506の実行後、図10の処理も終了する。なお、ブラウザ111がXHRを用いてDBアクセス結果を振り分け部103に通知する場合は、振り分け部103は、さらに、XHRによるHTTP要求に対するHTTP応答をブラウザ111に返してもよい。例えば、振り分け部103は、ステータスコードが200(OK)でメッセージボディが空のHTTP応答を、ブラウザ111に返してもよい。
さて、図11は、第1実施形態において振り分け部103がブラウザ111からの要求の受信を契機として行う処理のフローチャートである。例えば、図8のステップS401、S404、S410、S414、S425では、振り分け部103がブラウザ111からのHTTP要求を受信する。そして、振り分け部103は、HTTP要求の受信を契機として、図11の処理を開始する。
なお、HTTP要求を振り分け部103が受信すると、ブラウザ111とWebサーバ100の間のHTTPコネクションが確立する。したがって、図11の処理が開始された時点で何らかのコネクションが存在する。
ステップS601で振り分け部103は、セッションがあるか否かを判断する。具体的には、振り分け部103は、受信したHTTP要求のCookieヘッダを参照することで、セッションがあるか否かを判断してもよい。そして、セッションがなければ処理はステップS602に移行する。逆に、セッションが既に存在していれば、振り分け部103は例えばCookieヘッダからセッションIDを認識し、処理はステップS604に移行する。
ステップS602で振り分け部103は、セッションを新規に作成する。具体的には、振り分け部103は、新たなセッションIDを発行する。ステップS602が実行されるのは、例えば、図8のステップS401の要求の受信を契機として図11の処理が開始された場合である。
そして、次のステップS603で振り分け部103は、HTTP応答のSet−CookieヘッダにステップS602で発行したセッションIDを設定して、親ページ300をブラウザ111に返す。親ページ300の<iframe>要素301に付けられているsrc属性を”/”の代わりにHTTP要求のリクエストラインにあったパスとしておくことも可能である。ステップS603の具体例は、図8のステップS402である。また、ステップS603の実行後、図11の処理は終了する。
他方、セッションが既に存在する場合、ステップS604で振り分け部103は、ブラウザ111から要求されたURIが、DBアクセス用の特定のパスを含むURIであるか否かを判断する。例えば、特定のパスは、先に例示した“/_reservedForComet”であってもよい。
そして、ブラウザ111から要求されたURIが、DBアクセス用の特定のパスを含むURIの場合、処理はステップS605に移行する。逆に、ブラウザ111から要求されたURIが、DBアクセス用の特定のパスを含まないURI(すなわち、Webアプリケーション101が使用するURI)の場合、処理はステップS609に移行する。
なお、振り分け部103は、図8のステップS404で要求を受信したときにステップS604の判断を行う。また、図8のステップS411とS415でも、ステップS604の判断が行われる。さらに、振り分け部103は、図8のステップS425でDBアクセス結果をHTTP要求の形で受信したときも、ステップS604の判断を行う。
そして、ブラウザ111から要求されたURIが、DBアクセス用の特定のパスを含むURIの場合、ステップS605で振り分け部103は、ブラウザ111からのHTTP要求のメソッドがGETメソッドであるか、それともPOSTメソッドであるかを判断する。振り分け部103は、受信したHTTP要求のリクエストラインを参照することでメソッドを認識することができる。
リクエストラインにGETメソッドが指定されていた場合、処理はステップS606に移行する。逆に、リクエストラインにPOSTメソッドが指定されていた場合、処理はステップS611に移行する。
例えば、図8のステップS404の要求は、GETメソッドによって特定のパスへのアクセスを求める要求である。よって、ステップS404の受信を契機として図11の処理が開始された場合、処理はステップS606へと進む。
逆に、図8のステップS425のDBアクセス結果の通知のためのHTTP要求は、POSTメソッドによって特定のパスへのアクセスを求める要求である。よって、ステップS425の受信を契機として図11の処理が開始された場合、処理はステップS611へと進む。
さて、ステップS606で振り分け部103は、対応表105に新規エントリを追加する。そして、振り分け部103は、新規エントリのセッションIDフィールドに、ステップS601で認識したセッションIDを設定する。
また、ステップS606が実行されるのは、例えば図8のステップS404のように、Cometコネクション用にiframe113に読み込むための子ページ400がブラウザ111から要求された場合である。そして、ブラウザ111からのHTTP要求の受信を契機として、図11の処理の開始時点でHTTPコネクションは確立済みである。したがって、ステップS606で振り分け部103は、新規エントリのコネクションIDフィールドに、確立したコネクションを識別するコネクションIDを設定する。
以上のようにしてステップS606では、セッションIDとコネクションIDの新たなペアが対応表105に登録される。ステップS606の具体例は図8のステップS405である。
そして、次のステップS607で振り分け部103は、スクリプト生成部104にスクリプトを生成させる。ステップS607の具体例は、図8のステップS406〜S407である。つまり、ステップS607で振り分け部103は、アドレス代入文402と関数定義403を含むスクリプトをスクリプト生成部104に生成させる。
そして、次のステップS608で振り分け部103は、生成されたスクリプトを含むページをチャンク形式でブラウザ111に返す。ステップS608の具体例は、図8のステップS408である。振り分け部103がチャンク形式でページを返す(すなわちHTTP応答を返す)ことにより、ブラウザ111のiframe113とWebサーバ100との間でコネクションは維持され続ける。ステップS608の実行後、図11の処理は終了する。
さて、ブラウザ111から要求されたURIが特定のパスを含まない場合、ステップS609で振り分け部103は、スレッドローカルな変数に、ステップS601で認識したセッションIDを保存する。ここで保存されたセッションIDは、前述のとおり、図10のステップS501で参照される。
そして、次のステップS610で振り分け部103は、Webアプリケーション101に処理を委譲する。具体的には、振り分け部103は、ブラウザ111から受信したHTTP要求をWebアプリケーション101に出力する。そして、振り分け部103による図11の処理は終了する。なお、ステップS609〜S610の処理は、例えば、図8においては、ステップS412においても行われ、ステップS416においても行われる。
他方、ブラウザ111から特定のパスへのPOSTメソッドによるアクセスが要求された場合、振り分け部103はステップS611の処理を行う。なお、ステップS611の処理が行われるのは、上記のとおり、例えば図8のステップS425のようにDBアクセス結果の通知のためのHTTP要求を振り分け部103が受信した場合である。よって、ステップS611で振り分け部103は、具体的には、DBアクセス結果の受信を認識する。
すると、図11の処理フローは終了するが、他方で、振り分け部103は、図10のステップS505でDBアクセス結果の受信を待ってもいるので、図10において処理がステップS505からステップS506へと進む。その結果、振り分け部103は、ブラウザ111から受信したDBアクセス結果をDBインタフェイス部102へと出力する。
なお、より詳しく説明すると、第1実施形態では、振り分け部103のスレッドは、ステップS610でWebアプリケーション101へ処理を委譲した後、図11の処理を一旦終了するが、消滅はしない。スレッドが消滅せずに存在を続けることは、図8においては、振り分け部103の列に示したアクティベーションの矩形が、ステップS415からステップS426まで続いていることにより表現されている。
そして、ステップS610に相当するステップS416での委譲を行ったスレッドは、ステップS418でのDBインタフェイス部102からのDBアクセス要求の受付を契機に図10の処理を開始し、図10のステップS505でDBアクセス結果の受信を待つ。また、ステップS425でのDBアクセス結果の受信を契機に、当該スレッドは図11の処理を開始する。
以上のようにして、DBインタフェイス部102からのDBアクセス要求を受け付けたスレッド自体が、対応するDBアクセス結果をブラウザ111から受信する。したがって、振り分け部103は、ブラウザ111から受信したDBアクセス結果がDBインタフェイス部102からのどのDBアクセス要求に対応するのかを認識して、DBインタフェイス部102に正しくDBアクセス結果を出力することができる。
もちろん、実施形態によっては、DBアクセス要求を識別する要求IDが、DBアクセス要求とDBアクセス結果の対応関係の管理のために使われてもよい。つまり、要求IDがDBアクセス要求とともにDBインタフェイス部102から振り分け部103に出力されてもよい。そして、関数定義403は、引数として、SQL文とともに要求IDをとるように変形されてもよい。また、DBアクセス結果は、要求IDとともにブラウザ111から振り分け部103へ、振り分け部103からDBインタフェイス部102へ、と返されてもよい。
以上のとおり、第1実施形態によれば、iframe113に読み込まれる子ページ600がチャンク形式で送られる(つまり、ストリーミングのように少しずつ送られる)ことにより、ブラウザ111とWebサーバ100の間のコネクションが維持され続ける。また、Webアプリケーション101によるDBアクセス要求がいつ生じても、コネクションが維持され続けているので、振り分け部103はすぐにDBアクセス要求をブラウザ111に中継することができる。
そして、ブラウザ111がDBアクセス代行スクリプト114にしたがってDBアクセスを代行し、DBアクセス結果は振り分け部103とDBインタフェイス部102を介して最終的にWebアプリケーション101に出力される。したがって、Webアプリケーション101は、直接DBサーバ120にアクセスすることが許されなくても、DBアクセス結果を得ることができる。
このように、第1実施形態によれば、インタフェイス・サーバまたは中継サーバなどの付加的な装置がなくても、Webアプリケーション101が、ファイアウォール130で隔てられたイントラネット140内のDB121のデータを使って処理を行うことができる。また、Webアプリケーション101は、DB121のデータを一時的かつ部分的に使うだけであり、DB121のデータがWebサーバ100に不揮発的に長期にわたって保存されるわけではない。したがって、第1実施形態は、DB121に機密情報が含まれる場合にも好適である。
続いて、図12〜16を参照して第2実施形態について説明する。第2実施形態では、Cometコネクションの維持のために「ロングポーリング」と呼ばれる技術が使われる。具体的には、DBアクセス代行スクリプト114にしたがってブラウザ111がXHRオブジェクトを用いて送信するHTTP要求に対する応答を、Webサーバ100が延期することで、応答が返るまでの間、コネクションが維持され続ける。
第2実施形態では、上記のようにして維持されるCometコネクション(換言すればHTTPコネクション)を利用して、振り分け部103がDBアクセス要求をブラウザ111に送信する。以下ではより具体的に第2実施形態について説明する。
図12は、第2実施形態のWebサーバ100の動作を説明する、UMLで表現されたアクティビティ図である。詳しくは後述するが、第2実施形態では、iframe113内に読み込む対象のデータが、チャンク形式で複数回に分けられて送信されるのではなく、一度に送信される。図12は、少なくとも親ページがWebサーバ100からブラウザ111に送信された後のWebサーバ100の動作を説明する図である。また、iframe113への子ページの読み込みのための処理は、図12では省略されている。
初期ノードS701からのフローは、ブラウザ111がiframe112内にページを読み込むためにHTTP要求を送信し、振り分け部103が当該HTTP要求を受信することを契機として始まる。具体的には、HTTP要求を受信した振り分け部103は、ステップS702においてスレッドローカルな変数にセッションIDを保存する。
そして、次の決定ノードS703に示すように、その後の動作には、DBアクセス以外の処理が発生する場合と、DBアクセスの処理が発生する場合と、Webアプリケーション101の処理が終了する場合がある。それぞれの場合に対応して、制御は、ステップS704、S709、S715へと移行する。
もしDBアクセス以外の処理が発生すると、ステップS704で、振り分け部103はWebアプリケーション101に処理を委譲し、Webアプリケーション101が適宜の処理を行う。例えば、静的または動的なページがブラウザ111から要求された場合、ステップS704でWebアプリケーション101による処理が行われる。そして、制御は、マージノードS705を経て決定ノードS703に戻る。
他方で、初期ノードS706からのフローは、ブラウザ111がDBアクセス代行スクリプト114にしたがって、XHRオブジェクトを用いてロングポーリング用のHTTP要求を送信し、振り分け部103が当該HTTP要求を受信することを契機として始まる。ロングポーリング用のHTTP要求は、具体的には、メッセージボディにDBアクセス要求を含むHTTP応答を受信するための要求であり、iframe112へのページ読み込みのためのHTTP要求とは非同期に送信される。また、ロングポーリング用のHTTP要求に対する応答は、コネクションの維持のために適宜延期される。
具体的には、振り分け部103は、ロングポーリング用のHTTP要求を受信すると、ステップS707で、対応表105に新規エントリを挿入する。また、振り分け部103は、新規エントリのセッションIDフィールドに、ブラウザ111とWebサーバ100の間で確立済みのセッションのセッションIDを設定する。そして、振り分け部103は、ロングポーリング用のHTTP要求の受信によってブラウザ111とWebサーバ100との間に確立したHTTPコネクションを識別するコネクションIDを、新規エントリのコネクションIDフィールドに設定する。
なお、上記のようにロングポーリング用のHTTP要求は、iframe112へのページ読み込みのためのHTTP要求とは非同期に送信される。また、iframe112に読み込む対象のWebアプリケーション101のページが常にDBアクセスをともなうとも限らない。逆に、振り分け部103がDBインタフェイス部102からDBアクセス要求を受け取った時点で、「ロングポーリング用のHTTP要求が既に受信されており、かつ、まだHTTP応答は返されていない」という条件が成立するとも限らない。
そこで、ステップS707の処理の後は、ジョインノードS708に示すように、待ち合わせが生じる。待ち合わせの対象は、ステップS709〜S710のフローである。
具体的には、ステップS704でのWebアプリケーション101への処理の委譲の結果として、DBアクセスの処理が発生することもある。すると、ステップS709で、振り分け部103は、スレッドローカルな変数からセッションIDを取得する。そして、次のステップS710で振り分け部103は、取得したセッションIDに対応するコネクションを対応表105から探す。
ステップS710での検索の結果、コネクションが見つかれば、続いてステップS711の処理が行われる。
しかし、ステップS710での検索の結果、コネクションが見つからない場合もある。対応するコネクションが見つからない場合は、スレッドローカルな変数に保存されているセッションIDを持つエントリがステップS707で対応表105に追加されるまで、ステップS711の処理は行われない。つまり、待ち合わせが生じる。
そして、ステップS711では、振り分け部103が、ステップS709で取得したセッションIDと、当該セッションIDに対応づけられたコネクションIDとのペアを、対応表105から削除する。より具体的には、振り分け部103は、当該コネクションIDを記憶してから、セッションIDとコネクションIDのペアを削除する。
さらに、次のステップS712では、XHRオブジェクトを用いたHTTP要求に対するHTTP応答を経由してのDBアクセスが行われる。
具体的には、振り分け部103が、ステップS711で記憶したコネクションIDで特定されるコネクションを利用して、DBアクセス要求をブラウザ111に送信する。つまり、振り分け部103は、XHRオブジェクトを用いてロングポーリング用にブラウザ111から以前送信されたHTTP要求に対するHTTP応答として、DBインタフェイス部102から受け取ったDBアクセス要求を、ブラウザ111に送信する。
そして、ブラウザ111は、DBアクセス要求を受信すると、DBアクセス代行スクリプト114にしたがって、DBアクセスを代行し、DBアクセス結果をWebサーバ100に返信する。DBアクセス結果は、具体的には、XHRオブジェクトを用いたHTTP要求(具体的にはPOSTメソッドのHTTP要求)のメッセージボディに含められて、Webサーバ100に送信される。
すると、振り分け部103が、以上のようにしてブラウザ111からXHRオブジェクトを用いて送信されたDBアクセス結果を受信し、DBインタフェイス部102にDBアクセス結果を出力する。また、DBインタフェイス部102は、DBアクセス結果をWebアプリケーション101に出力する。
また、DBアクセス結果の受信によりステップS712のガード条件が満たされるので、ジョインノードS708で合流した二つのフローは、フォークノードS713に示すように再び分かれる。すなわち、初期ノードS706からのフローは最終ノードS714に至り、ステップS709〜S710からのフローは、マージノードS705を経て決定ノードS703に戻る。
なお、ブラウザ111は、DBアクセス代行スクリプト114にしたがって、再びロングポーリング用の新たなHTTP要求をWebサーバ100に送信する。よって、Webサーバ100では再び初期ノードS706からのフローが始まる。
他方で、上記のようにしてステップS712でDBインタフェイス部102からDBアクセス結果を受け取ったWebアプリケーション101は、必要に応じてDBアクセス結果を用いて動的にページを生成する。そして、Webアプリケーション101によるページ生成の処理が終了すると、ステップS715のとおり、Webサーバ100からブラウザ111にHTTP応答が返されて、フローは最終ノードS716に至る。
続いて、第2実施形態の一動作例を、図13のシーケンス図を参照して説明する。
ステップS801でブラウザ111は、Webサーバ100に対する初回の要求を送信する。すると、振り分け部103がステップS801の要求を受信する。そして、ステップS802で振り分け部103は、新たなセッションを生成し、iframe112とiframe113を要素として指定する親ページを返す。
ステップS801〜S802は、図8のステップS401〜S402とほぼ同じである。ただし、第1実施形態では、Webサーバ100がブラウザ111にDBアクセスを代行させるために予約される特殊なパスが1つのみだが、第2実施形態では次の(B1)〜(B3)の3つのパスが予約される。
(B1)iframe113用のパス(以下では説明の便宜上、“/_reservedForIframe”とする)。
(B2)XHRオブジェクトを用いたロングポーリング用のHTTP要求を受け付けるためのパス(以下では説明の便宜上、“/_reservedForLP”とする)。
(B3)ブラウザ111からDBアクセス結果の通知を受信するためのパス(以下では説明の便宜上、“/_reservedForDB”とする)。
なお、以上の3つのパスのうち、ロングポーリング用のHTTP要求を受け付けるための(B2)のパスが、図1に関して説明した「特定要求」により要求される「特定のパス」である。
ここで、図14を参照してステップS802で送信される親ページの例について説明する。図14は、第2実施形態でブラウザ111に送信されるソースコードの例を示す図である。
ステップS802では、例えば図14の親ページ500が返される。親ページ500は、<iframe>ブロック501と<iframe>ブロック502を含む。
図14の<iframe>ブロック501は、ブラウザ111に、iframe112の中にWebアプリケーション101のページを表示させるためのHTMLソースコードの例である。また、<iframe>ブロック501は、iframe112の幅と高さがそれぞれ400ピクセルと600ピクセルであること、および、iframe112に読み込む対象のソースの相対URIが“/”であることを示している。
他方、<iframe>ブロック502は、(B1)のiframe113用のパスをソースとして指定するHTMLソースコードである。換言すれば、<iframe>ブロック502は、ブラウザ111を(B2)の「特定のパス」にアクセスさせるためのコードを、クライアントマシン110(具体的にはブラウザ111)に取得させるためのコードである。なお、「ブラウザ111を(B2)の『特定のパス』にアクセスさせるためのコード」とは、具体的には、iframe113に読み込まれる子ページ600のコードである。子ページ600の詳細については後述する。
なお、<iframe>ブロック502によれば、第1実施形態と同様に、ユーザの利便性の観点から、iframe113が実質的に不可視に設定される。
ここで、図13の説明に戻る。ステップS802で親ページ500を受信したブラウザ111は、親ページ500が2つのiframe112とiframe113を含むことを認識する。
なお、第1実施形態と同様に、iframe112とiframe113の読み込み順を制御するために<iframe>ブロック501が変形されてもよい。しかし、第2実施形態では、図12のジョインノードS708に示すような待ち合わせが行われるので、読み込み順の制御は不要である。
図14の動作例は、たまたまiframe113へのページ読み込みが先に生じた場合の例である。この場合、ステップS803でiframe113が生成され、ステップS804でブラウザ111は、<iframe>ブロック502に指定されたURIに対するHTTP要求を、Webサーバ100に送信する。
すなわち、ステップS804でブラウザ111は、Comet用のページを要求する。ただし、ステップS804の要求自体は、Cometコネクションを維持するための「特定要求」ではなく、特定要求の送信をブラウザ111に指示するDBアクセス代行スクリプト114を含むページに対する要求である。DBアクセス代行スクリプト114にしたがってブラウザ111が特定要求を送信することでCometコネクションが維持されるので、図14のステップS804には「Comet用ページ要求」と表記してある。
さて、ステップS804で要求を受信した振り分け部103は、ステップS805でスクリプト生成部104にスクリプトの生成を指示する。すると、スクリプト生成部104は、スクリプトを生成し、生成したスクリプトをステップS806で振り分け部103に出力する。
そして、ステップS807で振り分け部103は、スクリプト生成部104から取得したスクリプトを含むComet用のページをブラウザ111に返す。なお、ステップS807では、iframe113内に読み込むためのページ全体が返される。つまり、チャンク形式は使われない。
ここで、再び図14を参照し、iframe113に読み込まれる子ページの例について説明する。
図14の子ページ600は、<head>要素と<body>要素を含む。そして、<head>要素は<script>ブロックを含み、<script>ブロックは、アドレス代入文601と、図1に関して説明した「代行処理」の関数定義602と、メインルーチンの関数定義603を含む。
また、<body>要素も<script>ブロック604を含む。そして、<script>ブロック604は、具体的には、関数定義603で定義された関数の呼び出しステートメントを含む。
なお、関数main()の呼び出しステートメントは、<head>要素内の<script>ブロックにあってもよい。または、アドレス代入文601、関数定義602、および関数定義603が、<body>要素内の<script>ブロック604の中の、関数main()の呼び出しステートメントの前にあってもよい。
アドレス代入文601は、図9のアドレス代入文402と同様である。アドレス代入文402が関数定義403の中にあってもよいのと同様に、アドレス代入文601も、関数定義602の中にあってもよい。
また、関数定義602で定義される関数execute2()は、DBアクセス要求を示すSQL文を引数sqlとしてとる。関数execute2()は、第1実施形態の関数execute1()とほぼ同様だが、関数定義の中に埋め込まれるDBアクセス結果の通知先のURIが異なる。
第1実施形態では、GETメソッドによる特定要求を受け付けるための特定のパスが、POSTメソッドによるDBアクセス結果の通知を受け付けるのにも使われる。よって、第1実施形態のexecute1()の中には、“http://www.foo.com/_reservedForComet”という、特定のパスを含むURIが、DBアクセス結果の通知先のURIとして埋め込まれる。
それに対して、第2実施形態では、特定要求を受け付けるための上記(B2)の特定のパスとは別の、上記(B3)のパスが、DBアクセス結果の通知を受け付けるのに使われる。よって、代行処理の関数定義602の中には、“http://www.foo.com/_reservedForDB”というURIが埋め込まれる。
また、関数execute2()は、XHRオブジェクトを用いてHTTP要求の形でDBアクセス結果をWebサーバ100に送信した後、対応するHTTP応答の受信またはタイムアウトを待ってから終了するよう、定義される。DBアクセス結果を送信するためのHTTP要求に対応するHTTP応答は、具体的には、例えば、ステータスコードが200(OK)で、メッセージボディが空のHTTP応答である。
また、関数定義603で定義されるメインルーチンは、具体的には、下記(C1)〜(C3)のステップを繰り返すルーチンである。
(C1)新規XHRオブジェクトを生成し、新規XHRオブジェクトによるロングポーリング用のHTTP要求(すなわち、(B2)の特定のパスに対する特定要求)を送信するステップ。
(C2)上記(C1)の要求に対する応答を待ち、応答を受信したら、受信した応答からDBアクセス要求(すなわちSQL文)を抽出するステップ。
(C3)抽出したSQL文を引数として指定して関数execute2()を呼び出すステップ。
ブラウザ111は、メインルーチンの関数呼び出しステートメントを含む<script>ブロック604をiframe113に読み込むと、関数main()の実行を開始する。その結果、上記(C1)のステップが実行される。すなわち、図13のステップS808に示すように、XHRオブジェクトによるロングポーリング用のHTTP要求がブラウザ111からWebサーバ100へと送信され、振り分け部103において受信される。
すると、要求を受信した振り分け部103は、次のステップS809において、図12のステップS707に示すようにセッションとコネクションの対応づけを行う。そして、図12のジョインノードS708に示すように、振り分け部103は、DBインタフェイス部102からのDBアクセス要求を待つ。
他方、ステップS810ではiframe112が生成され、ステップS811ではiframe112へのページ読み込みが発生する。すなわち、ブラウザ111は、図14の<iframe>ブロック501に指定されたURIに対するHTTP要求を、Webサーバ100に送信する。
なお、図14の例も、図8と同様に、Webアプリケーション101のトップページが静的ページの場合の例である。したがって、図8のステップS410〜S413と同様の一連の処理が、ステップS811〜S814で行われる。その結果、ブラウザ111は静的なページをiframe112の中に表示する。
続いて、ステップS815では、図8のステップS414と同様に、ブラウザ111が、iframe112に読み込む対象の動的なページに対するHTTP要求を、Webサーバ100に送信する。すると、図8のステップS415〜S418と同様の一連の処理が、ステップS816〜S819で行われる。
そして、次のステップS820で振り分け部103は、図12のステップS709〜S710に示すように、対応表105を参照してコネクションの照会を行う。図13の例では、ステップS808の要求に対してまだ応答が返されていないので、ステップS820での照会の結果、コネクションが見つかる。すると、図12のステップS711に関して説明したように、振り分け部103はコネクションIDを記憶してから、見つけたエントリを対応表105から削除する。
そして、ステップS821で振り分け部103は、図12のステップS712に関して説明したように、受信済みのHTTP要求(図13の例ではステップS808の要求)に対する応答として、DBアクセス要求をブラウザ111に送信する。すると、ブラウザ111はDBアクセス代行スクリプト114にしたがって上記(C2)〜(C3)の処理を行う。
その結果、関数execute2()の呼び出しにより、ステップS822では、XHRオブジェクトを用いたブラウザ111からDBサーバ120へのHTTP要求が送信される。ステップS822のHTTP要求のメッセージボディには、DBアクセス要求が含まれる。そして、DBアクセス要求を受信したDBサーバ120は、DBアクセス要求にしたがってDB121にアクセスし、DBアクセス結果を取得する。
また、ステップS823でDBサーバ120は、取得したDBアクセス結果を、ステップS822のHTTP要求に対するHTTP応答として、ブラウザ111に返す。
すると、DBアクセス結果を受信したブラウザ111は、ステップS824で、DBアクセス結果をWebサーバ100に送信する。ステップS822〜S824の詳細は図8のステップS423〜S425と同様である。
そして、以上のようにして送信されたDBアクセス結果は、振り分け部103により受信される。すると、振り分け部103は、ステップS825でDBインタフェイス部102にDBアクセス結果を出力する。そして、ステップS826でDBインタフェイス部102は、DBアクセス結果をWebアプリケーション101に出力する。ステップS825〜S826は、図12のステップS712に対応し、図8のステップS426〜S427と同様である。
また、DBインタフェイス部102からDBアクセス結果を取得したWebアプリケーション101は、ステップS827において、取得したDBアクセス結果を用いて動的にページを生成する。また、Webアプリケーション101は、生成した動的なページを、ステップS815のHTTP要求に対するHTTP応答として、ステップ827でブラウザ111に返す。ステップS827は、図8のステップS428と同様である。また、ステップS827でのHTTP応答の送信は、図12のステップS715に対応する。
また、図13では紙幅の都合上省略されているが、振り分け部103は、ステップS824でDBアクセス結果を受信すると、上記のとおりメッセージボディが空のHTTP応答をブラウザ111に返す。その結果、ブラウザ111では、上記(C3)における関数execute2()の実行が完了する。
すると、ブラウザ111は、メインルーチンの関数定義603にしたがって再度(C1)のステップを実行する。すなわち、ブラウザ111は、ステップS828でステップS808と同様にして、再びXHRオブジェクトによるロングポーリング用のHTTP要求を送信する。すると、要求を受信した振り分け部103は、次のステップS829において、ステップS809と同様の処理を行う。
なお、以上説明した図13の例は様々な動作例のうちの一つに過ぎない。図8に関して説明したのと同様に、図13に関しても様々なバリエーションがあり得る。
例えば、ステップS827で動的ページがブラウザ111に返された後、再び別の動的なページが要求されてもよい。あるいは、1つのページの生成が、複数のDBアクセス要求をともなっていてもよい。また、Webアプリケーション101のトップページは、必ずしも静的なページでなくてもよい。そして、DBアクセス要求の種類は、参照、追加、更新、削除のいずれであってもよい。DBアクセス要求の種類が何であれ、DBアクセスはブラウザ111によって代行される。
ところで、図5〜7を参照して前述した処理を、図12〜14と対応づけてより詳細に説明すれば、以下のとおりである。
図5に示すように、ブラウザ111は、iframe113に読み込んだDBアクセス代行スクリプト114にしたがって動作する。DBアクセス代行スクリプト114は、図14の例では、具体的には、アドレス代入文601、代行処理の関数定義602、メインルーチンの関数定義603、および<script>ブロック604内のメインルーチンの関数呼び出しステートメントを含む。
ブラウザ111は、図5のステップS101に示すように、Webサーバ100からDBアクセス要求を受信するまで待つ。第2実施形態では、ステップS101は、図13におけるステップS808のロングポーリング用のHTTP要求の送信を含む。さらに、ステップS101での待機は、図13の例では、ステップS808の送信後、ステップS821でのHTTP応答の形でのDBアクセス要求の受信まで待つことに対応する。
そして、図5のステップS102は図13のステップS822に対応する。また、図5のステップS103に示すように、ブラウザ111は、DBサーバ120からDBアクセス結果を受信するまで待つ。図13の例では、ブラウザ111は、ステップS823でのDBアクセス結果の受信まで待つ。
そして、図5のステップS104は、図13のステップS824に対応する。また、図5ではステップS104からステップS101へと制御が戻る。この図5のループにより、上記のように複数の動的なページが要求される場合、または1つのページが複数のDBアクセス要求をともなう場合において、それぞれのDBアクセスがブラウザ111により代行される。そして、この図5のループは、第2実施形態では、関数main()内のループにより実現される。
すなわち、図14のメインルーチンの関数定義603は、図5の全体のフローを定義している。また、代行処理の関数定義602は、図5のステップS102〜S104の動作を定義している。そして、<script>ブロック604は、図5の処理の開始をブラウザ111に指示するコードである。
また、図6に動作を示したDBインタフェイス部102は、第1実施形態と同様である。
また、図7のステップS301は図13には明示されていない。スクリプト生成部104は、ステップS301の実行後、ステップS302で振り分け部103からスクリプトの生成指示を受け取るまで待つ。図13の例では、スクリプト生成部104は、ステップS805まで待つ。
そして、図7のステップS303でスクリプト生成部104が生成するスクリプトの内容は、具体的には、図14の子ページ600に含まれる<head>要素内の<scritp>ブロックおよび<body>要素内の<script>ブロック604である。
また、図7の処理はステップS304からステップS302へと再び戻る。したがって、この図7のループにより、複数のブラウザからの要求に対応するそれぞれのスクリプトがスクリプト生成部104により生成される。
続いて、第2実施形態における振り分け部103の動作について、図15〜16を参照して詳しく説明する。
図15は、第2実施形態において振り分け部103がDBインタフェイス部102からのDBアクセス要求の受付を契機として行う処理のフローチャートである。例えば、図13のステップS819でのDBアクセス要求の受付を契機として、振り分け部103は図15の処理を開始する。
そして、ステップS901で振り分け部103は、スレッドローカルな変数からセッションIDを取得する。ステップS901は、図10のステップS501と同様であり、また、図12のステップS709に対応する。
次に、ステップS902で振り分け部103は、ステップS901で取得したセッションIDに対応するコネクションを対応表105から探す。なお、ステップS902は図10のステップS502と似ているが、違いもある。すなわち、ステップS502では予期せぬエラーでもない限りコネクションが1つ見つかるのに対し、ステップS902ではコネクションが見つかる保証はない。図12のジョインノードS708に関して説明したとおり、例えば、図13のステップS808のHTTP要求の受信の前に、振り分け部103がステップS819のDBアクセス要求を受け付けた場合などは、コネクションが見つからない。
そこで、次のステップS903で振り分け部103は、ステップS902の検索の結果コネクションが見つかったか否かを判断する。コネクションが見つかった場合、処理はステップS904に移行する。逆に、コネクションが見つからなかった場合、処理はステップS906に移行する。
ステップS904で振り分け部103は、ステップS902の検索の結果として見つかったエントリのコネクションIDを記憶し、見つかったエントリ(すなわちセッションIDとコネクションIDのペア)を対応表105から削除する。
なお、ステップS904は、図12のステップS711に対応する。また、ステップS904で記憶されるコネクションIDは、具体的には、ブラウザ111が過去にXHRオブジェクトを用いて送信したHTTP要求を振り分け部103が受信してから維持され続けているコネクションのコネクションIDである。
そして、次のステップS905で振り分け部103は、ステップS904で記憶したコネクションIDにより特定されるコネクションを介して、DBアクセス要求をブラウザ111に送信する。つまり、コネクションの維持のために応答を延期していた、XHRオブジェクトを用いたHTTP要求に対するHTTP応答として、振り分け部103は、DBアクセス要求をメッセージボディに含むHTTP応答を返す。
ステップS905は、図12のステップS712の一部である。また、ステップS905の具体例は、図13のステップS821である。
そして、ステップS905の実行後、図15の処理フローは終了するが、振り分け部103のスレッド自体は消滅しない。振り分け部103のスレッドでは、その後のブラウザ111からのDBアクセス結果の受信を契機に、図16の処理が始まる。
他方、ステップS902の検索の結果、コネクションが見つからなかった場合、振り分け部103はステップS906の処理を行う。ステップS906の処理は、図12においてジョインノードS708で表される待ち合わせのための処理である。
具体的には、振り分け部103は、待ち合わせのために、セッションIDごとにDBアクセス要求のキューをメモリ上に保持している。よって、ステップS906で振り分け部103は、図15の処理の開始の契機となったDBインタフェイス部102からのDBアクセス要求を、ステップS901で取得したセッションIDに対応するキューに追加する。
そして、図15の処理フローは終了するが、振り分け部103のスレッド自体は消滅しない。振り分け部103のスレッドでは、XHRオブジェクトを用いたロングポーリング用の新たなHTTP要求のブラウザ111からの受信を契機に、図16の処理が始まる。
さて、図16は、第2実施形態において振り分け部103がブラウザ111からの要求の受信を契機として行う処理のフローチャートである。例えば、図13のステップS801、S804、S808、S811、S815、S824、S828では、振り分け部103がブラウザ111からのHTTP要求を受信する。そして、振り分け部103は、HTTP要求の受信を契機として、図16の処理を開始する。
なお、HTTP要求を振り分け部103が受信すると、ブラウザ111とWebサーバ100の間のHTTPコネクションが確立する。したがって、図16の処理が開始された時点で何らかのコネクションが存在する。
ステップS1001で振り分け部103は、図11のステップS601と同様に、セッションがあるか否かを判断する。セッションがなければ処理はステップS1002に移行する。逆に、セッションが既に存在していれば、振り分け部103はセッションIDを認識し、処理はステップS1004に移行する。
ステップS1002で振り分け部103は、セッションを新規に作成する。具体的には、振り分け部103は、新たなセッションIDを発行する。ステップS1002が実行されるのは、例えば、図13のステップS801の要求の受信を契機として図16の処理が開始された場合である。
そして、次のステップS1003で振り分け部103は、HTTP応答のSet−CookieヘッダにステップS1002で発行したセッションIDを設定して、親ページ500をブラウザ111に返す。親ページ500の<iframe>要素501に付けられているsrc属性を”/”の代わりにHTTP要求のリクエストラインにあったパスとしておくことも可能である。ステップS1003の具体例は、図13のステップS802である。また、ステップS1003の実行後、図16の処理は終了する。
他方、セッションが既に存在する場合、ステップS1004で振り分け部103は、ブラウザ111から要求されたURIの種類を判定する。
要求されたURIが、上記(B1)のiframe113用のパスを含む場合、処理はステップS1005に移行する。例えば、図13のステップS804の要求の受信を契機として図16の処理が開始された場合、処理はステップS1005へと移行する。
また、要求されたURIが、上記(B2)のロングポーリング用のHTTP要求(つまり特定要求)を受け付けるためのパスを含む場合、処理はステップS1008に移行する。例えば、図13のステップS808またはS828の要求の受信を契機として図16の処理が開始された場合、処理はステップS1008へと移行する。
また、要求されたURIが、上記(B3)のDBアクセス結果の通知用のパスを含む場合、処理はステップS1013に移行する。例えば、図13のステップS824のHTTP要求の形でのDBアクセス結果の通知を振り分け部103が受信したことを契機として図16の処理が開始された場合、処理はステップS1013に移行する。
そして、要求されたURIが、上記(B1)〜(B3)のいずれのパスも含まない場合(すなわち、要求されたURIが、Webアプリケーション101が使うための通常のパスを示す場合)、処理はステップS1006に移行する。例えば、図13のステップS811またはS815の要求の受信を契機として図16の処理が開始された場合、処理はステップS1006へと移行する。
さて、(B1)のiframe113用のパスを含むURIへの要求をブラウザ111から受信した場合、振り分け部103は、ステップS1005において、設定ファイル106に基づくスクリプトをスクリプト生成部104に生成させる。そして、振り分け部103は、スクリプト生成部104に生成させたスクリプトを含むページを生成し、生成したページをブラウザ111に送付する。ステップS1005の実行後、図16の処理は終了する。
なお、ステップS1005の具体例は、図13のステップS805〜S807である。また、ステップS1005でスクリプト生成部104が生成するスクリプトの具体例は、図14の子ページ600の<head>要素内の<script>ブロックと<body>要素内の<script>ブロック604である。つまり、ステップS1005で振り分け部103が生成するページの例は、図14の子ページ600である。
さて、ブラウザ111から要求されたURIが、上記(B1)〜(B3)のいずれのパスも含まない場合、振り分け部103は、ステップS1006で、スレッドローカルな変数に、ステップS1001で認識したセッションIDを保存する。ここで保存されたセッションIDは、前述のとおり、図15のステップS901で参照される。
そして、次のステップS1007で振り分け部103は、Webアプリケーション101に処理を委譲する。具体的には、振り分け部103は、ブラウザ111から受信したHTTP要求をWebアプリケーション101に出力する。そして、振り分け部103による図16の処理は終了する。
なお、ステップS1006は図12のステップS702に対応し、ステップS1007は図12のステップS704の一部である。また、ステップS1006〜S1007の処理は、例えば、図13のステップS813においても行われ、ステップS817においても行われる。
また、(B2)のロングポーリング用のHTTP要求(つまり特定要求)を受け付けるためのパスを含むURIへの要求をブラウザ111から受信した場合、振り分け部103は、ステップS1008以降の処理を行う。
具体的には、ステップS1008で振り分け部103は、対応表105に新規エントリを挿入する。また、振り分け部103は、新規エントリのセッションIDフィールドに、ステップS1001で認識したセッションIDを設定する。そして、振り分け部103は、ロングポーリング用のHTTP要求の受信によってブラウザ111とWebサーバ100との間に確立したHTTPコネクションを識別するコネクションIDを、新規エントリのコネクションIDフィールドに設定する。ステップS1008は図12のステップS707に相当する。
そして、次のステップS1009で振り分け部103は、図15に関して説明したキューが空であるか否かを判断する。具体的には、振り分け部103は、ステップS1001で認識したセッションIDに対応するキューが空か否かを判断する。
キューが空の場合とは、振り分け部103が、DBインタフェイス部102からDBアクセス要求を受け取る前に、ロングポーリング用のHTTP要求を受信した場合である。よって、振り分け部103が次にDBインタフェイス部102からDBアクセス要求を受け取るまで、ロングポーリング用のHTTP要求に対するHTTP応答は延期される。つまり、振り分け部103が、今回受信したロングポーリング用のHTTP要求に対して現時点で行う処理はない。したがって、図16の処理は終了する。
逆に、キューが非空の場合とは、振り分け部103が、ロングポーリング用のHTTP要求を受信する前に、既にDBインタフェイス部102からDBアクセス要求を受け取っている場合である。よって、振り分け部103は、今回受信したロングポーリング用のHTTP要求に対するHTTP応答を延期せず、キューに蓄積されているDBアクセス要求をHTTP応答の形でブラウザ111に送信する。
つまり、ステップS1009でキューが非空の場合とは、図12のステップS710のガード条件が今まで満たされていなかったのが、ロングポーリング用のHTTP要求の受信によりガード条件が満たされた場合に相当する。そこで、キューが非空の場合、処理はステップS1010に移行する。
すると、ステップS1010で振り分け部103は、ステップS1008で対応表105に追加したエントリのコネクションIDを記憶し、ステップS1008で対応表105に追加したエントリを対応表105から削除する。ステップS1010は、図12のステップS711に対応する。
そして、次のステップS1011で振り分け部103は、キューから先頭のDBアクセス要求を取り出す。
また、次のステップS1012で振り分け部103は、ステップS1011で取り出したDBアクセス要求をブラウザ111に送信する。具体的には、振り分け部103は、キューから取り出したDBアクセス要求を、今回受信したHTTP要求(すなわちXHRオブジェクトによるロングポーリング用のHTTP要求)に対するHTTP応答に含めて、ブラウザ111に返す。そして、図16の処理は終了する。なお、ステップS1011〜S1012は図12のステップS712の一部である。
ところで、振り分け部103は、(B3)のDBアクセス結果の通知用のパスを含むURIへの要求をブラウザ111から受信した場合、ステップS1013〜S1014の処理を行う。ステップS1013〜S1014の処理は、図12のステップS712のガード条件が満たされたときに行われる処理だが、図12には明示されていない。
具体的には、振り分け部103はステップS1013において、ブラウザ111から受信したDBアクセス結果に対応する、DBインタフェイス部102からのDBアクセス要求に対して、DBアクセス結果を返す。ステップS1013の具体例は、図13のステップS825である。
なお、第1実施形態と同様に第2実施形態でも、振り分け部103は、DBインタフェイス部102からのDBアクセス要求を受け取ったのと同じスレッドでブラウザ111からDBアクセス要求を受信する。よって、振り分け部103は、ブラウザ111から受信したDBアクセス結果がどのDBアクセス要求に対応するのかを認識することができる。もちろん、実施形態によっては、DBアクセス要求を識別する要求IDが、DBアクセス要求とDBアクセス結果の対応関係の管理のために使われてもよい。
また、次のステップS1014で振り分け部103は、DBアクセス結果の通知のためにブラウザ111からXHRオブジェクトを用いて送られたHTTP要求に対して、メッセージボディが空のHTTP応答を返す。そして、図16の処理は終了する。
以上のとおり、第2実施形態によれば、ブラウザ111がDBアクセス代行スクリプト114にしたがって送信するHTTP要求に対する応答を、振り分け部103が延期することにより、ブラウザ111とWebサーバ100の間のコネクションが維持される。また、応答が返されて、その結果としてコネクションが切れると、ブラウザ111はDBアクセス代行スクリプト114にしたがって新たなHTTP要求を送信する。したがって、新たなHTTP要求に対する応答が延期されている間は、新たなコネクションが維持される。
つまり、第2実施形態では、第1実施形態のように1つのコネクションが維持され続けるわけではなく、コネクションが順次切り換わる。しかし、第2実施形態によれば、1つのコネクションが切れるとすぐに新たなコネクションが確立される。したがって、第2実施形態は、ブラウザ111とWebサーバ100の間に常にコネクションが維持されている状態とほとんど変わらない状態を実現することができる。
つまり、第2実施形態によれば、DBアクセス要求がエンキューされている間の短い待ち時間が生じることはあり得る。しかし、そのような短い待ち時間を除けば、Webアプリケーション101によるDBアクセス要求がいつ生じても、振り分け部103はすぐにDBアクセス要求をブラウザ111に中継することができる。
そして、ブラウザ111がDBアクセス代行スクリプト114にしたがってDBアクセスを代行し、DBアクセス結果は振り分け部103とDBインタフェイス部102を介して最終的にWebアプリケーション101に出力される。したがって、Webアプリケーション101は、直接DBサーバ120にアクセスすることが許されなくても、DBアクセス結果を得ることができる。
このように、第2実施形態によれば、インタフェイス・サーバまたは中継サーバなどの付加的な装置がなくても、Webアプリケーション101が、ファイアウォール130で隔てられたイントラネット140内のDB121のデータを使って処理を行うことができる。また、Webアプリケーション101は、DB121のデータを一時的かつ部分的に使うだけであり、DB121のデータがWebサーバ100に不揮発的に長期にわたって保存されるわけではない。したがって、第2実施形態は、DB121に機密情報が含まれる場合にも好適である。
ところで、以上説明した第2実施形態は、同じ1つのXHRオブジェクトによる1つのHTTP要求が、図13のステップS824のDBアクセス結果の通知と、ステップS828のロングポーリング用の要求を兼ねるように変形されてもよい。具体的には、例えば以下のような変形が可能である。
まず、図14の関数execute2()は、XHRオブジェクトを用いてHTTP要求の形でDBアクセス結果をWebサーバ100に送信した後、対応するHTTP応答を受信したら、受信した応答のメッセージボディを返り値として返すように変形される。つまり、変形された関数execute2()は、あるDBアクセス要求を代行してDBアクセス結果をWebサーバ100に返すとともに、次のDBアクセス要求を受け取るための関数である。
また、図14の関数main()は、以下の(D1)〜(D3)のステップを実行した後、(D4)のステップを繰り返すように変形される。
(D1)新規XHRオブジェクトを生成し、新規XHRオブジェクトによるロングポーリング用のHTTP要求(すなわち、(B2)の特定のパスに対する特定要求)を送信するステップ。
(D2)上記(D1)の要求に対する応答を待ち、応答を受信したら、受信した応答からDBアクセス要求(すなわち最初のDBアクセス要求を表すSQL文)を抽出するステップ。
(D3)関数execute2()に引数として与えるための変数(説明の便宜上“q”とする)に、上記(D2)で抽出したSQL文の文字列を代入するステップ。
(D4)変数qを引数として与えて関数execute2()を呼び出し、返り値(すなわち次のDBアクセス要求を表すSQL文)を取得し、取得した返り値を変数qに代入するステップ(つまり、“q=execute2(q);”というステップ)。
また、上記(B3)のDBアクセス結果の受信用のパスは、本変形例では不要である。そして、振り分け部103による図16の処理は、次のように変形される。
すなわち、ステップS1004で判定されたパスが、ロングポーリング用のHTTP要求を受け付けるための上記(B2)のパスだった場合、振り分け部103は、受信したHTTP要求のメッセージボディが空か否かを判断する。そして、メッセージボディが空の場合は、DBアクセス結果の通知は行われていないので、振り分け部103は、ステップS1008以降の処理を行う。逆に、メッセージボディが非空の場合は、振り分け部103はステップS1013の処理を行い、次のステップS1014の処理は省略し、その代わりに続けてステップS1008以降の処理を行う。
例えば以上のような変形により、図13のステップS824とS828を同じ1つのHTTP要求で実現することが可能となる。その結果、Webサーバ100とクライアントマシン110の間のトラフィックを削減することができる。
続いて、上記の第1実施形態と第2実施形態のいずれに対しても適用可能な変形の例とを説明する。具体的には、設定ファイル106の変形およびそれにともなう処理の変形について、図17〜19を参照して説明する。
図17は、設定ファイル106の他の例を示す図である。図2の設定ファイル106aは、ブラウザ111がDBサーバ120にアクセスするための「DBアドレス」という項目のみを含む。しかしながら、他の項目をさらに含む設定ファイル106が使われてもよい。
例えば、図17の設定ファイル106bは、設定ファイル106aと同様のDBアドレスに加えて、「プライベートキー」という項目を含む。図17では説明の便宜上、プライベートキーの値の例として“abcdef0123456789”という値が例示されているが、もちろん、プライベートキーの値は任意である。
設定ファイル106bに記憶されるプライベートキーは、Webサーバ100のプライベートキー(換言すれば、Webアプリケーション101を提供するSaaSベンダあるいはASPのプライベートキー)である。また、対応するパブリックキーが、DBサーバ120に予め記憶される。
そして、設定ファイル106bが使われる変形例においては、DBアクセス要求がブラウザ111に送信されるとき、署名が付けられる。具体的には第1実施形態と第2実施形態はそれぞれ以下のように変形されてもよい。
第1実施形態がプライベートキーを使うように変形される場合の変更点は次のとおりである。
まず、図9の関数execute1()は、もう1つの引数として署名をとるように変形される。さらに、関数execute1()は、XHRオブジェクトを用いてDBアクセス要求(すなわち引数sqlで表されるSQL文)をDBサーバ120に送信するときに、署名も一緒に同じHTTP要求のメッセージボディに含めて送信するように変形される。
また、本変形例の振り分け部103は、図10のステップS503において、署名を生成する。そして、振り分け部103は、スクリプト生成部104に対して、DBアクセス要求を表すSQL文だけでなく、署名も、スクリプトの生成に用いるための情報として指定する。すると、スクリプト生成部104は、振り分け部103から指定されたSQL文と署名を引数とする関数execute1()の呼び出しステートメントを含む<script>ブロックを生成する。以上のようにして生成された<script>ブロックを含むチャンクが、図10のステップS504で送信される。
なお、振り分け部103による署名の生成方法と、DBサーバ120による認証処理の内容は、実施形態に応じて様々であってよい。
例えば、振り分け部103は、ステップS503の実行時に、タイムスタンプを取得する。また、振り分け部103は、SHA(Secure Hash Algorithm)−1などの暗号学的ハッシュ関数を用いてSQL文からハッシュ値を計算する。そして、振り分け部103は、タイムスタンプとハッシュ値を連結した文字列をプライベートキーで暗号化することにより、署名を生成する。
すると、SQL文と署名を引数とする関数execute1()をブラウザ111が実行すると、SQL文とともに署名がDBサーバ120に送信される。DBサーバ120は、署名をパブリックキーで復号することによりタイムスタンプとハッシュ値を得る。また、DBサーバ120は、ブラウザ111から送信されたSQL文から、振り分け部103が使ったのと同じハッシュ関数を用いてハッシュ値を計算する。
DBサーバ120は、復号と計算によりそれぞれ得られた2つのハッシュ値を比較する。そして、2つのハッシュ値が異なれば、DBサーバ120は、「不正なDBアクセス要求を受信した」と判断して適宜のエラー処理を行ってもよい。
また、DBサーバ120は、リプレイ攻撃への対策として、復号により得たタイムスタンプとハッシュ値のペアを、所定時間の間メモリ上のテーブルに記憶してもよい。そして、DBサーバ120は、復号と計算によりそれぞれ得られた2つのハッシュ値が同じ場合、復号により得たタイムスタンプとハッシュ値のペアとまったく同じペアがテーブルに記憶されているか否かをチェックする。もし同じペアがテーブルに記憶されている場合は、DBサーバ120は「リプレイ攻撃を受けた」と判断して適宜のエラー処理を行ってもよい。
また、DBアクセス要求の種類によっては、同じ要求の繰り返しが許容されない場合があり得る。例えば、同じデータに対する参照要求の繰り返しは許容されるが、同じデータに対する削除要求の繰り返しは許容されないかもしれない。
そこで、DBサーバ120は、上記のテーブルの検索によって同じペアが見つからなかった場合、さらに、次のようなチェック処理を行ってもよい。すなわち、繰り返しが許容されない種類のDBアクセス要求を受けた場合、DBサーバ120は、復号により得たハッシュ値と同じハッシュ値がテーブルに記憶されているか否かをチェックしてもよい。そして、もし同じハッシュ値が見つかれば、DBサーバ120はエラー処理を行ってもよい。
また、DBサーバ120とWebサーバ100は、例えばNTP(Network Time Protocol)などによって正しい時刻に同期されていてもよい。DBサーバ120は、復号により得たタイムスタンプと、現在時刻との差に応じて、適宜のエラー処理を行ってもよい。例えば、DBサーバ120は、時間差が閾値以上の場合はエラー処理を行ってもよい。
そして、以上例示したようなエラー処理の対象にならないDBアクセス要求に対してのみ、DBサーバ120は、DB121への実際のアクセスを行ってもよい。
また、第2実施形態がプライベートキーを使うように変形される場合の変更点は次のとおりである。
まず、図14の関数execute2()は、もう1つの引数として署名をとるように変形される。さらに、関数execute2()は、XHRオブジェクトを用いてDBアクセス要求(すなわち引数sqlで表されるSQL文)をDBサーバ120に送信するときに、署名も一緒に同じHTTP要求のメッセージボディに含めて送信するように変形される。そして、図14の関数main()は、上記(C2)のステップにおいて、振り分け部103より受信したHTTP応答から、SQL文だけでなく署名も抽出するように、変形される。
また、振り分け部103は、図15のステップS905または図16のステップS1012において、署名を生成する。そして、振り分け部103は、ステップS905またはS1012で送信するHTTP応答のメッセージボディに、DBアクセス要求を表すSQL文だけでなく、生成した署名も含める。
なお、振り分け部103による署名の生成方法と、DBサーバ120による署名を用いた認証処理の内容は特に限定されない。第1実施形態の変形に関して例示したような、タイムスタンプとハッシュ関数を用いた署名が使われてもよいし、そのような署名を用いた認証がDBサーバ120により行われてもよい。
ここで、図17の説明に戻る。図2の設定ファイル106aの代わりに、例えば図17の設定ファイル106cが用いられてもよい。設定ファイル106cは、設定ファイル106aと同様のDBアドレスに加えて、「イントラネット上のテーブル名」と「インターネット上のテーブル名」という2つの項目を含む。以下ではこれら2つの項目により表される情報を「所在情報」ともいう。
設定ファイル106cの例では、具体的には、「イントラネット上のテーブル名」として、「顧客」および「注文」という2つのテーブル名が記憶されており、「インターネット上のテーブル名」として「商品」および「カート」という2つのテーブル名が記憶されている。つまり、所在情報107は、「顧客」テーブルと「注文」テーブルがイントラネット140内にあることと、「商品」テーブルと「カート」テーブルがイントラネット140外にあることを示す。
より一般化して言えば、所在情報107は、DB121が含む各テーブルの識別情報をDB121と対応づけるとともに、DB181が含む各テーブルの識別情報をDB181と対応づける情報である。そして、図17では、各テーブルの識別情報として、テーブル名が使われている。
所在情報107を含む設定ファイル106cは、DBがイントラネット140と外部ネットワーク150に分散している図18のような場合に使われる。また、設定ファイル106cが使われる場合、DBインタフェイス部102の動作が図19のように変更される。
図18は、変形例のシステム構成図である。図1と図18の違いは以下のとおりである。
図18の変形例においては、図6のフローチャートにしたがって動作する図1のDBインタフェイス部102の代わりに、図19のフローチャートにしたがって動作するDBインタフェイス部102aが設けられる。なお、DBインタフェイス部102aがWebアプリケーション101に対して提供するインタフェイスは、DBインタフェイス部102がWebアプリケーション101に対して提供するインタフェイスと同じである。
また、外部ネットワーク150内に、Webサーバ100のDBインタフェイス部102aからアクセス可能なDBサーバ180がさらに設けられる。また、DBサーバ180はDB181を記憶する。
なお、DBインタフェイス部102aも、例えば図4のCPU201がプログラムを実行することにより、実現される。また、DBインタフェイス部102aはDBサーバ180と通信するが、DBインタフェイス部102aの通信機能は、例えば図4のネットワーク接続装置203により実現される。
図17の設定ファイル106cの例によれば、イントラネット140内のDB121に含まれるテーブルは、「顧客」および「注文」という2つのテーブルである。また、設定ファイル106cの例によれば、外部ネットワーク150内のDB181に含まれるテーブルは、「商品」および「カート」という2つのテーブルである。
DBインタフェイス部102aは、設定ファイル106cを参照し、アクセス対象のテーブルに応じて、ブラウザ111にDBアクセスを代行させるか、DBインタフェイス部102a自身がDBアクセスを行うかを決定する。そして、DB121へのDBアクセス要求が生じた場合は、DBインタフェイス部102aは、ブラウザ111にDBアクセスを代行させるために、振り分け部103にDBアクセス要求を出力する。逆に、DB181へのDBアクセス要求が生じた場合は、DBインタフェイス部102a自身がDBサーバ180にDBアクセス要求を送信する。
ところで、DB181へのDBアクセスには、Webサーバ100とDBサーバ180の間のRTT(Round Trip Time)以上の時間がかかる。また、DB121へのDBアクセスには、Webサーバ100とクライアントマシン110の間のRTTと、クライアントマシン110とDBサーバ120の間のRTTの和以上の時間がかかる。
そして、外部ネットワーク150は、より具体的には、SaaSベンダあるいはASPのLANである。したがって、Webサーバ100とDBサーバ180の間のRTTは、Webサーバ100とクライアントマシン110の間のRTTと比較すると、大幅に短い。つまり、DB181へのDBアクセスにかかる時間は、DB121へのDBアクセスにかかる時間よりも大幅に短い。
詳しくは後述するが、あるデータをDB121とDB181のいずれに格納するのが好ましいかは、DBアクセスにかかる時間の違いも考慮に入れたうえで決められることが好ましい。
なお、図18の例ではWebサーバ100とDBサーバ180が別のサーバだが、実施形態によっては、物理的には1台のサーバがWebサーバ100とDBサーバ180を兼ねていてもよい。逆に、負荷分散のためにDBサーバ180が物理的には複数のサーバであってもよい。
さて、図19は、変形例のDBインタフェイス部102aの動作を説明するフローチャートである。
ステップS1101でDBインタフェイス部102aは、Webアプリケーション101からDBアクセス要求を受け取るまで待つ。ステップS1101は、図6のステップS201と同様である。
そして、DBインタフェイス部102aがWebアプリケーション101からDBアクセス要求を受信すると、処理はステップS1102に移行する。ステップS1102でDBインタフェイス部102aは、設定ファイル106cの所在情報107を参照する。
そして、次のステップS1103でDBインタフェイス部102aは、DBアクセス要求により要求されたテーブルがDB121とDB181のどちらに含まれるのかを確認する。DBアクセス要求により要求されたテーブルが、クライアントマシン110から見てインターネット側のDB181に含まれる場合、処理はステップS1104に移行する。逆に、DBアクセス要求により要求されたテーブルが、イントラネット140内のDB121に含まれる場合、処理はステップS1105に移行する。
例えば、「商品」テーブルまたは「カート」テーブルに対するDBアクセス要求をDBインタフェイス部102aがWebアプリケーション101から受け取った場合、処理はステップS1104に移行する。逆に、「顧客」テーブルまたは「注文」テーブルに対するDBアクセス要求をDBインタフェイス部102aがWebアプリケーション101から受け取った場合、処理はステップS1105に移行する。
ステップS1104でDBインタフェイス部102aは、DBサーバ180に直接アクセスしてDBアクセス結果を取得する。そして、処理はステップS1107に移行する。
他方、ステップS1105でDBインタフェイス部102aは、図6のステップS202と同様に、Webアプリケーション101から受け取ったDBアクセス要求を振り分け部103に出力する。
そして、次のステップS1106でDBインタフェイス部102aは、図6のステップS203と同様に、振り分け部103からDBアクセス結果を受け取るまで待つ。DBインタフェイス部102aが振り分け部103からDBアクセス結果を受け取ると、処理はステップS1107に移行する。
ステップS1107でDBインタフェイス部102aは、図6のステップS204と同様に、DBアクセス結果をWebアプリケーション101に返す。そして、処理はステップS1101に戻る。
続いて、図18〜19の変形例の利点について説明する。図18〜19の変形例の利点は、データの特性に応じてDB121とDB181の両方が利用可能な点である。
Webアプリケーション101の種類は様々であり、Webアプリケーション101が利用するデータの種類も様々である。そして、ある種のデータは、イントラネット140内のDB121に格納されることが好ましく、別の種類のデータは、Webサーバ100から直接アクセス可能なDBサーバ180内のDB181に格納されることが好ましい。
例えば顧客の個人情報や注文履歴などの機密性の高いデータは、DB121に格納されることが好ましい。なぜなら、企業ユーザは、外部ネットワーク150からの情報漏洩のリスクをおそれて、イントラネット140の外部に機密性の高いデータが保存されることを嫌うからである。図17の所在情報107の例でも、顧客の個人情報を含む「顧客」テーブルと、顧客の注文履歴を含む「注文」テーブルは、「イントラネット上のテーブル名」の項目に登録されている。
逆に、DB181に格納するのに適したデータの例は、たとえ漏洩しても被害が限定的な機密性の低いデータや、そもそも公開されていて機密性のないデータである。例えば、Webアプリケーション101がオンラインショッピングのアプリケーションの場合、商品は公開されているので、商品に関するデータは機密性がない。
また、「カート」テーブルのデータは、例えば、一時的に顧客のIDと商品のIDを対応づけるだけのデータかもしれない。すると、たとえ「カート」テーブルのデータが漏洩しても、顧客の住所や氏名などの個人情報そのものが漏洩するわけではないので、被害は限定的である。そして、限定的な被害ならば許容される場合もあり得る。よって、図17の所在情報107の例では、「商品」テーブルと「カート」テーブルが「インターネット上のテーブル名」の項目に登録されている。
また、あるデータがDB121とDB181のどちらに格納される方が好ましいか、ということに関しては、データの機密性以外の観点もある。
例えば、頻繁にアクセスされるデータ(すなわち、読み書きが多く発生するデータ)は、DB181に格納するのに適している。なぜなら、DB121に格納されたデータをWebアプリケーション101が利用するためには、以下の(E1)〜(E4)の通信が生じるからである。
(E1)Webサーバ100の振り分け部103から、クライアントマシン110のブラウザ111への、DBアクセス要求の送信
(E2)ブラウザ111からDBサーバ120へのDBアクセス要求の送信
(E3)DBサーバ120からブラウザ111へのDBアクセス結果の送信
(E4)ブラウザ111から振り分け部103へのDBアクセス結果の送信
つまり、頻繁にアクセスされるデータがDB121に格納されている場合、頻繁に生じるアクセスのたびに(E1)〜(E4)の通信が生じる。その結果、Webサーバ100とクライアントマシン110の間、およびイントラネット140内における通信トラフィックが増大する。通信トラフィックの増大は、例えば他のネットワークアプリケーションに悪影響を及ぼすおそれもある。
そして、もちろん通信には遅延がともなう。また、上記のとおり、Webサーバ100とDBサーバ180の間のRTTよりも、Webサーバ100とクライアントマシン110の間のRTTの方が大幅に長い。
よって、DB181内のデータが使われる場合よりも、DB121内のデータが使われる場合の方が、ユーザにとっての応答時間も長い。なお「ユーザにとっての応答時間」とは、ユーザがiframe112内のページに対して、クリックや入力などの操作を行ってから、Webアプリケーション101から返された応答内容がiframe112内に表示されるまでの時間のことである。
以上のとおりなので、頻繁にアクセスされるデータは、たとえデータサイズそのものが小さいとしても、通信トラフィックの抑制およびユーザにとっての利便性の観点からは、DB181に格納されることが好ましい。
逆に言えば、あまりアクセスされないデータは、DB121に格納されていても、ユーザにとっての利便性をあまり損なわない。また、あまりアクセスされないデータへのアクセスによって生じる通信トラフィックは、たとえデータサイズそのものが比較的大きいとしても、単位時間あたりでは少ない。
そして、SaaSベンダ(あるいはASP)によっては、DB181に格納されるデータの量に応じてユーザに課金する。すると、データサイズが大きいデータは、金銭コストの観点からは、DB121に格納されることが好ましい。
例えば、ある種のデータは、新しいエントリが次々と作成されて量が増えていく一方で、めったに参照されないかもしれない。例えば、ある種のログデータは、大量に蓄積されるが、めったに参照されないかもしれない。このようにデータサイズが大きく、かつ参照頻度の少ないデータは、金銭コストの観点からDB121に格納されることが好ましい場合がある。そして、参照頻度の少ないデータは、たとえデータサイズが大きくても、DB121に格納されたことによって通信トラフィックやユーザの利便性にそれほど悪影響を与えない。
以上のように、各種のデータは、様々な観点から、「DB121とDB181のどちらに格納する方が好ましいか」ということが異なる。そして、図18〜19に示した変形例によれば、データの特性に応じてDB121またはDB181の適切な方に各データが格納された環境において、Webアプリケーション101は、DB121とDB181のいずれに格納されたデータも利用可能である。
また、Webアプリケーション101は、データがDB121とDB181のどちらに格納されているかを判断する必要がない。つまり、データの所在はWebアプリケーション101に対して隠蔽されている。よって、Webアプリケーション101は、DB121のデータに対しても、DB181のデータに対しても、同じロジックでDBアクセス要求を発行することができる。したがって、既存のWebアプリケーション101も、図18のシステムにおいて利用可能である。
なお、図19に関する上記の説明では簡単のため、「1つのDBアクセス要求では、DB121内のテーブルのみに対してアクセスが要求されるか、またはDB181内のテーブルのみに対してアクセスが要求される」と仮定している。しかし、1つのDBアクセス要求が、DB121内の「注文」テーブルとDB181内の「商品」テーブルの両方へのアクセスを要求する場合もあり得る。例えば、SQLのSELECT文のFROM句に「注文」テーブルと「商品」テーブルの双方が指定されている場合、当該SELECT文は、DB121とDB181の両方へのアクセスを要求するDBアクセス要求である。
1つのDBアクセス要求が、DB121内のテーブルとDB181のテーブルの両方へのアクセスを要求する場合、DBインタフェイス部102aは、例えば以下の(F1)〜(F3)の処理を行ってもよい。
(F1)Webアプリケーション101から受け取ったDBアクセス要求から、DB121内のテーブルのみに対するDBアクセス要求を生成し、生成したDBアクセス要求を使ってステップS1105〜S1106の処理を行う処理。
(F2)Webアプリケーション101から受け取ったDBアクセス要求から、DB181内のテーブルのみに対するDBアクセス要求を生成し、生成したDBアクセス要求を使ってステップS1104の処理を行う処理。
(F3)Webアプリケーション101から受け取ったDBアクセス要求におけるテーブル結合の種類や結合条件に応じて、(F1)と(F2)でそれぞれ得られたDBアクセス結果から、最終的なDBアクセス結果を生成する処理。
なお、Webアプリケーション101から出力されたDBアクセス要求に指定されている結合条件(例えばSQL文のWHERE句などに指定されている条件)に応じて、(F1)の処理が先に実行されてもよく、(F2)の処理が先に実行されてもよい。あるいは、結合条件によっては、(F1)と(F2)が並列に実行されてもよい。
また、(F3)の処理は、具体的には、直積演算や、Webアプリケーション101から出力されたDBアクセス要求に指定されている条件による絞り込み演算(すなわち選択演算)などを含む。
ところで、本発明は上記実施形態に限られるものではない。上記の説明においてもいくつかの変形について説明したが、上記実施形態は、さらに例えば下記の観点から様々に変形することもできる。そして、上記および下記の変形は、相互に矛盾しない限り、任意に組み合わせることが可能である。
変形の第1の観点は、データ構造に関する。例えば、図2には、対応表105の具体例として、対応表105aがテーブル形式で図示されている。しかし、対応表105のデータ構造は実施形態に応じて任意であり、連想配列、線形リスト、その他の任意のデータ構造が利用可能である。
また、図2と図17には設定ファイル106の具体例として設定ファイル106a〜106cがテーブル形式で図示されている。しかし、設定ファイル106のフォーマットも実施形態に応じて任意である。また、設定ファイル106がプライベートキーと所在情報107の双方を含んでいてもよい。
変形の第2の観点は、「複数のDBアクセス要求がどのように処理されるか」という観点である。1つのページの生成が複数のDBアクセス要求をともなう場合、図8のステップS417〜S427の一連の処理または図13のステップS818〜S826の一連の処理が、DBアクセス要求の数だけ繰り返されてもよい。しかし、Webアプリケーション101は、複数のDBアクセス要求をまとめて一度にDBインタフェイス部102に出力してもよい。
例えば、あるページの生成が5つのSQL文の実行をともなう場合、ステップS417〜S427の一連の処理またはステップS818〜S826の一連の処理が5回繰り返されてもよい。しかし、Webアプリケーション101は、5つのSQL文をデリミタ文字“;”で区切って1つに連結した文字列を、ステップS417またはステップS818でDBインタフェイス部102に出力してもよい。
すると、DBインタフェイス部102から振り分け部103へ、振り分け部103からブラウザ111へ、そしてブラウザ111からDBサーバ120へ、と送られるDBアクセス要求は、5つのSQL文が連結された文字列により表される。そこで、DBサーバ120は、5つのSQL文をそれぞれ実行し、5つのSQL文それぞれに対するDBアクセス結果を得る。そして、DBサーバ120は、5つのDBアクセス結果を適宜のフォーマットにしたがって連結し、連結した5つのDBアクセス結果を、1つのHTTP応答によりブラウザ111に返す。
すると、連結された5つのDBアクセス結果は、ブラウザ111から振り分け部103へ、振り分け部103からDBインタフェイス部102へ、DBインタフェイス部102からWebアプリケーション101へと送られる。Webアプリケーション101は、5つのDBアクセス結果をそれぞれ抽出し、抽出したDBアクセス結果に基づいてページを生成し、生成したページをブラウザ111に返す。
以上のように、複数のDBアクセス要求がまとめて一緒に送信され、対応する複数のDBアクセス結果がまとめて一緒に返信されてもよい。すると、Webサーバ100とクライアントマシン110の間およびクライアントマシン110とDBサーバ120の間の通信トラフィックの削減という効果が得られるし、ユーザにとっての応答時間の短縮という効果も得られる。
変形の第3の観点は、DBの種類に関する。DB121とDB181は、リレーショナルDBでもよいが、他の種類のDBでもよい。例えば、XMLDB(Extensible Markup Language Database)またはKVS(Key-Value Store)が使われてもよい。DBの種類に応じて、DBアクセス要求を表す問い合わせ言語も異なる。
変形の第4の観点は、クロスドメイン非同期通信の具体的実装に関する。上記の説明では、具体的な実装例として、XHRオブジェクトによるHTTP通信を利用する実施形態について詳しく説明した。しかし、具体的実装は実施形態に応じて様々であってよい。
例えば、クロスドメイン非同期通信のためには、上述のとおりレベル2のXHRオブジェクトを用いる実装が採用されてもよい。しかし、実施形態によっては、JSONP(JavaScript Object Notation with Padding)またはXDR(XDomainRequest)オブジェクトを用いる実装が採用されてもよい。
変形の第5の観点は、タイムアウトに関する。Cometコネクションの維持に関して、上記では説明を省略したが、タイムアウトによりコネクションが切れる場合もあり得る。そこで、タイムアウトを防ぐための適宜の変形、または、タイムアウトに応じて再びHTTP要求をブラウザ111に送信させるための適宜の変形が、上記実施形態に適用されてもよい。
例えば、第1実施形態の振り分け部103は、DBインタフェイス部102から一定時間以上DBアクセス要求を受け取らない場合、子ページ400の新たなチャンクとして、適宜のダミーデータを含むチャンクを送信してもよい。また、第2実施形態におけるメインルーチンの関数定義603は、ロングポーリング用のHTTP要求がタイムアウトしたら、ロングポーリング用のHTTP要求を送信しなおすためのコードを含んでいてもよい。
変形の第6の観点は、振り分け部103やDBインタフェイス部102の具体的実装に関する。具体的実装は実施形態に応じて様々に異なっていてよい。
例えば、振り分け部103がスレッドローカルな変数を使ってセッションIDを記憶する例について上記で説明したが、振り分け部103がセッションIDの認識するために他の実装が採用されてもよい。例えば、実施形態によっては、セッションIDはコールスタックに格納されていてもよい。
変形の第7の観点は、DBアクセス代行スクリプト114に関する。第1実施形態に関して図9に例示した子ページ400の送信においては、最初にアドレス代入文402と関数定義403を含むチャンク401が送信される。そして、その後は、DBアクセス要求の発生のたびに、関数呼び出しステートメントのみを含む短い<script>ブロックが送信される。このように関数定義403を利用することで、第1実施形態では、Webサーバ100とクライアントマシン110の間の通信トラフィックが抑制される。
しかし、通信トラフィックが増えてもかまわないならば、次のような変形も可能である。すなわち、最初のチャンク401は<script>ブロックを含まなくてもよい。その代わり、DBアクセス要求の発生のたびに、(G1)〜(G3)をすべて含む<script>ブロックがスクリプト生成部104により生成され、振り分け部103によりブラウザ111へと送信されてもよい。
(G1)アドレス代入文402
(G2)DBアクセス要求を表すSQL文の文字列を変数sqlに代入する代入文
(G3)関数定義403の内容と同様の内容のスクリプト
また、図9では関数定義403の外にアドレス代入文402があり、図14では関数定義602の外にアドレス代入文601がある。しかし、実施形態によっては、関数execute1()またはexecute2()が、引数としてイントラネット140内のDBサーバのアドレスを受け取るように変形されてもよい。
図1には1台のDBサーバ120のみが図示されているが、イントラネット140内に複数のDBサーバがあってもよい。そして、設定ファイル106には、テーブル名ごとにイントラネット140内のDBサーバのアドレス(つまりURI)が記憶されていてもよい。
すると、第1実施形態のスクリプト生成部104は、次のように変形されてもよい。
すなわち、DBアクセス要求を表すSQL文を振り分け部103から指定されたとき、スクリプト生成部104は、設定ファイル106を参照して、アクセス先のDBサーバのアドレスを特定する。そして、スクリプト生成部104は、特定したアドレスを引数として含む、関数execute1()の呼び出しステートメントを生成する。
あるいは、第2実施形態の振り分け部103とスクリプト生成部104は、次のように変形されてもよい。
振り分け部103は、DBアクセス要求をブラウザ111に送信するときに、DBアクセス要求に応じたアクセス先のDBサーバのアドレスもブラウザ111に送信する。なお、振り分け部103は、設定ファイル106を参照することで、アクセス先のDBサーバのアドレスを特定することができる。
また、スクリプト生成部104は、次のように変形されたメインルーチンの関数定義603を生成する。すなわち、本変形例の関数main()は、HTTP応答から、DBアクセス要求を表すSQL文とともにDBサーバのアドレスを抽出し、抽出したSQL文とアドレスを引数として関数execute2()を呼び出すように、定義される。
なお、もちろん関数名や変数名は実施形態に応じて任意に変更してよい。
変形の第8の観点は、予約されるパスに関する。
第1実施形態では、図11のステップS605に示すように、子ページ400の読み込み要求とDBアクセス結果の通知がメソッドにより区別される。しかし、子ページ400の読み込み要求とDBアクセス結果の通知が、第2実施形態のようにパスによって区別されてもよい。
つまり、第1実施形態は、2つの予約されたパスを使うように変形されてもよい。そして、振り分け部103は、受信したHTTP要求に指定されたURIに含まれるパスのみから、受信したHTTP要求が、子ページ400の読み込み要求か、DBアクセス結果の通知か、Webアプリケーション101に対する要求か、を判断してもよい。
逆に、第2実施形態では、上記(B1)〜(B3)の3つのパスが予約され、使われているが、予約されるパスは2つでもよい。
例えば、(B1)のiframe113用のパスと、(B3)のDBアクセス結果の通知用のパスが同じであってもよい。その場合、iframe113への子ページ600の読み込み要求ではGETメソッドが指定され、DBアクセス結果の通知ではPOSTメソッドが指定されるので、振り分け部103は、メソッドに基づいて、子ページ600の読み込み要求とDBアクセス結果の通知を区別することができる。
あるいは、(B1)のiframe113用のパスと、(B2)のロングポーリング用のHTTP要求を受け付けるためのパスが同じであってもよい。ロングポーリング用のHTTP要求のメソッドとしては、第2実施形態ではGETメソッドが使われるが、POSTメソッドが使われる場合でもロングポーリングは可能である。
そこで、(B1)と(B2)のパスが同じ場合、iframe113への子ページ600の読み込み要求ではGETメソッドが指定され、ロングポーリング用のHTTP要求ではPOSTメソッドが指定されてもよい。振り分け部103は、ロングポーリング用のHTTP要求のメッセージボディを無視して、単にHTTP応答を返すときにHTTP応答のメッセージボディにDBアクセス要求を示す文字列(例えばSQL文)を設定すればよい。振り分け部103は、メソッドに基づいて、子ページ600の読み込み要求とロングポーリング用のHTTP要求を区別することができる。
なお、本明細書および図面におけるパスの具体例は単なる例示である。実施形態に応じて任意に決められたパスが「特定要求」のための「特定のパス」として使われてよい。また、第2実施形態のように(B1)〜(B3)の3つのパスが予約される場合、3つのパスは任意に決められてよい。
例えば、上記に例示した“/_reservedForComet”などのパスは、Webサーバ100のドキュメントルートの直下のパスだが、ドキュメントルートの直下ではないパスも利用可能である。また、上記に例示したパスは拡張子を含まないが、もちろん拡張子を含むパスが利用されてもよい。
また、上記ではブラウザ111から振り分け部103が受信したHTTP要求の種類を区別するために、パスとメソッドが使われる。しかし、URIに含まれるパスとクエリ・ストリングの組み合わせによりHTTP要求の種類が区別される実施形態も可能である。
変形の第9の観点はマルチテナンシ(multi-tenancy)に関する。上記の説明においては、Webアプリケーション101がマルチテナント環境に対応しているか否かについて特に言及しなかった。しかし、次のような変形により、マルチテナント型のWebアプリケーション101にも上記実施形態は適用可能である。
すなわち、テナントごとに予め用意された複数の設定ファイル106がWebサーバ100に記憶される。また、上記のとおり、実施形態に応じて1つ、2つ、または3つの予約されたパスが使われるが、各テナントごとに異なるパスが予約される。さらに、Webサーバ100には、各テナントについて、当該テナントのIDと、当該テナント用に予約されたパスと、当該テナント用の設定ファイル106とを対応づける情報が予め格納される。
すると、振り分け部103は、HTTP要求を受信したとき、受信したHTTP要求がどのテナント用に予約されたパスへの要求であるかに応じて、どのテナントのブラウザ111からHTTP要求を受信したのかを認識することができる。したがって、振り分け部103は、スクリプト生成部104にスクリプトの生成を指示する場合に、どの設定ファイル106からDBアドレスを読み出せばよいかを正しく指示することができる。
また、図2のように設定ファイル106においてプライベートIPアドレスを含むURIが使われることは、マルチテナント環境におけるセキュリティ保持にも有益である。なぜなら、たとえ第1のテナントのブラウザが第2のテナント用に予約されたパスにアクセスしたとしても、第1のテナントのブラウザがプライベートIPアドレスを使ってアクセス可能なのは、第1のテナントにとってのイントラネット内部のみだからである。つまり、たとえ第1のテナントのブラウザが第2のテナント用に予約されたパスにアクセスしたとしても、第1のテナントのブラウザから第2のテナントのDBサーバがアクセスされることはない。
さらに、マルチテナント環境においては、振り分け部103は、ブラウザ111がどのテナントに属するかを判断し、テナントに応じた処理を行ってもよい。HTTP要求はIPパケットの中にカプセル化されているので、振り分け部103は、ブラウザ111から受け取ったHTTP要求の送信元IPアドレスから、ブラウザ111がどのテナントに属するかを判断することもできる。
変形の第10の観点はブラウザ111に関する。図1のブラウザ111は、汎用的なWebブラウザであってもよい。しかし、汎用的なWebブラウザ以外の、例えば「リッチクライアント」と呼ばれるタイプのクライアントが、ブラウザ111の代わりに使われてもよい。そして、リッチクライアントに対応するサーバサイド・アプリケーションがWebアプリケーション101の代わりに使われてもよい。
ブラウザ111の代わりにリッチクライアントが使われる場合であっても、リッチクライアントが特定要求をWebサーバに送信することを契機にコネクションが確立される。そして、確立されたコネクションを介して、WebサーバがDBアクセス要求をリッチクライアントに送信する。すると、リッチクライアントがDBアクセス代行スクリプトにしたがってDBアクセスを代行してDBアクセス結果をWebサーバに送信する。
なお、以上説明した第10の観点について補足すれば、以下のとおりである。
Webサーバ100は、DBアクセスを制御するサーバサイドの制御装置の一例である。また、クライアントマシン110あるいはブラウザ111は、クライアントの一例である。
そして、振り分け部103は、クライアントから、特定のパスへのアクセスを求める特定要求を受け付ける第1の受付手段の一例である。また、振り分け部103は、クライアントと制御装置との間のコネクションを、第1の受付手段による特定要求の受付を契機として確立する確立手段の一例でもある。
そして、DBインタフェイス部102と振り分け部103は協働して、クライアントのアクセス先であるアプリケーションがDBへのアクセスを求めるDBアクセス要求をアプリケーションから受け付ける第2の受付手段として動作する。
さらに、スクリプト生成部104を含む振り分け部103は、次のような送信手段としても動作する。すなわち、送信手段はスクリプトをクライアントに送信する。当該スクリプトは、DBアクセス要求にしたがってDBにアクセスし、DBアクセス結果をDBから取得し、制御装置にDBアクセス結果を送信する処理を、クライアントに実行させるためのものである。また、送信手段は、DBアクセス要求を、スクリプトに含めて、またはスクリプトとは別に、確立手段により確立された上記コネクションを介してクライアントに送信する。
さらに、DBインタフェイス部102と振り分け部103は協働して、クライアントからDBアクセス結果を受信して、DBアクセス結果をアプリケーションに出力する出力手段としても動作する。
以上、変形例も含めて様々な実施形態について説明したが、いずれの実施形態においても、以下のような利点がある。
第1に、イントラネット140内のDB121のデータを使ってWebアプリケーション101が処理を行うことが可能だが、DB121のデータは外部ネットワーク150上に不揮発的に蓄積されることはない。したがって、外部ネットワーク150からの情報漏洩のリスクはほとんどない。
第2に、Webサーバ100とクライアントマシン110以外の、中継サーバ等の付加的な装置が不要である。したがって、上述の各種実施形態は、コスト、保守性、可用性などが優れている。
第3に、ファイアウォール130の設定を変更する必要がない。ファイアウォール130の設定の変更は、うっかり間違えるとセキュリティホールを作ってしまうことになりかねないので、設定変更が不要なことは利点である。
そして、以上例示した利点は、Webアプリケーション101の利用促進を図るうえで有益である。その理由は以下のとおりである。
近年では、企業が社内のイントラネットにWebアプリケーションをデプロイして利用する代わりに、インターネットを介してSaaSベンダなどが提供するWebアプリケーションを利用する事例も増えつつある。一方で、企業は、社外のネットワークに機密情報が保存されることを嫌う。
しかし、上述の各種実施形態によれば、DB121は企業のイントラネット140内にあり、かつ、外部ネットワーク150のWebアプリケーション101が利用可能である。したがって、上述の各種実施形態は、企業ユーザにおけるWebアプリケーション101の利用促進を図るうえで有益である。
最後に、上記の種々の実施形態に関して、さらに下記の付記を開示する。
(付記1)
第1のコンピュータに、
第2のコンピュータから、特定のパスへのアクセスを求める特定要求を受け付け、
前記第2のコンピュータと前記第1のコンピュータとの間のコネクションを、前記特定要求の受付を契機として確立し、
前記第2のコンピュータのアクセス先であるアプリケーションが第1のデータベースへのアクセスを求める第1のデータベースアクセス要求を、前記アプリケーションから受け付け、
前記第1のデータベースアクセス要求にしたがって前記第1のデータベースにアクセスし、第1のデータベースアクセス結果を前記第1のデータベースから取得し、前記第1のコンピュータに前記第1のデータベースアクセス結果を送信する代行処理を、前記第2のコンピュータに実行させるための実行命令スクリプトを、前記第2のコンピュータに送信し、
前記第1のデータベースアクセス要求を、前記実行命令スクリプトに含めて、または前記実行命令スクリプトとは別に、前記コネクションを介して前記第2のコンピュータに送信することで、前記代行処理を前記第2のコンピュータに実行させ、
前記第2のコンピュータから前記第1のデータベースアクセス結果を受信し、
前記第1のデータベースアクセス結果を前記アプリケーションに出力する
ことを含む制御処理を実行させるプログラム。
(付記2)
前記第2のコンピュータから、前記第1のコンピュータへのアクセスを求めるアクセス要求を受け付け、
前記アクセス要求に対応するセッションが存在するか否かを判断し、
前記セッションが存在しない場合、
新規セッションを生成し、
前記第2のコンピュータを前記特定のパスにアクセスさせるための第1のコードと、前記アプリケーションのページを第2のコンピュータに表示させるための第2のコードを、前記第2のコンピュータに送信し、
前記セッションが存在する場合、
前記アクセス要求が前記特定要求ならば、確立した前記コネクションを前記セッションと対応づけて記憶手段に記憶し、
前記アクセス要求が前記アプリケーションに対する要求ならば、前記アクセス要求を前記アプリケーションに出力する
ことを前記制御処理がさらに含むことを特徴とする付記1に記載のプログラム。
(付記3)
前記第1のコードは、前記特定のパスを第1のフレームのソースとして指定するコードであり、
前記第2のコードは、前記第2のコンピュータに、第2のフレームの中に前記アプリケーションの前記ページを表示させるためのコードである
ことを特徴とする付記2に記載のプログラム。
(付記4)
前記第1のデータベースアクセス要求を前記アプリケーションから受け付けると、前記セッションを識別するセッション識別情報を認識し、
前記記憶手段を検索することにより、前記セッション識別情報で識別される前記セッションと対応づけられた前記コネクションを特定する
ことを前記制御処理がさらに含み、
前記第1のデータベースアクセス要求を含む前記実行命令スクリプトが、特定された前記コネクションを介して前記第2のコンピュータに送信される
ことを特徴とする付記2または3に記載のプログラム。
(付記5)
前記第1のデータベースアクセス要求を受け付ける前に予め、前記代行処理のための関数の定義を含む定義スクリプトを、前記コネクションを介して前記第2のコンピュータに送信することを前記制御処理がさらに含み、
前記実行命令スクリプトは、前記第1のデータベースアクセス要求を表す引数を指定して前記関数の実行を命令するステートメントを含む
ことを特徴とする付記1から4のいずれか1項に記載のプログラム。
(付記6)
前記第2のコンピュータから、前記第1のコンピュータへのアクセスを求めるアクセス要求を受け付け、
前記アクセス要求に対応するセッションが存在するか否かを判断し、
前記セッションが存在しない場合、
新規セッションを生成し、
前記第2のコンピュータを前記特定のパスにアクセスさせるための第1のコードを前記第2のコンピュータに取得させるためのコードと、前記アプリケーションのページを第2のコンピュータに表示させるための第2のコードを、前記第2のコンピュータに送信し、
前記セッションが存在する場合、
前記アクセス要求が前記特定要求ならば、確立した前記コネクションを前記セッションと対応づけて記憶手段に記憶し、
前記アクセス要求が前記第1のコードを取得するための要求ならば、前記第1のコードを生成して前記第2のコンピュータに送信し、
前記アクセス要求が前記アプリケーションに対する要求ならば、前記アクセス要求を前記アプリケーションに出力する
ことを前記制御処理がさらに含むことを特徴とする付記1に記載のプログラム。
(付記7)
前記第1のコードは、前記第2のコンピュータに、前記特定要求を前記第1のコンピュータに繰り返し送信させるためのスクリプトを含む
ことを特徴とする付記6に記載のプログラム。
(付記8)
前記第1のデータベースアクセス要求を前記アプリケーションから受け付けると、前記セッションを識別するセッション識別情報を認識し、
前記セッション識別情報で識別される前記セッションと対応づけられた前記コネクションを特定する
ことを前記制御処理がさらに含み、
前記第1のデータベースアクセス要求は、前記実行命令スクリプトとは別に、特定された前記コネクションを介して前記第2のコンピュータに送信される
ことを特徴とする付記6または7に記載のプログラム。
(付記9)
前記制御処理は、
前記特定要求を受け付けた後、前記第1のデータベースアクセス要求を受け付けるまでは、前記特定要求への応答である特定応答の送信を延期し、
前記特定応答に、前記第1のデータベースアクセス要求を含め、
前記特定応答を前記第2のコンピュータに送信する
ことをさらに含み、
前記実行命令スクリプトは、前記第2のコンピュータに、
前記特定応答の受信を待ち、
前記特定応答を受信したら、前記特定応答から、前記第1のデータベースアクセス要求を抽出し、
抽出した前記第1のデータベースアクセス要求にしたがって前記代行処理を実行する
ことを含む処理を実行させる
ことを特徴とする付記1、6、7または8に記載のプログラム。
(付記10)
第2のデータベースへのアクセスを求める第2のデータベースアクセス要求を前記アプリケーションから受け付け、
前記第2のデータベースアクセス要求にしたがって前記第2のデータベースにアクセスし、
第2のデータベースアクセス結果を前記第2のデータベースから取得し、
前記第2のデータベースアクセス結果を前記アプリケーションに出力する
ことを前記制御処理がさらに含む
ことを特徴とする付記1から9のいずれか1項に記載のプログラム。
(付記11)
前記アプリケーションから受け付ける各データベースアクセス要求について、
前記第1のデータベースが含む各テーブルの識別情報を前記第1のデータベースと対応づけるとともに、前記第2のデータベースが含む各テーブルの識別情報を前記第2のデータベースと対応づける所在情報を参照し、
当該データベースアクセス要求が、前記第1のデータベースへのアクセスを求める要求なのか、それとも前記第2のデータベースへのアクセスを求める要求なのかを、前記所在情報を用いて判断する
ことを前記制御処理がさらに含むことを特徴とする付記10に記載のプログラム。
(付記12)
前記制御処理は、署名を前記第2のコンピュータに送信することをさらに含み、
前記代行処理における前記第2のコンピュータから前記第1のデータベースへのアクセスは、前記第2のコンピュータが前記第1のコンピュータから受信した前記署名を、前記第1のデータベースを管理する第3のコンピュータに送信することを含み、
前記署名は前記第3のコンピュータによる認証処理に使われる
ことを特徴とする付記1から11のいずれか1項に記載のプログラム。
(付記13)
サーバサイドの制御装置であって、
クライアントから、特定のパスへのアクセスを求める特定要求を受け付ける第1の受付手段と、
前記クライアントと前記制御装置との間のコネクションを、前記第1の受付手段による前記特定要求の受付を契機として確立する確立手段と、
前記クライアントのアクセス先であるアプリケーションがデータベースへのアクセスを求めるデータベースアクセス要求を、前記アプリケーションから受け付ける第2の受付手段と、
前記データベースアクセス要求にしたがって前記データベースにアクセスし、データベースアクセス結果を前記データベースから取得し、前記制御装置に前記データベースアクセス結果を送信する処理を、前記クライアントに実行させるためのスクリプトを、前記クライアントに送信し、
前記データベースアクセス要求を、前記スクリプトに含めて、または前記スクリプトとは別に、前記コネクションを介して前記クライアントに送信する送信手段と、
前記クライアントから前記データベースアクセス結果を受信して、前記データベースアクセス結果を前記アプリケーションに出力する出力手段
を備えることを特徴とする制御装置。
(付記14)
第1のコンピュータが、
第2のコンピュータから、特定のパスへのアクセスを求める特定要求を受け付け、
前記第2のコンピュータと前記第1のコンピュータとの間のコネクションを、前記特定要求の受付を契機として確立し、
前記第2のコンピュータのアクセス先であるアプリケーションがデータベースへのアクセスを求めるデータベースアクセス要求を、前記アプリケーションから受け付け、
前記データベースアクセス要求にしたがって前記データベースにアクセスし、データベースアクセス結果を前記データベースから取得し、前記第1のコンピュータに前記データベースアクセス結果を送信する処理を、前記第2のコンピュータに実行させるためのスクリプトを、前記第2のコンピュータに送信し、
前記データベースアクセス要求を、前記スクリプトに含めて、または前記スクリプトとは別に、前記コネクションを介して前記第2のコンピュータに送信することで、前記処理を前記第2のコンピュータに実行させ、
前記第2のコンピュータから前記データベースアクセス結果を受信し、
前記データベースアクセス結果を前記アプリケーションに出力する
ことを特徴とする方法。