libcgroupとmrubyを使ったWebサーバのリソース制御アーキテクチャ

 libcgroupとmrubyを使ったWebサーバのリソース制御アーキテクチャ

2b692bd83f4418103142a053ecf5ff59?s=128

MATSUMOTO Ryosuke

October 04, 2013
Tweet

Transcript

  1. libcgroupとmrubyを使った Webサーバのリソース制御アーキテクチャ 松本 亮介 @matsumotory

  2. 自己紹介 • 京都大学大学院情報学研究科の博士課程学生 – OS・Middlewareやインターネット基盤ソフトウェア技術 • Webサーバのセキュリティ・パフォーマンス • Webサーバの運用性・大規模・高集積 •

    Linux Kernel・ファイルシステム・cgroups・Capability・I/O • P2P、SMTP – ネットワークセキュリティ • データマイニングによるパケット解析 • 変化点検出(外れ値と変化点の検知アルゴリズム) 2 • http://blog.matsumoto-r.jp/ • http://www.net.ist.i.kyoto-u.ac.jp/ja/index.php?matsumoto_r
  3. 目次 1. 本研究の概要 2. 既存のWebサーバのリソース制御 3. 提案するリソース制御アーキテクチャ 4. 実装 5.

    実験と評価 6. まとめ 3
  4. 本研究の概要 4

  5. 研究の背景 • Webサーバへのアクセス数の増加 – スマートフォンの普及 – Webサービスの無料・低価格化と普及 – よりリッチなWebアプリケーションが求められる •

    Webサービスの低価格化と安定性向上が課題 – Webサービスの高集積マルチテナント環境 – テナント単位でセキュリティやリソースを管理 – 既存のWebサーバのリソース制御では困難 5
  6. Webサーバのリソース制御 • 既存のリソース制御アーキテクチャ – リソース値を閾値処理で制御 – 閾値を超えるとリクエスト処理を強制切断・拒否 – 受けるか受けないかの単純な制御 •

    問題点の概要 – クライアントの印象が悪い・問い合わせ殺到 – サーバの品質を保つためだと説明するが・・・ – 品質を上げるためのリソース制御が全体としてサー ビス品質が低下させている場合が多い 6
  7. 本研究 • Webサーバの新しいリソース制御を提案 – 管理者が柔軟にリソース制御ルールを記述可能 – リソースを分離して処理するアーキテクチャ – リソース分離範囲内で継続的に処理 •

    高集積マルチテナント環境にも最適 – テナント(ホスト)・リクエスト単位でリソース分離 – 特定のリクエストのリソース占有を防ぐ – 占有を防ぎつつ継続的に処理 7
  8. 既存のWebサーバのリソース制御 8

  9. Webサーバのリソース制御設定 • リクエスト単位で閾値によるリソース制御 – CPU使用時間や同時接続数等 – リクエスト処理途中で強制切断(CPU使用時間) – 閾値超過中はリクエストを拒否(同時接続数) •

    問題点 – リクエストの切断・拒否中はサービス停止と同様 – 切断・拒否を伴う場合適切な閾値設定が困難 – 対応が後手に回る場合が多い – せいぜいファイルやIP単位での設定で複数の条件に よる制御構造が設定できない等ルール記述の自由 度が低い 9
  10. リソース制御の課題 • リソース制御の設定を柔軟にできる仕組み – Webサービスの大規模・複雑化にも対応 – Webサーバの内部情報や複数条件で制御構造記述 – リソース制御とアクセス制御やプロキシ処理を連携 •

    サービス停止しないようにリソースを制御 – 閾値で処理を停止する事なく継続してリクエスト処理 – 特定のリクエストのリソース占有を防ぐ 10
  11. 提案するリソース制御アーキテクチャ 11

  12. 提案するリソース制御 • ドメイン固有言語(DSL)で制御ルールを記述 – スクリプト言語のようにルール記述が可能 – リソース制御ルールを変更後即時反映可能 – DSL実行のオーバーヘッドが少ないアーキテクチャ •

    制御ルールに基づいて仮想的にリソースを分離 – 閾値処理ではなくリソース分離内で継続的に処理 – リクエスト処理同士で影響を受けない – CPU、CPUコア、DISK I/O等のリソースを対象 12
  13. 提案するリソース制御概要(1) 13 Server Process Client 仮想リソース領域 CPU 10%・Disk write 5MB/s

    DSL記述設定 CPU 10% Disk write 5MB/s create Request処理時にattach リソースコントローラ Request 設定読込 • リクエスト処理中のみサーバプロセスを仮想リソース領域に分離 • DSL記述によるWebサーバの機能拡張とみなす • オーバーヘッドの少ないスクリプト言語による機能拡張機構が必要
  14. 提案するリソース制御概要(2) 14 Server Process Client 仮想リソース領域 DSL記述 create Request処理時にattach Request

    DSL実行 機能拡張機構 リソースコントローラ リソースコントローラ: DSLで使用するメソッドやクラスの定義 機能拡張機構: Webサーバの拡張、DSLの言語仕様の定義、DSLの実行
  15. 実装 15

  16. 提案するリソース制御実装(1) • DSLによる機能拡張機構 – オーバーヘッドが少なく高速・省メモリに動作 – mod_mruby、ngx_mruby[1]を以前の研究で開発 – Rubyを使って柔軟で可読性の高いDSLを定義可能 •

    リソースコントローラ + DSL記述設定 – mrubyの拡張(mrbgem)として実装 • リソース分離 – Linux Cgroups(Linux Kernel 2.6.24以降) – プロセス単位でOSリソースを制御 • Webサーバソフトウェア – Linux Kernel 3.10+ Apache HTTP Server 2.4.6 16 [1] 松本亮介・岡部寿男, 組み込みスクリプト言語mrubyを利用したWebサーバの機能拡張支援機構, 情報処 理学会研究報告 Vol.2012-IOT-18, No.6, 2012年6月.
  17. 17 Apache Server Process mod_mruby mruby (libmruby.a) mruby-cgroup 提案するリソース制御実装(2) libcgroup

    Linux cgroups • 各機能は単体で動作可能(疎結合) • mod_mrubyはApacheのmruby Binding • mruby-cgroupはlibcgroupのmruby Binding • mruby + mruby-cgroup • RubyやCコード内でリソースを制御可能 • このループはCPU20%で • この書き出しはDISK書込1MB/secで
  18. mod_mruby 18

  19. mod_mruby • Apacheのmruby binding – RubyでApacheをコントロール – ApacheモジュールをRubyで書ける – mruby拡張を書けばそれをApache上でも使える

    – DSLでWebサーバを制御するためのDSLエンジン – 高速かつ軽量に動作 19
  20. Reverse Proxy by mod_mruby 20 # mrubyTranslateNameFirst “/path/to/proxy.rb” backends =

    [ "http://192.168.0.101:8888/", "http://192.168.0.102:8888/", "http://192.168.0.103:8888/", "http://192.168.0.104:8888/", ] r = Apache::Request.new backend = backends[rand(backends.length)] r.handler = "proxy-server" r.proxyreq = Apache::PROXYREQ_REVERSE r.filename = "proxy:" + backend + r.uri Apache::return Apache::OK
  21. VirtualHost by mod_mruby

  22. BasicAuth by mod_mruby

  23. BasicAuth with Redis by mod_mruby

  24. suEXEC by mod_mruby

  25. mruby-cgroup 25

  26. mruby-cgroup 26 • libcgroupのmruby binding • mrubyの拡張として実装(mrbgem) – Cgroup::CPUクラス –

    Cgroup::CPUSETクラス – Cgroup::BLKIOクラス – libcgroupは/sys/fs/cgroupの制御インターフェイス cpu = Cgroup::CPU.new “name” cpu.cfs_quota_us = 10000 cpu.create # /sys/fs/cgroup/cpu/name/cpu.cfs_quota_usに10000が入る
  27. メソッド 動作 Cgroup::CPU.new CPUクラスの初期化 Cgroup::CPU#create cgroup生成 Cgroup::CPU#modify cgroup変更 Cgroup::CPU#delete cgroup削除

    Cgroup::CPU#attach cgroupにattach Cgroup::CPU#detach cgroupにdetach Cgroup::CPU#exist? cgroupが存在するか Cgroup::CPU#cfs_quota_us= cfs_quota_usに値設定 Cgroup::CPU#cfs_quota_us cfs_quota_us参照 Cgroup::CPU#stat stat参照 Cgroup::CPU#cpuacct.usage_percpu cpuacct/usage_percpu参照 Cgroup::CPU#cpuacct.usage cpuacct/usage 27 その他、Cgroup::CPUSETやCgroup::BLKIO等
  28. mruby-cgroup 28 c = Cgroup::CPU.new "/test" if !c.exist? c.cfs_quota_us =

    30000 c.create end # CPU 30% c.attach (1..10000000).each do |i| end c.detach # CPU 100% (1..100000000).each do |i| end Rubyコード上でリソース制御 CPU使用率を制御 # CPU 10% c.cfs_quota_us = 10000 c.modify c.attach (1..10000000).each do |i| end c.detach
  29. mruby-cgroup 29 c = Cgroup::BLKIO.new "/test" c.throttle_write_bps_device = "8:0 10000000“

    c.throttle_read_bps_device = "8:0 50000000" c.create # write 10Mbps and read 50Mbps c.attach # I/O processing here! c.detach # read iops 2000iops c.throttle_read_iops_device = 2000 c.modify c.attach # I/O processing here! c.detach Rubyコード上でリソース制御 DISK I/Oを制御
  30. mruby-cgroup 30 rate = Cgroup::CPU.new "test" core = Cgroup::CPUSET.new "test"

    rate.cfs_quota_us = 30000 core.cpus = core.mems = "0" rate.create core.create # CPU core 0 and rate 30% rate.attach core.attach (1..100000000).each do |i| end Rubyコード上でリソース制御 CPUコアと使用率を同時に制御 # CPU core 0,1,2 and rate 30% rate.cfs_quota_us = 90000 core.cpus = core.mems = "0-2" rate.modify core.modify (1..100000000).each do |i| end
  31. mod_mruby + mruby-cgroup 31

  32. 32 Apache Server Process Client cgroups 1 (cpu.cgi) CPU 10%

    Ruby DSL config 1 target cpu.cgi CPU 10% config 2 target io.cgi CPU 50% Disk Write 1MB/sec create attach mod_mruby cgroups 2 (io.cgi) CPU 50% Disk Write 1MB/sec mruby Request cpu.cgi mruby-cgroup DSL実行 提案するリソース制御実装 mod_mrubyとmruby-cgroupを組み合わせてアーキテクチャ実装
  33. Ruby DSLによる制御ルール例 33 r = Apache::Request.new if r.filename == “/path/to/cpu.cgi”

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  34. Ruby DSLによる制御ルール例 34 r = Apache::Request.new if r.hostname == “matsumoto-r.jp”

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  35. Ruby DSLによる制御ルール例 35 r = Apache::Request.new if r.user == “matsumoto_r”

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  36. Ruby DSLによる制御ルール例 36 r = Apache::Request.new if r.method == “POST”

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  37. Ruby DSLによる制御ルール例 37 r = Apache::Request.new if r.protocol == “HTTP/1.1”

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  38. Ruby DSLによる制御ルール例 38 r = Apache::Request.new if r.finfo.user == 500

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  39. Ruby DSLによる制御ルール例 39 r = Apache::Request.new if r.finfo.group == 300

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  40. Ruby DSLによる制御ルール例 40 r = Apache::Request.new if r.finfo.size > 1000

    cpu = Cgroup::CPU.new “cpu_group” # CPUを10%に制御したい場合 cpu.cfs_quota_us = 10000 cpu.create cpu.attach end
  41. オプション制御ツール • Apacheの仕様上リクエスト処理途中のスクリプトのリ ソースを変更できない – リクエスト処理前に設定しておく必要がある – 高負荷なスクリプトの処理が継続する場合 • オプションツールとして動作中のプロセスのリソースを

    変更できるツールを準備(PID指定) – change-cpurate – change-read-bps-rate – change-write-bps-rate – change-read-iops-rate – change-write-iops-rate – run-cpu-rate ⇒ 運用者のためのツール作りは重要 41
  42. 実装まとめ • 管理者がDSLでWebサーバを柔軟にリソース制御 – mod_mrubyで内部情報と柔軟に連携できる – Rubyによる記述でアプリエンジニアも容易に拡張 – 高速かつ軽量でオーバーヘッドの少ないアーキテクチャ •

    mrubyの拡張を書けばそれがDSLに反映 – mod_mrubyと今回のリソース制御mruby-cgroup – ngx_mrubyでも同様(課題はある) – Java Servletのようなアーキテクチャは対象外 • C/C++アプリをmruby-cgroupでリソース制御 – mrubyはそもそもアプリに組み込んで使う – Cコード上でmrubyのメソッドも実行可能 – Cのコード上でmrubyでリソース制御もできる 42
  43. 実験と評価 43

  44. 実験環境 クライアント CPU Intel Core2Duo E6600 3.06GHz Memory 8GB NIC

    Realtek RTL8111/8168B 1Gbps OS Fedora 18 Linux kernel 3.10 44 サーバ CPU Intel Corei7-4770K 3.5GHz Memory 32GB NIC Intel I217V 1Gbps OS Fedora 19 Linux kernel 3.10 MiddleWare(Web server) Apache/2.4.6
  45. 評価(1) • 提案手法導入によるオーバーヘッドの評価 – 制御対象でないリクエストの性能低下を評価 – “Hello World”を出力するだけのHTMLファイル – abコマンドで同時接続数100、総接続数100万

    • 結果 – 提案手法を未導入時: 32915.46 request/sec – 提案手法を導入時: 32322.07 request/sec 45
  46. 評価(2) • リクエスト処理時間による精度評価 – CPU100%使用するループCGIを使用 – そのCGIをCPU使用率50%にリソース制御 – ループ回数によって1リクエスト処理時間を変化 –

    リクエスト処理時間を変動させ性能制御率を測定 – abコマンドで同時接続数10、総接続数1000 ※ 性能制御率: リソース制御前後で1秒間のリクエスト処理数 が何%低下しているか(本実験では50%に近ければより良い) 46
  47. 評価(2) 47

  48. 考察 • リソース制御値より低く制御される場合 – 1リクエスト処理時間が0msec〜6msec – プロセスを仮想リソース領域に分離する処理が オーバーヘッド • 適切にリソース制御が機能するには

    – 比較的処理時間の長いコンテンツ – 本実験環境では7msec以上 48
  49. まとめ 49

  50. まとめと今後の予定 • まとめ – 管理者が柔軟にリソース制御ルールを記述 – リクエスト・ホスト単位でリソースを分離 – 高集積マルチテナント環境にも適している •

    今後の予定 – 仮想リソース領域の分離処理の最適化 – Disk I/O制御の評価 – トラフィック・メモリも統一的に扱う実装追加 – リソース消費の統計値を計測する機能追加 50