<前の日記(2010年08月24日) 次の日記(2010年09月02日)> 最新 編集

高木浩光@自宅の日記

目次 はじめに 連絡先:blog@takagi-hiromitsu.jp
訪問者数 本日: 265   昨日: 2889

2010年08月29日

三菱図書館システムMELIL旧型の欠陥、アニメ化 - 岡崎図書館事件(7)

21日の日記で示したMELIL/CS(旧型)の構造上の欠陥について、その仕組みをアニメーションで表現してみる。

まず、Webアクセスの仕組み。ブラウザとWebサーバはHTTPで通信するが、アクセスごとにHTTP接続は切断される*1。以下のアニメ1はその様子を表している。

アニメ1: HTTP接続とWebアプリのセッション管理
(クリックで開始、リロードでもう一度)

このように、アクセスが終わると接続が切断されて、次のアクセスで再び接続するのであるが、ブラウザごとに毎回同じ「セッションオブジェクト」に繋がるよう、「セッションID」と呼ばれる受付番号を用いて制御されている。

なお、赤い線は、その接続が使用中であることを表している。

次に、「3層アーキテクチャ」と呼ばれる、データベースと連携したWebアプリケーションの実現方式について。3層アーキテクチャでは、Webアプリケーションが、Webサーバからデータベースサーバ(DB)へと接続して、SQL文実行をDBに要求する。

以下のアニメ2は、3層アーキテクチャにおける、ブラウザからWebサーバへのHTTP接続と、WebサーバからDBサーバへのDB接続のタイミングを表している。

アニメ2: いわゆる「3層アーキテクチャ」の一般的構成(都度接続方式の場合)
(クリックで開始、リロードでもう一度)

このように、HTTP接続を維持したまま、DB接続でSQL実行を要求し、SQL実行が終わって、結果をブラウザに返すとき、DB接続とHTTP接続を切断する。このような実現方式は「都度接続方式」と呼ばれる*2

複数のブラウザからアクセスがあるとき、SQL実行が十分に短時間であれば、DBサーバ上でのSQL実行は同時に1つとなる(アニメ2の前半)が、あるSQL実行が長時間にわたった場合には、複数のSQL実行が同時に走ることになる(アニメ2の後半で青い丸が2個ある状態)。この数が過多となると、サイトが「重い」状態となる。

そして、メリル方式(旧型MELIL/CS)の場合を以下のアニメ3に示す。メリル方式では、セッションオブジェクトが作られると同時にDB接続が作成され、その後HTTP接続が切断されても、DB接続は維持されたまま、そのセッションオブジェクト専用として使われる。アニメ3では、DB接続が3本までに制限されている場合を想定している。(実環境ではその100倍前後の本数で運用されている。)

アニメ3: メリル方式(旧型MELIL/CS)の場合
(クリックで開始、リロードでもう一度)

このように、3台の端末のブラウザがアクセスしてきた時点で、DB接続の上限の3本を使い尽くし、4台目のブラウザがアクセスしてくると、DB接続に失敗して、そのブラウザは何度アクセスしてもエラー画面*3になってしまうという「閲覧障害」が起きる。(DBでの処理が「重い」かどうかに関係なく。)

そしてアニメ3の後半では、一部の端末がいなくなって10分が経過すると、セッションのタイムアウトが起きて、当該セッションオブジェクトが消滅し、消滅と同時にそのセッションが握っていたDB接続が切断されて、DB接続に空きができ、5台目の端末が接続できるようになる(閲覧障害が解消する)という様子を表している。

これがメリル方式の特徴であり、もし、永遠にDB接続が切断されないバグであったなら、毎日すぐに閲覧障害になって使い物にならないから、さすがに放置されることはなかったであろうが、このように、セッションタイムアウトまでの期間中に一定数のブラウザがアクセスに来たときだけ閲覧障害が起きるという、微妙なものであった。

次に、ブラウザがcookieオフ設定である場合をアニメ化してみる。

以下のアニメ4は、cookieオフのブラウザ、あるいは元々cookie機能を持たない自動アクセスプログラム(Googlebot等のWebクローラ等)が連続アクセスするときの様子を表している。

アニメ4: cookie非対応クライアントによる連続アクセス
(クリックで開始、リロードでもう一度)

このように、cookie非対応であることから、同じブラウザからのアクセスであることを識別できないため、次々と新しいセッションオブジェクトが作られて処理される。しかし、一般的には、Webサーバ上のセッションオブジェクトはほぼ無尽蔵に作成できるので*4、とくに問題はない。

