第 6章 まとめ
小さいことが確認できた。
なお、プロトタイプの実装に用いたRuby言語は実装が容易な反面で、C言語などに比べて実 行速度が遅いことが指摘されており、C言語などで実装を最適化することによって、さらにオー バヘッドを縮小することができる。
さらに、単純な構成のwebサーバに対してベンチマーキングツールによって同時接続クライ アント数を増加させつつファイルを同時取得する実験を実施し、データ転送速度の変化を計測し た。その結果から計算し、バックエンドサーバに対する接続クライアント数に偏りが生じた場合、
それを提案手法によって平滑化することによって、平均転送速度、最低転送速度、ともに向上さ せられることがわかった。
謝辞
本論文の作成にあたり、日頃より御指導を頂いた早稲田大学理工学術院の後藤滋樹教授に深く 感謝いたします。
竹谷賢二さん、山田大輔さん、河野真也さん、時光潤さん、鈴木幹也さん、夏目祐輔さん、板 倉弘明さん、岸本和之さん、魏元さん、下田晃弘さん、の皆様にも、後藤研での生活全般でお世 話になりました。
また、大学院在学中に奨学金を貸与し、生活を助けていただいた独立行政法人日本学生支援機 構および日本政府と納税者のみなさまに感謝いたします。
最後に、私の無能力さを強く確信しながらも、学費を支払い、書籍を毎年買い与え続けてくれ た父と母に感謝いたします。
参考文献
[1] Koichiro Doi and Shigeki Goto, “Load Balancing with HTTP Session Handover”, CORE University Seminar, Jeju, Korea, October 2007.
[2] 総務省, “平成19年 情報通信白書”
http://www.johotsusintokei.soumu.go.jp/whitepaper/ja/h19 [3] 総務省, “ブロードバンドサービスの契約数等(平成19年9月末)”
http://www.soumu.go.jp/s-news/2007/071218_4.html [4] “KDDI”
http://www.kddi.com/
[5] “ウィルコム”
http://www.willcom-inc.com/
[6] Wold wide web consortium, “XHTML2 Working Group Home Page”
http://www.w3.org/MarkUp/
[7] Internet Assigned Numbers Authority, “PORT NUMBERS”
http://www.iana.org/assignments/port-numbers
[8] Internet Assigned Numbers Authority, “HTTP Status Code Registry”
http://www.iana.org/assignments/http-status-codes [9] “Ultra Monkey”
http://sourceforge.jp/projects/ultramonkey/
[10] “Ruby on Rails”
http://www.rubyonrails.org/
[11] “Blogger”
http://www.blogger.com/
参考文献
[12] R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, T. Berners-Lee,
“Hypertext Transfer Protocol – HTTP/1.1”, RFC 2616, June 1999.
[13] デージーネット『Linux アドバンスト ネットワークサーバ構築ガイド HAサーバ構築編』
秀和システム, Dec 2005.
[14] Douglas E. Comer著, 村井純・楠本博之訳『TCP/IPによるネットワーク構築 原理・プロ トコル・アーキテクチャ』共立出版, Aug 2002.
[15] V Cerf, R. Kahn, “A Protocol for Packet Network Interconnection”, IEEE Transaction on Communication, vol. COM-22, pp.637–648, May 1974.
[16] H-Hash, “Studying HTTP”
http://www.studyinghttp.net/
[17] ささだ こういち, “YARV: Yet Another Ruby VM”
http://www.atdot.net/~ko1/tmp/yp.pdf
[18] Rubyコミュニティ, “Rubyリファレンスマニュアル – TCPServer”
http://www.ruby-lang.org/ja/man/index.cgi?cmd=view;name=TCPServer [19] Apache Foundation, “ab – Apache HTTP server benchmarking tool”
http://httpd.apache.org/docs/2.0/programs/ab.html [20] Netcraft, “October 2007 Web Server Survey”
http://news.netcraft.com/archives/2007/10/11/october_2007_web_server_
survey.html
[21] 西田佳史, 日本ネットワークインフォメーションセンター編, ”TCP 詳説” www.nic.ad.jp/jp/materials/iw/1999/proceedings/C03.PDF
[22] W.Richard Stevens, “TCP/IP Illustrated, Volume 1: The Protocols”, Addison-Wesley, 1994.
[23] David A. Patterson, John L. Hennessy, “Computer organization and design 3/e”, Morgan Kaufmann, 2005.
[24] アンドリュー・S. タネンバウム 『構造化コンピュータ構成 第4版』 ピアソンエデュケー ション, 2000.
[25] Andrew S. Tanenbaum, “Computer Networks 4/e”, Prentice Hall, 2003.
参考文献
[26] Nicholas G. Carr, “Does IT matter?”, Harvard Business School Press, 2004.
[27] Ben Laurie, Peter Laurie, “Apache 3/e, The definiteve guide”, O’Reilly, 2003.
[28] まつもとゆきひろ,石塚圭樹 『オブジェクト指向スクリプト言語Ruby』 ASCII, 1999.
[29] 竹下隆史, 村山公保, 荒井透, 苅田幸雄 『マスタリングTCP/IP 入門編 第4版』 オーム社, 2007.
[30] 砂原秀樹, 知念賢一,中田秀基, 松岡聡, 後藤滋樹 『岩波講座インターネット ネットワークア プリケーション』 岩波書店, 2003.
[31] 後藤滋樹, 外山勝保 『電子情報通信レクチャーシリーズ インターネット工学』 コロナ社, 2007.
[32] George Apostolopoulos, Vinod Peris, Prashant Pradhan, Debanjan Saha, “L5: A Self Learning Layer-5 Switch”, IBM Research Division, 1999.
[33] Andy Oram, Greg Wilson, “Beautiful Code”, O’Reilly, 2007.
付録 A
プロトタイプのソースコード
require ’socket’
require ’gserver’
$running = true
class LoadBalancer < GServer
PORT = 8080
HOST_ADDR = "192.168.0.20"
AUDIT = true
MAX_CONNECTIONS = 1
#バッファが大きい方が転送効率が高いが、バックエンドサーバとの
#切断と再接続のタイミングが少なくなる BUF_SIZE = 1024 * 1024
def initialize(port=PORT, host=HOST_ADDR, *args) super(port, host, MAX_CONNECTIONS, *args) end
def serve(io)
#ブラウザのHTTPメッセージを受信 req_str = []
付録 A プロトタイプのソースコード
resource = ""
while s = io.gets req_str << s
if s[0..2] == "GET" #リソース名を保存 arr = s.split(/ /)
resource = arr[1]
end
break if req_str.last == "\r\n"
end
#ブラウザのHTTPメッセージをサーバに対して再送信
#Rangeフィールドを追加したりするので、末尾の\r\nはpopして除去
log("[ " << resource << " ] サーバにHTTPメッセージを発行中\n") req_str.pop
sock = issue_GET("192.168.0.30", 80, req_str)
#以下、サーバからの応答をブラウザに返す
log("[ " << resource << " ] サーバデータをブラウザに転送中\n")
#ヘッダの処理 Content-Lengthを読み取って切断タイミングを計る
#これがないと、どこまで読み取ったらいいか分からないのでタイムアウトまで時間がかか る
total = 0 #リソースの合計データ長(オクテット)
len = 0 #読み取ったデータ長(オクテット)
reconnect = false #ハンドオーバによる再接続であるか
while true
#TODO: 元々がRangeだった場合は、レスポンスがContent-Rangeとなるので、その場
合も考慮する必要がある。
#HTTP/TCP再接続 if reconnect
additional = []
付録 A プロトタイプのソースコード
additional << "Range: bytes=" << (len) << "-" << total << "\r\n"
sock = issue_GET("192.168.0.30", 80, req_str, additional)
log(’[ ’ << resource << ’ ] 部分取得済...: ’ << len.to_s << ’/’ \\
<< total.to_s << "\n") end
#TODO: パターンマッチをする前に先頭数文字([0..3])を比較すれば計算量を減らせ
る
#再接続の時は、sock.getsではなく、前回の接続先から帰ってきたHTTPメッセージを そのまま返す
log("[ " << resource << " ] HTTPヘッダを転送中\n") if !reconnect while s = sock.gets
if !reconnect
if /^HTTP\/.* (\d+ .*)$/ =~ s
log("[ " << resource << " ] オリジナルレスポンスコード: " << \\
$1.chomp! << "\n")
elsif /^[Cc]ontent-[Ll]ength: (\d+)\r\n/ =~ s total = $1.to_i
log("[ " << resource << " ] データ長: " << $1 << "\n") end
end
#HTTPのレスポンスヘッダは、再接続後は無視して破棄
io.write(s) if !reconnect break if s == "\r\n"
end
if total > 0
log("[ " << resource << " ] ブラウザにHTTPボディを転送中\n") while len < total && $running
if total - len > BUF_SIZE s = sock.read(BUF_SIZE) else
付録 A プロトタイプのソースコード
s = sock.read(total - len) end
io.write(s) len += s.size end
elsif
log("[ " << resource << " ] HTTPボディなし\n") end
sock.close
log("[ " << resource << " ] 切断\n") if total > len
$running = true reconnect = true
log("[ " << resource << " ] 再接続中...\n") else
break end end
log("[ " << resource << " ] サーバデータをブラウザに転送終了\n") end
def issue_GET(host, port, req_str, additional=nil) sock = TCPSocket.open(host, port)
req_str.each{|line|
sock.write(line) }
if additional != nil additional.each{|line|
sock.write(line) }
end
sock.write("\r\n")