Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

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

Avatar for MATSUMOTO Ryosuke

MATSUMOTO Ryosuke PRO

October 04, 2013
Tweet

More Decks by MATSUMOTO Ryosuke

Other Decks in Technology

Transcript

  1. 自己紹介 • 京都大学大学院情報学研究科の博士課程学生 – 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
  2. 研究の背景 • Webサーバへのアクセス数の増加 – スマートフォンの普及 – Webサービスの無料・低価格化と普及 – よりリッチなWebアプリケーションが求められる •

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

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

    高集積マルチテナント環境にも最適 – テナント(ホスト)・リクエスト単位でリソース分離 – 特定のリクエストのリソース占有を防ぐ – 占有を防ぎつつ継続的に処理 7
  5. Webサーバのリソース制御設定 • リクエスト単位で閾値によるリソース制御 – CPU使用時間や同時接続数等 – リクエスト処理途中で強制切断(CPU使用時間) – 閾値超過中はリクエストを拒否(同時接続数) •

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

    サービス停止しないようにリソースを制御 – 閾値で処理を停止する事なく継続してリクエスト処理 – 特定のリクエストのリソース占有を防ぐ 10
  7. 提案するリソース制御 • ドメイン固有言語(DSL)で制御ルールを記述 – スクリプト言語のようにルール記述が可能 – リソース制御ルールを変更後即時反映可能 – DSL実行のオーバーヘッドが少ないアーキテクチャ •

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

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

    DSL実行 機能拡張機構 リソースコントローラ リソースコントローラ: DSLで使用するメソッドやクラスの定義 機能拡張機構: Webサーバの拡張、DSLの言語仕様の定義、DSLの実行
  10. 提案するリソース制御実装(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月.
  11. 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で
  12. 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
  13. 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が入る
  14. メソッド 動作 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等
  15. 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
  16. 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を制御
  17. 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
  18. 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を組み合わせてアーキテクチャ実装
  19. 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
  20. 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
  21. 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
  22. 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
  23. 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
  24. 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
  25. 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
  26. 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
  27. オプション制御ツール • Apacheの仕様上リクエスト処理途中のスクリプトのリ ソースを変更できない – リクエスト処理前に設定しておく必要がある – 高負荷なスクリプトの処理が継続する場合 • オプションツールとして動作中のプロセスのリソースを

    変更できるツールを準備(PID指定) – change-cpurate – change-read-bps-rate – change-write-bps-rate – change-read-iops-rate – change-write-iops-rate – run-cpu-rate ⇒ 運用者のためのツール作りは重要 41
  28. 実装まとめ • 管理者が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
  29. 実験環境 クライアント 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
  30. 評価(2) • リクエスト処理時間による精度評価 – CPU100%使用するループCGIを使用 – そのCGIをCPU使用率50%にリソース制御 – ループ回数によって1リクエスト処理時間を変化 –

    リクエスト処理時間を変動させ性能制御率を測定 – abコマンドで同時接続数10、総接続数1000 ※ 性能制御率: リソース制御前後で1秒間のリクエスト処理数 が何%低下しているか(本実験では50%に近ければより良い) 46
  31. まとめと今後の予定 • まとめ – 管理者が柔軟にリソース制御ルールを記述 – リクエスト・ホスト単位でリソースを分離 – 高集積マルチテナント環境にも適している •

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