次に、cookie非対応で都度接続方式のサイトに連続アクセスした場合の様子を、アニメ5に示す。

アニメ5: 都度接続方式におけるcookieオフでの連続アクセス
(クリックで開始、リロードでもう一度)

このように、アクセスごとにセッションオブジェクトは次々新しいものとなるが、「シリアルアクセス」でアクセスしている限り、DB接続とSQL実行は同時に1つであり、とくに問題は起きない。

ところが、メリル方式の場合はそうはいかない。cookieオフで連続アクセスするとアニメ6のようになる。

アニメ6: メリル方式におけるcookieオフでの連続アクセス
(クリックで開始、リロードでもう一度)

このように、3回アクセスした時点でDB接続が上限に達し、4回目以降はエラーとなる。そして、10分後には、セッションタイムアウトとなって、DB接続は解放され、元の状態に戻る。

岡崎図書館事件では、朝日新聞の記事によると「10分間にアクセスが約1千件を超えると、ホームページの閲覧ができなくなり」とあり、DB接続の上限が1000本だった。仮に1秒に1.5回のアクセスペースだとすると、10分で900本のDB接続を占有することになり、他に一般の利用者が100人以上いたならば、閲覧障害が生じることになる。もっとも、最初のアクセスから10分が経過すると、最初のアクセスで作られたセッションがタイムアウトし、DB接続が次々解放され始めるので、閲覧障害は解消されたはずである。

このことについて、「サーバ管理者日誌」の7月27日のエントリ「シリーズ・クロールとDoSの違いと業務妨害罪と(7) - 念力デバッグ再び」が、この閲覧障害発生のタイミングを図1のように推定していた。

グラフ
図1: 推定された閲覧障害のタイミング(「サーバ管理者日誌 2010年07月27日」より)
(ここではDB接続の上限を400本と仮定)

青い線は、連続アクセスが順調に進んだ期間を表しており、線が途切れている部分が、閲覧障害発生中の期間を表している。

このように、閲覧障害は、一旦起きるとずっと続くというものではなく、グラフのように断続的に、あるいは一時的に発生するものであった。その発生割合は、連続アクセスの速度と、DB接続の上限本数と、セッションタイムアウトの時間によって決まる(多くなったり少なくなったりする)。

ただ、アニメ3に示したように、一旦接続エラーになったブラウザ(アニメ3における4番目の端末のブラウザ)は、10分が経過した後も、DB接続のないセッションオブジェクトに繋がり続けるため、何度リロードしても閲覧障害が解消していないように見えただろう。この状態は、ブラウザを再起動する(あるいは、10分間以上リロードをしないで我慢して、タイムアウトさせてからリロードする)まで続く。(追記:※1この様子を表すアニメ8を以下の最後に追加した。)

そのため、閲覧障害の発生期間がグラフのように部分的であっても、たまたまその期間中にサイトに訪れた利用者は、その後ずっとリロードしても閲覧できなくなることから、苦情の電話に至ったものと考えられる。

ちなみに、メリル方式のことを、DB接続を維持するものであることから、「コネクションプーリング」と呼んでいる人をTwitter界隈で稀に見かけたが、それは間違いで、こういうのをコネクションプーリングとは言わない。

コネクションプーリングとは、以下のアニメ7に示すような方式のことを指す。

アニメ7: コネクションプーリング方式(cookieオンの場合)
(クリックで開始、リロードでもう一度)

つまり、事前にDB接続を一定数確保して接続プールとし、Webアプリのセッションは、空いている任意のDB接続をプールから獲得して使用し、使い終えたら切断しないでプールに戻すというもの。都度接続方式に比べて、DB接続の確立に要す時間を省くことができ、レスポンスが早いと言われる。1990年代後半にその必要性が認識され、1999年ごろまでに確立し2000年ごろには広く知られていた

このようなコネクションプーリング方式や、都度接続方式を用いて3層アーキテクチャを構成していたならば、岡崎図書館事件の閲覧障害は起きなかった。これらの方式で閲覧障害が起きるとしたら、ひとつひとつのSQL実行の処理時間が相当長い場合*5、つまり、1つのSQL実行が終わらないうちに次のSQL実行が始まり、それが繰り返されて積み重なっていくような場合に限られる。「シリアルアクセス」ではそのようなことは起きないので、起きるとすれば、本当にたくさんの人が同時に訪れたときや、「パラレルアクセス」での真のDoS攻撃が行われた場合であろう。

