Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

RubyKaigi 2014 mod_mruby ngx_mruby

RubyKaigi 2014 mod_mruby ngx_mruby

なぜ僕はmod_mrubyを作る必要があったのか、そこからどう応用させたのかについて、自分が作った、mrubyによるWebサーバの新しいリソース制御を軸にお話します。

MATSUMOTO Ryosuke

September 19, 2014
Tweet

More Decks by MATSUMOTO Ryosuke

Other Decks in Technology

Transcript

  1. ࣗݾ঺հ •  ژ౎େֶͷത࢜՝ఔֶੜ –  Πϯλʔωοτج൫ٕज़ͷݚڀ –  ೥ୈճ೔ຊ044঑ྭ৆ड৆ –  ത࢜՝ఔͷલ͸ϑΝʔεταʔόͰӡ༻ • 

    NSVCZίϯτϦϏϡʔλ –  NPE@NSVCZɾOHY@NSVCZɾBCNSVCZ –  ࠷ۙͰ͸5SVTUFSE)5518FC4FSWFS –  NHFNMJTUʹొ࿥ࡁͷNHFN͸ݸͰੈքҐ 3VCZ,BJHJ 
  2. NHFNMJTU3BOLJOH 3VCZ,BJHJ  $  mgem  info  |  grep  Author  |

     sort  |  uniq  -­‐c  |  sort  -­‐nr  |  head        26      Author:              MATSUMOTO  Ryosuke      25      Author:              maCn      12      Author:              ppibburr      10      Author:              iij          7      Author:              ksss          6      Author:              Internet  IniJaJve  Japan.,  Inc.          5      Author:              Takeshi  Watanabe          3      Author:              h2so5          2      Author:              kyab          2      Author:              crimsonwoods  
  3. 8FCαʔόͷϦιʔε੍ޚͱ͸ •  طଘͷϦιʔε੍ޚΞʔΩςΫνϟ –  ίϯϐϡʔλϦιʔε஋Λᮢ஋ॲཧͰ੍ޚ –  ᮢ஋Λ௒͑ΔͱϦΫΤετॲཧΛڧ੍੾அɾڋ൱ –  ड͚Δ͔ड͚ͳ͍͔ͷ୯७ͳ੍ޚ • 

    ໰୊఺ –  ΫϥΠΞϯτͷҹ৅͕ѱ͍ɾ໰͍߹Θͤࡴ౸ –  αʔόͷ඼࣭ΛอͭͨΊͩͱઆ໌͢Δ͕ɾɾɾ –  ඼࣭Λ্͛ΔͨΊͷϦιʔε੍ޚ͕શମͱͯ͠ αʔϏε඼࣭͕௿Լ͍ͤͯ͞Δ৔߹͕͋Δ 3VCZ,BJHJ 
  4. ๻͕ཉ͔ͬͨ͠Ϧιʔε੍ޚ •  ؅ཧऀ͕ϓϩάϥϚϒϧʹ੍ޚϧʔϧΛهड़ –  ॊೈͰՄಡੑͷߴ੍͍ޚϧʔϧΛදݱ͍ͨ͠ –  αʔόϓϩηεͷ࠶ىಈͳ͘ϧʔϧΛมߋ͍ͨ͠ –  ϧʔϧ͕ΦʔόʔϔουʹͳΒͳ͍Α͏ʹ͍ͨ͠ • 

    ϦΫΤετ୯ҐͰϦιʔεΛׂΓ౰ͯΔ –  ϦΫΤετͷதஅͰ͸ͳ͘ܧଓతʹॲཧ͍ͤͨ͞ –  ಛఆͷϦιʔεൣғ಺Ͱॲཧ͍ͤͨ͞ –  ಛʹ੍ޚࠔ೉ͳ$16΍%*4,*0౳Λ੍ޚ͍ͨ͠ 3VCZ,BJHJ 
  5. ๻͕ཉ͔ͬͨ͠Ϧιʔε੍ޚ •  ؅ཧऀ͕ϓϩάϥϚϒϧʹ੍ޚϧʔϧΛهड़ –  ॊೈͰՄಡੑͷߴ੍͍ޚϧʔϧΛදݱ͍ͨ͠ –  αʔόϓϩηεͷ࠶ىಈͳ͘ϧʔϧΛมߋ͍ͨ͠ –  ϧʔϧ͕ΦʔόʔϔουʹͳΒͳ͍Α͏ʹ͍ͨ͠ • 

    ϦΫΤετ୯ҐͰϦιʔεΛׂΓ౰ͯΔ –  ϦΫΤετͷதஅͰ͸ͳ͘ܧଓతʹॲཧ͍ͤͨ͞ –  ಛఆͷϦιʔεൣғ಺Ͱॲཧ͍ͤͨ͞ –  ಛʹ੍ޚࠔ೉ͳ$16΍%*4,*0౳Λ੍ޚ͍ͨ͠ 3VCZ,BJHJ 
  6. NPE@NSVCZ •  "QBDIFIUUQEͷ%4-੍ޚΤϯδϯ •  ߴ଎͔ͭলϝϞϦʹ8FCαʔόΛ੍ޚՄೳ 3VCZ,BJHJ  # mrubyTranslateNameFirst “/path/to/proxy.rb”!

    ! backends = [! "http://192.168.0.101:8888/",! "http://192.168.0.102:8888/",! "http://192.168.0.103:8888/",! ]! ! r = Apache::Request.new! backend = backends[rand(backends.length)] ! r.reverse_proxy backend + r.unparsed_uri!
  7. NPE@NSVCZͷϑοΫϞσϧ 3VCZ,BJHJ  ɾ ɾ ɾ  ਌αʔόϓϩηε ࢠαʔόϓϩηε" ϦΫΤετॲཧ༻ΠϯλϓϦλ

    ىಈ࣌ॲཧ༻ΠϯλϓϦλ ϦΫΤετҎ֎ͷॲཧ༻ΠϯλϓϦλ εΫϦϓτ εΫϦϓτ εΫϦϓτ εΫϦϓτ εΫϦϓτ ੑೳ͕ཁٻ͞ΕΔϑοΫ ͸ΠϯλϓϦλΛڞ༗
  8. NPE@NSVCZΞʔΩςΫνϟʢ௨ৗʣ 3VCZ,BJHJ  ߏจ໦ղੳ όΠτίʔυੜ੒ 7.্Ͱ࣮ߦʢ"QBDIFΛ੍ޚʣ ϦΫΤετຖʹαʔόϓϩηε͕εΫϦϓτΛϑοΫ εΫϦϓτಡΈࠐΈ ΠϯλϓϦλͱ ϥΠϒϥϦΛڞ༗

    όΠτίʔυɺάϩʔόϧม਺ɾΫϥεɺྫ֎ϑϥάΛ։์ •  αʔόϓϩηεىಈ࣌ ʹΠϯλϓϦλΛ֬อ •  ෳ਺ͷεΫϦϓτͰಉ ҰͷΠϯλϓϦλΛ࠶ ར༻ •  εΫϦϓτؒͰͰ͖Δ ͚ͩঢ়ଶ͕ׯব͠ͳ͍ Α͏ʹ͢Δ ഉଞॲཧ ϚϧνεϨου8FC αʔόΞʔΩςΫνϟ ʹରԠ
  9. NPE@NSVCZΞʔΩςΫνϟʢΩϟογϡʣ 3VCZ,BJHJ  ߏจ໦ղੳ όΠτίʔυੜ੒ 7.্Ͱ࣮ߦʢ"QBDIFΛ੍ޚʣ ϦΫΤετຖʹαʔόϓϩηε͕εΫϦϓτΛϑοΫ εΫϦϓτಡΈࠐΈ ΠϯλϓϦλͱ ϥΠϒϥϦΛڞ༗

    άϩʔόϧม਺ɾΫϥεɺྫ֎ϑϥάΛ։์   αʔόϓϩηεىಈ࣌ ʹίϯύΠϧ   όΠτίʔυςʔϒϧ ʹอଘ   όΠτίʔυ*%͔Β औΓग़͠ όΠτίʔυ ςʔϒϧ
  10.          

        NPE@NSVCZ NPE@NSVCZ DBDIF BQBDIIUUQE JOEFYIUNM OHY@NSVCZ OHJOY JOEFYIUNM OHY@NSVCZ DBDIF 3&26&4544&$ NPE@NSVCZOHY@NSVCZ)FMMP8PSME1FSGPSNBODF BCLDOIUUQ 
  11. "QBDIFIUUQEઃఆྫ ʢNPE@NSVCZʣ 3VCZ,BJHJ  # Normal hook! <Location /mruby-test>! mrubyHandlerMiddle

    /path/to/test.rb! </Location>! ! # ByteCode Caching at Start up! <Location /mruby-test-cache>! mrubyHandlerMiddle /path/to/test.rb cache! </Location>
  12. OHJOYઃఆྫ ʢOHY@NSVCZ  3VCZ,BJHJ  # Normal hook! location /mruby-test

    {! mruby_content_handler /path/to/test.rb;! }! ! # ByteCode Caching at Start up! location /mruby-test-cache {! mruby_content_handler /path/to/test.rb cache;! }
  13. OHJOYઃఆྫ ʢOHY@NSVCZ  3VCZ,BJHJ  # Inline code hook! location

    /mruby-hello {! mruby_content_handler_code ‘! r = Nginx::Request.new! c = Nginx::Connection.new! ! r.content_type = “text/plain”! Nginx.echo “Hello #{c.remote_ip} World”! ‘;! }
  14. 3FWFSTF1SPYZ NPE@NSVCZ  3VCZ,BJHJ  # mrubyTranslateNameFirst “/path/to/proxy.rb”! ! backends

    = [! "http://192.168.0.101:8888/",! "http://192.168.0.102:8888/",! "http://192.168.0.103:8888/",! ]! ! r = Apache::Request.new! backend = backends[rand(backends.length)] ! r.reverse_proxy backend + r.unparsed_uri!
  15. 3FWFSTF1SPYZ OHY@NSVCZ  3VCZ,BJHJ  # location /proxy {! #

    mruby_set $backend "/path/to/proxy.rb";! # proxy_pass http://$backend;! # }! ! backends = [! "http://192.168.0.101:8888/",! "http://192.168.0.102:8888/",! "http://192.168.0.103:8888/",! ]! ! backends[rand(backends.length)]!
  16. #BTJD"VUIXJUI3FEJT NPE@NSVCZ  3VCZ,BJHJ  # <Location /basic/>! # AuthType

    basic! # AuthName "Message for clients"! # AuthBasicProvider mruby! # mrubyAuthnCheckPassword /path/to/authn_basic.rb! # require valid-user! # </Location>! ! anp = Apache::AuthnProvider.new! redis = Redis.new "127.0.0.1”, 6379! ! if redis.get(anp.user) == anp.password! Apache.return Apache::AuthnProvider::AUTH_GRANTED! else! Apache.return Apache::AuthnProvider::AUTH_DENIED! end
  17. $POUSPMOHJOYWBSJBCMFT OHY@NSVCZ  3VCZ,BJHJ  # http://example.com/vars?name=matsumotory! # location /vars

    {! # set $hoge ”100";! # mruby_set_code $foo ‘! # r = Nginx::Request.new! # r.var.hoge.to_i * 2 #=> 200! # ’;! # mruby_content_handler /path/to/var.rb;! # }! r = Nginx::Request.new! Nginx.echo “name: #{r.var.arg_name}” #=> “matsumotory” ! Nginx.echo “hoge: #{r.var.hoge}” #=> “100”! Nginx.echo “foo : #{r.var.foo}” #=> “200”! Nginx.echo “uri : #{r.var.uri}” #=> “/vars”! r.var.hoge = “ngx_mruby”!
  18. NPE@NSVCZͱOHY@NSVCZ 3VCZ,BJHJ  "QBDIF "1* 3VCZTDSJQU NPE@NSVCZ 3VCZTDSJQU ɾ ɾ

    ɾ ɾ  3VCZTDSJQUO /HJOY "1* OHY@NSVCZ 3VCZTDSJQU "QBDIF $PSF /HJOY $PSF 3VCZ %4- GPS8FC "QBDIF 5SB⒏D 4FSWFS "1* UT@NSVCZ "QBDIF 5SB⒏D 4FSWFS $PSF SFGIUUQTHJUIVCDPNTZVDSFBNUT@NSVCZ
  19. ಉҰͷهड़ྫʢ)FMMP8PSMEʣ 3VCZ,BJHJ  # Output Hello World! if server_name ==

    "NGINX"! Server = Nginx! elsif server_name == "Apache"! Server = Apache! elsif server_name == "ApacheTrafficServer"! Server = ATS! end! ! Server.rputs "Hello #{Server.module_name}/ #{Server.module_version} world!"! # mod_mruby => "Hello mod_mruby/1.9.3 world!"! # ngx_mruby => "Hello ngx_mruby/1.3.2 world!"! # ts_mruby => "Hello ts_mruby/0.0.1 world!"
  20. ಉҰͷهड़ྫʢ0VUQVU'JMUFSʣ 3VCZ,BJHJ  SFGIUUQICNBUTVNPUPSKQFOUSZ # Markdown convert! if server_name =

    “NGINX”! Server = Nginx! elsif server_name == “Apache”! Server = Apache! end! ! f = Server::Filter.new! css = “https://example.com/style.css”! title = “markdown file”! md = Discount.new css, title! ! f.body = md.md2html f.body
  21. ๻͕ཉ͔ͬͨ͠Ϧιʔε੍ޚ •  ؅ཧऀ͕ϓϩάϥϚϒϧʹ੍ޚϧʔϧΛهड़ –  ॊೈͰՄಡੑͷߴ੍͍ޚϧʔϧΛදݱ͍ͨ͠ –  αʔόϓϩηεͷ࠶ىಈͳ͘ϧʔϧΛมߋ͍ͨ͠ –  ϧʔϧ͕ΦʔόʔϔουʹͳΒͳ͍Α͏ʹ͍ͨ͠ • 

    ϦΫΤετ୯ҐͰϦιʔεΛׂΓ౰ͯΔ –  ϦΫΤετͷதஅͰ͸ͳ͘ܧଓతʹॲཧ͍ͤͨ͞ –  ಛఆͷϦιʔεൣғ಺Ͱॲཧ͍ͤͨ͞ –  ಛʹ੍ޚࠔ೉ͳ$16΍%*4,*0౳Λ੍ޚ͍ͨ͠ 3VCZ,BJHJ 
  22. NPE@NSVCZ NSVCZDHSPVQ •  NPE@NSVCZ͔ΒDHSPVQΛ੍ޚ͢Δ – ࢦఆͷ$16ൣғ಺ͰॲཧΛܧଓతʹॲཧ 3VCZ,BJHJ  r = Apache::Request.new!

    ! # CPU使用量を1コア10%に制御したい場合! if r.hostname == “matsumoto-r.jp”! cpu = Cgroup::CPU.new “httpd-limited”! cpu.cfs_quota_us = 10000! cpu.create ! cpu.attach! end
  23. ৽͍͠Ϧιʔε੍ޚ֓ཁ 3VCZ,BJHJ  "QBDIF1SPDFTT NPE@NSVCZ NSVCZ MJCNSVCZB  NSVCZDHSPVQ MJCDHSPVQ

    -JOVYDHSPVQT •  ֤ػೳ͸୯ମͰಈ࡞Մೳʢૄ݁߹ʣ •  NPE@NSVCZ͸"QBDIFΛNSVCZͰ੍ޚ •  NSVCZDHSPVQ͸MJCDHSPVQΛNSVCZͰ੍ޚ •  NSVCZ NSVCZDHSPVQ •  3VCZ΍$ίʔυ಺ͰϦιʔεΛ੍ޚՄೳ •  ͜ͷϧʔϓ͸$16Ͱ •  ͜ͷॻ͖ग़͠͸%*4,ॻࠐ.#TFDͰ
  24. ৽͍͠Ϧιʔε੍ޚ࣮૷ 3VCZ,BJHJ       "QBDIF4FSWFS1SPDFTT $MJFOU

    DHSPVQT DQVDHJ   $16  3VCZ%4-    $POpH 5BSHFUDQVDHJ $16   $POpH 5BSHFUJPDHJ $16 %JTL8SJUF.#TFD  $SFBUF "UUBDI NPE@NSVCZ NSVCZ 3FRVFTU DQVDHJ NSVCZDHSPVQ 3VO 3FTQPOTF %FUBDI
  25. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  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
  26. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  r = Apache::Request.new! ! if r.hostname ==

    “example.com”! cpu = Cgroup::CPU.new “cpu_group”! # CPUを10%に制御したい場合! cpu.cfs_quota_us = 10000! cpu.create ! cpu.attach! end
  27. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  r = Apache::Request.new! ! if r.user== “matsumotory”!

    cpu = Cgroup::CPU.new “cpu_group”! # CPUを10%に制御したい場合! cpu.cfs_quota_us = 10000! cpu.create ! cpu.attach! end
  28. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  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
  29. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  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
  30. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  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
  31. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  r = Apache::Request.new! ! if r.finfo.size >

    3000! cpu = Cgroup::CPU.new “cpu_group”! # CPUを10%に制御したい場合! cpu.cfs_quota_us = 10000! cpu.create ! cpu.attach! end
  32. 3VCZ%4-ʹΑΔ੍ޚϧʔϧྫ 3VCZ,BJHJ  if resource.most_heavy_hosts.include? r.hostname! # 1コアの100%固定でしか使えない、全タスクが1コア内で処理 c =

    Cgroup::CPU.new "httpd-static-limited"! c.cfs_quota_us = 100000! Apache::Resource.attach_cgroup c, "httpd-static-limited"! elsif resource.heavy_hosts.include? r.hostname! # 全CPUの25%(コア含む)のリソースを分配、コアが24個の場合最大6コア内で分配 # httpd グループと競合しない場合は100%(全コア)使用 c = Cgroup::CPU.new "httpd-limited"! c.shares = 25! Apache::Resource.attach_cgroup c, "httpd-limited"! else! # 全CPUの75%(コア含む)のリソースを分配、コアが24個の場合最大18コア内で分配 # httpd-limited グループと競合しない場合は100%(全コア)使用 c = Cgroup::CPU.new "httpd"! c.shares = 75! Apache::Resource.attach_cgroup c, "httpd"! end SFGIUUQTHJUIVCDPNNBUTVNPUPSNPE@NSVCZDPOUSPMDQVGPSWIPTU
  33. ࣮ݧ؀ڥ ΫϥΠΞϯτ $16 *OUFM$PSF%VP&()[ .FNPSZ (# /*$ 3FBMUFL35-#(CQT 04 'FEPSB-JOVYLFSOFM

    3VCZ,BJHJ  αʔό $16 *OUFM$PSFJ,()[ .FNPSZ (# /*$ *OUFM*7(CQT 04 'FEPSB-JOVYLFSOFM .JEEMF8BSF 8FCTFSWFS  "QBDIF
  34. ධՁʢ̍ʣ •  Ϧιʔε੍ޚಋೖʹΑΔΦʔόʔϔουͷධՁ –  l)FMMP8PSMEzΛग़ྗ͢Δ͚ͩͷ)5.-ϑΝΠϧ –  Ϧιʔε੍ޚΛಋೖ͠ͳ͍৔߹ –  Ϧιʔε੍ޚΛಋೖ͢Δ͕Ϧιʔε੍ޚ͠ͳ͍৔߹ – 

    BCίϚϯυͰಉ࣌઀ଓ਺ɺ૯઀ଓ਺ສ •  ݁Ռ –  ఏҊख๏Λະಋೖ࣌ɿ SFRVFTUTFD –  ఏҊख๏Λಋೖ࣌ ɹ SFRVFTUTFD 3VCZ,BJHJ 
  35. ධՁʢ̎ʣ •  Ϧιʔε੍ޚͷਫ਼౓ධՁ –  $(*Λ$16࢖༻཰ʹϦιʔε੍ޚ –  $16ˋ࢖༻͢Δϧʔϓ$(*Λ࢖༻ –  ϦΫΤετॲཧ͕࣌ؒ$16࢖༻࣌ؒͱݟͳͤΔ – 

    ϧʔϓճ਺ʹΑͬͯϦΫΤετॲཧ࣌ؒΛมԽ –  ϦΫΤετॲཧ࣌ؒΛมಈͤ͞ੑೳ੍ޚ཰Λଌఆ ˞ੑೳ੍ޚ཰ɿ ϦΫΤετॲཧ࣌ؒ ੍ޚແ͠ ϦΫΤετॲཧ࣌ؒ ੍ޚ༗Γ  3VCZ,BJHJ 
  36. ੑೳ੍ޚ཰         

                 ੑೳ੍ޚ཰ʢʣ $(*ͷ$16࢖༻࣌ؒʹϦΫΤετॲཧ࣌ؒʢNTFDʣ ੑೳ੍ޚ཰ 3VCZ,BJHJ 
  37. ߟ࡯ •  Ϧιʔε੍ޚ஋ΑΓ௿੍͘ޚ͞ΕΔ৔߹ –  ϦΫΤετॲཧ͕࣌ؒNTFDҎԼ –  ϓϩηεΛԾ૝ϦιʔεྖҬʹ෼཭͢Δॲཧ͕ Φʔόʔϔου •  ద੾ʹϦιʔε੍ޚ஋Ͱಈ࡞͢Δʹ͸

    –  ൺֱతॲཧ࣌ؒͷ௕͍ίϯςϯπ –  ຊ࣮ݧ؀ڥͰ͸NTFDҎ্ ʢ$16࢖༻࣌ؒʹϦΫΤετॲཧ࣌ؒͷ৔߹ʣ –  ͱ͸͍͑ҎԼͳͷͰؾʹ͠ͳͯ͘ྑ͍ʁ 3VCZ,BJHJ 
  38. ·ͱΊ •  ϦΫΤετ୯ҐͰϦιʔε੍ޚ –  MJCDHSPVQΛNSVCZͰ੍ޚ͢ΔͨΊͷNHFN –  ͦͷNHFNΛNPE@NSVCZʹϦϯΫ͢Δ •  ؅ཧऀ͕ϓϩάϥϚϒϧʹ੍ޚϧʔϧΛهड़ – 

    ͦͷͨΊʹNPE@NSVCZ͕ඞཁͩͬͨ •  NPE@NSVCZͱOHY@NSVCZ –  Ϣʔεέʔε͕ͪ´ –  ϗεςΟϯάେख਺ࣾͰͷ࠾༻ࣄҊ΋ –  ࣗ෼͕ब৬ͯ͠ӡ༻ͯ͠ΈΔ 3VCZ,BJHJ 
  39. ٕज़ऀ͔Βݚڀऀ΁ •  େࡕͷখ͞ͳϚϯγϣϯͰਓͰݚڀ –  ձࣾʹ΋ߦ͔ͣاۀͱͷ઀఺΋ͳ͍ –  େֶʹ΋ߦ͔ͣʹͻͨ͢Βࢠҭͯ –  ՈͰͻͨ͢ΒݚڀɾϒϩάΛॻ͍ͯ೥൒ – 

    ਓͩͱࢥ͍ͬͯͨ •  Πϯλʔωοτͷӟ͸ຊ౰ͩͬͨ –  ίʔυΛެ։͠ϒϩάΛॻ͘ –  ͍͔ͭ୭͔͕ؾ͍ͮͯ͘ΕΔ –  ϒϩάͷڞ༗΍ϑΟʔυόοΫΛͯ͘͠ΕΔ –  ਓͰ͸ͳ͔ͬͨ 3VCZ,BJHJ 
  40. ٕज़ऀͱݚڀऀͷڱؒ •  ݚڀͷΞΠσΞ΍ਐ௙Λϒϩάʹॻ͘ –  Ұ෦ͷݚڀऀ͔Β͸ආ೉Λड͚Δ –  ௕ॴɾ୹ॴ྆ํ͕͋ΔͷͰ೰Μͩ •  ݚڀࣨͷϘε͸͜͏ݴͬͯԼͬͨ͞ ʮੲͷ΍ΓํʹनΘΕͳͯ͘ྑ͍Ͱ͢ɻদຊ͞Μ͕ྑ͍

    ͱࢥ͏΍ΓํͰ޷͖ͳΑ͏ʹ΍ͬͯԼ͍͞ɻࠓͷ΍Γ ํɺྑ͍ͱࢥ͍·͢Αɻʯ  •  ٹΘΕͨ –  ͜Ε͕ແ͚Ε͹͜͜ʹ΋͍ͳ͔ͬͨ –  اۀ͔Βେֶʹ࠷ॳͷҰาΛ౿Έग़ͯ͠ྑ͔ͬͨ 3VCZ,BJHJ