21日の日記で示したように、2006年に開発された新型MELIL/CSでは、「都度接続方式」と「コネクションプーリング方式」が実装されている。

追記(9月3日)

上記※1で述べていた、閲覧障害発生中のタイミングで訪れたブラウザでは閲覧障害解消後も閲覧障害が続いているように見えるという、その様子を、以下のアニメ8に示す。

アニメ8: cookie非対応クライアントによる連続アクセスと
cookieオンのブラウザのアクセスが混在したときの様子
(クリックで開始、リロードでもう一度)

*1 Keep-Aliveについては、ここでは省略している。

*2 三菱電機ISの新型MELIL/CSの設定ファイルおよびコード上のコメントによると。

*3 旧型MELIL/CSでは、Global.asaにおいて、セッション開始時にのみDB接続を試みるように書かれていた。そのときエラーが発生しても、「On Error Resume Next」によって無視するように書かれていたため、初期化されない変数を抱えたまま、セッションオブジェクトは生成される。それ以降、そのセッションに接続するブラウザは、何度リロードしてもエラー「オブジェクトがありません」となる状態になったのではないかと考えられる。(エラー発生時にセッションを破棄するコードが書かれていなかったのならば。)

*4 無尽蔵にセッションを生成できるのは、Webが、HTTP接続をアクセスの都度切断するものとして設計されているため。もし、HTTPが接続を維持するタイプのプロトコルであったなら、セッション期間中のアクセス者数は、数百人ほどが限界になっていただろう。昔、Webが登場する前、Anonymous FTPをよく利用していたものだが、接続しようとすると「既に100人がログインしている」として接続を拒否されることがよくあったものだ。DB接続でも同様であり、使わない接続を維持し続けるのは無駄であり、3階層アーキテクチャでWebと結合すると、一般的なWebクローラが来ただけで破綻してしまう。

*5 旧型MELIL/CSでは、蔵書検索でのキーワード検索が異常なほど遅いという指摘も出ている。しかし、岡崎図書館事件で行われたアクセスは、蔵書検索ではなく、「TosCode」で指定された書誌ページへのアクセスであり、そのSQL実行は十分に短く、他の利用者への迷惑となるとは通常考えられない。

本日のTrackBacks(全11件) [TrackBack URL: http://takagi-hiromitsu.jp/diary/tb.rb/20100829]

WebアクセスとDBアクセスの関係がとても分かりやすい記事紹介

PC Online のコラム 賢人たちのリレーコラム セキュリティ"言いたい放題"から 岡崎市立図書館事件に見るネットと法執行機関のズレ http://pc.nikkeibp.co.jp/article/column/20100901/1027224/ 寄稿者は上原哲太郎氏(京都大学 学術情報メディアセンター教育支援システム研..

※事件の内容はhttp://www26.atwiki.jp/librahack/pages/16.htmlやhttp://takagi-hiromitsu.jp/diary/20100829.htmlなどご参照ください。。 &#160; この事件、何が正しくて何が誤りで、なぜ犯罪になるのか。十分な検証が必要だ。 ひとつ言える事は、三菱電機インフォメー..

高木浩光@自宅の日記 - 三菱図書館システムMELIL旧型の欠陥、アニメ化 - 岡崎図書館事件(7)

検索

<前の日記(2010年08月24日) 次の日記(2010年09月02日)> 最新 編集

最近のタイトル

2016年04月23日

2016年04月06日

2016年03月27日

2016年03月14日

2016年03月06日

2016年02月24日

2016年02月20日

2016年02月11日

2016年02月05日

2016年01月31日

2015年12月12日

2015年12月06日

2015年11月23日

2015年11月21日

2015年11月07日

2015年10月20日

2015年07月02日

2015年06月14日

2015年03月15日

2015年03月10日

2015年03月08日

2015年01月05日

2014年12月27日

2014年11月12日

2014年09月07日

2014年07月18日

2014年04月23日

2014年04月22日

2000|01|
2003|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|05|06|07|08|09|10|11|12|
2012|02|03|04|05|06|07|08|09|
2013|01|02|03|04|05|06|07|
2014|01|04|07|09|11|12|
2015|01|03|06|07|10|11|12|
2016|01|02|03|04|
<前の日記(2010年08月24日) 次の日記(2010年09月02日)> 最新 編集