なぜ僕はmod_mrubyを作る必要があったのか、そこからどう応用させたのかについて、自分が作った、mrubyによるWebサーバの新しいリソース制御を軸にお話します。
ԾతʹίϯϐϡʔλϦιʔεΛՄೳͳNSVCZʹΑΔ8FCαʔόͷϦιʔε੍ޚΞʔΩςΫνϟژେֶদຊ྄հ5XJUUFS!NBUTVNPUPSZ
View Slide
ࣗݾհ• ژେֶͷത࢜՝ఔֶੜ– Πϯλʔωοτج൫ٕज़ͷݚڀ– ୈճຊ044ྭड– ത࢜՝ఔͷલϑΝʔεταʔόͰӡ༻• NSVCZίϯτϦϏϡʔλ– NPE@NSVCZɾOHY@NSVCZɾBCNSVCZ– ࠷ۙͰ5SVTUFSE)5518FC4FSWFS– NHFNMJTUʹొࡁͷNHFNݸͰੈքҐ3VCZ,BJHJ
NHFNMJTU3BOLJOH3VCZ,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
ຊͷ༰ ཉ͔ͬͨ͠8FCαʔόͷϦιʔε੍ޚ ͦ͜ͰNPE@NSVCZΛ։ൃͨ͠ NPE@NSVCZ͔ΒDHSPVQTΛ੍ޚ Ϧιʔε੍ޚΛಈ͔ͯ͠Έͨ ·ͱΊ3VCZ,BJHJ
͕ཉ͔ͬͨ͠8FCαʔόͷϦιʔε੍ޚ3VCZ,BJHJ
8FCαʔόͷϦιʔε੍ޚͱ• طଘͷϦιʔε੍ޚΞʔΩςΫνϟ– ίϯϐϡʔλϦιʔεΛᮢॲཧͰ੍ޚ– ᮢΛ͑ΔͱϦΫΤετॲཧΛڧ੍அɾڋ൱– ड͚Δ͔ड͚ͳ͍͔ͷ୯७ͳ੍ޚ• – ΫϥΠΞϯτͷҹ͕ѱ͍ɾ͍߹Θͤࡴ౸– αʔόͷ࣭ΛอͭͨΊͩͱઆ໌͢Δ͕ɾɾɾ– ࣭Λ্͛ΔͨΊͷϦιʔε੍ޚ͕શମͱͯ͠αʔϏε࣭͕Լ͍ͤͯ͞Δ߹͕͋Δ3VCZ,BJHJ
͕ཉ͔ͬͨ͠Ϧιʔε੍ޚ• ཧऀ͕ϓϩάϥϚϒϧʹ੍ޚϧʔϧΛهड़– ॊೈͰՄಡੑͷߴ੍͍ޚϧʔϧΛදݱ͍ͨ͠– αʔόϓϩηεͷ࠶ىಈͳ͘ϧʔϧΛมߋ͍ͨ͠– ϧʔϧ͕ΦʔόʔϔουʹͳΒͳ͍Α͏ʹ͍ͨ͠• ϦΫΤετ୯ҐͰϦιʔεΛׂΓͯΔ– ϦΫΤετͷதஅͰͳ͘ܧଓతʹॲཧ͍ͤͨ͞– ಛఆͷϦιʔεൣғͰॲཧ͍ͤͨ͞– ಛʹ੍ޚࠔͳ$16%*4,*0Λ੍ޚ͍ͨ͠3VCZ,BJHJ
ͦ͜ͰNPE@NSVCZΛ։ൃͨ͠3VCZ,BJHJ
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!
NPE@NSVCZ• "QBDIFͷػೳ֦ுʹಛԽ– 8FCίϯςϯπ։ൃΛతͱ͠ͳ͍– ίϯύΠϧίετΛ͍ͨ͘͠– ػೳ͕ͩίετͰಈ࡞͍ͤͨ͞• "QBDIFͱNSVCZ– ίΞ͕ඇৗʹখ͘͞ݴޠࣗମͷ࠷దԽ͕༻ҙ– -VBΑΓ8FCܥ։ൃऀͱੑ͕ߴ͍– طଘख๏ͷվम࠷৽ͷ"QBDIFରԠେม3VCZ,BJHJ
NPE@NSVCZͷϑοΫϞσϧ3VCZ,BJHJ ɾɾɾαʔόϓϩηεࢠαʔόϓϩηε" ϦΫΤετॲཧ༻ΠϯλϓϦλىಈ࣌ॲཧ༻ΠϯλϓϦλϦΫΤετҎ֎ͷॲཧ༻ΠϯλϓϦλεΫϦϓτεΫϦϓτεΫϦϓτεΫϦϓτεΫϦϓτੑೳ͕ཁٻ͞ΕΔϑοΫΠϯλϓϦλΛڞ༗
NPE@NSVCZΞʔΩςΫνϟʢ௨ৗʣ3VCZ,BJHJ ߏจղੳόΠτίʔυੜ7.্Ͱ࣮ߦʢ"QBDIFΛ੍ޚʣϦΫΤετຖʹαʔόϓϩηε͕εΫϦϓτΛϑοΫεΫϦϓτಡΈࠐΈΠϯλϓϦλͱϥΠϒϥϦΛڞ༗όΠτίʔυɺάϩʔόϧมɾΫϥεɺྫ֎ϑϥάΛ։์• αʔόϓϩηεىಈ࣌ʹΠϯλϓϦλΛ֬อ• ෳͷεΫϦϓτͰಉҰͷΠϯλϓϦλΛ࠶ར༻• εΫϦϓτؒͰͰ͖Δ͚ͩঢ়ଶ͕ׯব͠ͳ͍Α͏ʹ͢ΔഉଞॲཧϚϧνεϨου8FCαʔόΞʔΩςΫνϟʹରԠ
NPE@NSVCZΞʔΩςΫνϟʢΩϟογϡʣ3VCZ,BJHJ ߏจղੳόΠτίʔυੜ7.্Ͱ࣮ߦʢ"QBDIFΛ੍ޚʣϦΫΤετຖʹαʔόϓϩηε͕εΫϦϓτΛϑοΫεΫϦϓτಡΈࠐΈΠϯλϓϦλͱϥΠϒϥϦΛڞ༗άϩʔόϧมɾΫϥεɺྫ֎ϑϥάΛ։์ αʔόϓϩηεىಈ࣌ʹίϯύΠϧ όΠτίʔυςʔϒϧʹอଘ όΠτίʔυ*%͔ΒऔΓग़͠όΠτίʔυςʔϒϧ
NPE@NSVCZ NPE@NSVCZDBDIFBQBDIIUUQEJOEFYIUNMOHY@NSVCZ OHJOYJOEFYIUNMOHY@NSVCZDBDIF3&26&4544&$NPE@NSVCZOHY@NSVCZ)FMMP8PSME1FSGPSNBODFBCLDOIUUQ
"QBDIFIUUQEઃఆྫʢNPE@NSVCZʣ3VCZ,BJHJ # Normal hook!!mrubyHandlerMiddle /path/to/test.rb!!!# ByteCode Caching at Start up!!mrubyHandlerMiddle /path/to/test.rb cache!
OHJOYઃఆྫʢOHY@NSVCZ3VCZ,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;!}
OHJOYઃఆྫʢOHY@NSVCZ3VCZ,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”!‘;!}
3FWFSTF1SPYZNPE@NSVCZ3VCZ,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!
3FWFSTF1SPYZOHY@NSVCZ3VCZ,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)]!
#BTJD"VUIXJUI3FEJTNPE@NSVCZ3VCZ,BJHJ # !# AuthType basic!# AuthName "Message for clients"!# AuthBasicProvider mruby!# mrubyAuthnCheckPassword /path/to/authn_basic.rb!# require valid-user!# !!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
$POUSPMOHJOYWBSJBCMFTOHY@NSVCZ3VCZ,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”!
NPE@NSVCZͱOHY@NSVCZ• Ͱ͖Δ͚ͩಉ͡هड़Ͱ֦ுͰ͖ΔΑ͏ʹઃܭ• ओཁͳ8FCαʔόͷ࣮ͷҧ͍Λ3VCZ%4-Ͱٵऩ• "QBDIF5SBGpD4FSWFSͷUT@NSVCZ• 3VCZͷΞϓϦέʔγϣϯ։ൃऀ͕։ൃͷԆͰ8FCαʔόͷػೳ֦ுߦ͑Δ3VCZ,BJHJ
NPE@NSVCZͱOHY@NSVCZ3VCZ,BJHJ "QBDIF"1*3VCZTDSJQUNPE@NSVCZ3VCZTDSJQUɾɾɾɾ3VCZTDSJQUO/HJOY"1*OHY@NSVCZ3VCZTDSJQU"QBDIF$PSF/HJOY$PSF3VCZ%4-GPS8FC"QBDIF5SB⒏D4FSWFS"1*UT@NSVCZ"QBDIF5SB⒏D4FSWFS$PSFSFGIUUQTHJUIVCDPNTZVDSFBNUT@NSVCZ
ಉҰͷهड़ྫʢ)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!"
ಉҰͷهड़ྫʢ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
ͦͷଞͷԠ༻• ίʔυͷγϯλοΫεϋΠϥΠτ– 0VUQVUϑΟϧλʔ• ଓʹԠͨ͡ॲཧͷΓସ͑– ಉ࣌ଓ੍ݶ– ϦόʔεϓϩΩγͷΓସ͑• %PDLFSͱͷ࿈ܞ– NPPLKQQPPM– ಈతʹίϯςφݕग़͢ΔϦόʔεϓϩΩγ3VCZ,BJHJ
NPE@NSVCZ͔ΒDHSPVQTΛ੍ޚ3VCZ,BJHJ
NPE@NSVCZNSVCZDHSPVQ• 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
৽͍͠Ϧιʔε੍ޚ֓ཁ3VCZ,BJHJ "QBDIF1SPDFTTNPE@NSVCZNSVCZMJCNSVCZBNSVCZDHSPVQMJCDHSPVQ-JOVYDHSPVQT• ֤ػೳ୯ମͰಈ࡞Մೳʢૄ݁߹ʣ• NPE@NSVCZ"QBDIFΛNSVCZͰ੍ޚ• NSVCZDHSPVQMJCDHSPVQΛNSVCZͰ੍ޚ• NSVCZNSVCZDHSPVQ• 3VCZ$ίʔυͰϦιʔεΛ੍ޚՄೳ• ͜ͷϧʔϓ$16Ͱ• ͜ͷॻ͖ग़͠%*4,ॻࠐ.#TFDͰ
৽͍͠Ϧιʔε੍ޚ࣮3VCZ,BJHJ "QBDIF4FSWFS1SPDFTT$MJFOUDHSPVQT DQVDHJ$163VCZ%4-$POpH5BSHFUDQVDHJ$16$POpH5BSHFUJPDHJ$16%JTL8SJUF.#TFD$SFBUF "UUBDINPE@NSVCZNSVCZ3FRVFTUDQVDHJ NSVCZDHSPVQ3VO3FTQPOTF%FUBDI
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
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
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
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
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
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
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
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
Ϧιʔε੍ޚΛಈ͔ͯ͠Έͨ3VCZ,BJHJ
࣮ݧڥΫϥΠΞϯτ$16 *OUFM$PSF%VP&()[.FNPSZ (#/*$ 3FBMUFL35-#(CQT04 'FEPSB-JOVYLFSOFM3VCZ,BJHJ αʔό$16 *OUFM$PSFJ,()[.FNPSZ (#/*$ *OUFM*7(CQT04 'FEPSB-JOVYLFSOFM.JEEMF8BSF 8FCTFSWFS "QBDIF
ධՁʢ̍ʣ• Ϧιʔε੍ޚಋೖʹΑΔΦʔόʔϔουͷධՁ– l)FMMP8PSMEzΛग़ྗ͢Δ͚ͩͷ)5.-ϑΝΠϧ– Ϧιʔε੍ޚΛಋೖ͠ͳ͍߹– Ϧιʔε੍ޚΛಋೖ͢Δ͕Ϧιʔε੍ޚ͠ͳ͍߹– BCίϚϯυͰಉ࣌ଓɺ૯ଓສ• ݁Ռ– ఏҊख๏Λະಋೖ࣌ɿ SFRVFTUTFD– ఏҊख๏Λಋೖ࣌ ɹ SFRVFTUTFD3VCZ,BJHJ
ධՁʢ̎ʣ• Ϧιʔε੍ޚͷਫ਼ධՁ– $(*Λ$16༻ʹϦιʔε੍ޚ– $16ˋ༻͢Δϧʔϓ$(*Λ༻– ϦΫΤετॲཧ͕࣌ؒ$16༻࣌ؒͱݟͳͤΔ– ϧʔϓճʹΑͬͯϦΫΤετॲཧ࣌ؒΛมԽ– ϦΫΤετॲཧ࣌ؒΛมಈͤ͞ੑೳ੍ޚΛଌఆ˞ੑೳ੍ޚɿϦΫΤετॲཧ࣌ؒ ੍ޚແ͠ϦΫΤετॲཧ࣌ؒ ੍ޚ༗Γ3VCZ,BJHJ
ੑೳ੍ޚ ੑೳ੍ޚʢʣ$(*ͷ$16༻࣌ؒʹϦΫΤετॲཧ࣌ؒʢNTFDʣੑೳ੍ޚ3VCZ,BJHJ
ߟ• Ϧιʔε੍ޚΑΓ੍͘ޚ͞ΕΔ߹– ϦΫΤετॲཧ͕࣌ؒNTFDҎԼ– ϓϩηεΛԾϦιʔεྖҬʹ͢Δॲཧ͕Φʔόʔϔου• దʹϦιʔε੍ޚͰಈ࡞͢Δʹ– ൺֱతॲཧ࣌ؒͷ͍ίϯςϯπ– ຊ࣮ݧڥͰNTFDҎ্ʢ$16༻࣌ؒʹϦΫΤετॲཧ࣌ؒͷ߹ʣ– ͱ͍͑ҎԼͳͷͰؾʹ͠ͳͯ͘ྑ͍ʁ3VCZ,BJHJ
·ͱΊ3VCZ,BJHJ
·ͱΊ• ϦΫΤετ୯ҐͰϦιʔε੍ޚ– MJCDHSPVQΛNSVCZͰ੍ޚ͢ΔͨΊͷNHFN– ͦͷNHFNΛNPE@NSVCZʹϦϯΫ͢Δ• ཧऀ͕ϓϩάϥϚϒϧʹ੍ޚϧʔϧΛهड़– ͦͷͨΊʹNPE@NSVCZ͕ඞཁͩͬͨ• NPE@NSVCZͱOHY@NSVCZ– Ϣʔεέʔε͕ͪ´– ϗεςΟϯάେखࣾͰͷ࠾༻ࣄҊ– ͕ࣗब৬ͯ͠ӡ༻ͯ͠ΈΔ3VCZ,BJHJ
࠷ޙʹ։ൃৼΓฦΓͱ͜Ε͔Β3VCZ,BJHJ
ٕज़ऀ͔Βݚڀऀ• େࡕͷখ͞ͳϚϯγϣϯͰਓͰݚڀ– ձࣾʹߦ͔ͣاۀͱͷͳ͍– େֶʹߦ͔ͣʹͻͨ͢Βࢠҭͯ– ՈͰͻͨ͢ΒݚڀɾϒϩάΛॻ͍ͯ– ਓͩͱࢥ͍ͬͯͨ• Πϯλʔωοτͷӟຊͩͬͨ– ίʔυΛެ։͠ϒϩάΛॻ͘– ͍͔ͭ୭͔͕ؾ͍ͮͯ͘ΕΔ– ϒϩάͷڞ༗ϑΟʔυόοΫΛͯ͘͠ΕΔ– ਓͰͳ͔ͬͨ3VCZ,BJHJ
ٕज़ऀͱݚڀऀͷڱؒ• ݚڀͷΞΠσΞਐΛϒϩάʹॻ͘– Ұ෦ͷݚڀऀ͔ΒආΛड͚Δ– ॴɾॴ྆ํ͕͋ΔͷͰΜͩ• ݚڀࣨͷϘε͜͏ݴͬͯԼͬͨ͞ʮੲͷΓํʹनΘΕͳͯ͘ྑ͍Ͱ͢ɻদຊ͞Μ͕ྑ͍ͱࢥ͏ΓํͰ͖ͳΑ͏ʹͬͯԼ͍͞ɻࠓͷΓํɺྑ͍ͱࢥ͍·͢Αɻʯ• ٹΘΕͨ– ͜Ε͕ແ͚Ε͜͜ʹ͍ͳ͔ͬͨ– اۀ͔Βେֶʹ࠷ॳͷҰาΛ౿Έग़ͯ͠ྑ͔ͬͨ3VCZ,BJHJ
ฏຌͳࣄͷੵΈॏͶ• ͍͠ࣄ΄ͱΜͲ͍ͬͯͳ͍– ฏຌͳՌͷެ։ΛڪΕ͍͚ͯͳ͍– ฏຌͳύονϒϩάΛίπίπॻ͘– ͋·Γߟ͑ͣʹͱΓ͋͑ͣॻ͍ͯΈΔ• ฏຌͳࣄͷੵΈॏͶ͕ྑ͍ʹ– ࣌ؒͱڞʹྑ͍ʹมΘ͍ͬͯΔࣄʹؾͮ͘– Πϯλʔωοτؾ͍ͮͯ͘ΕΔ– ͳΜͰͳ͍ࣄΛੵΈॏͶܧଓ͢Δࣄ͕େࣄ3VCZ,BJHJ
͜Ε͔Β• NPE@NSVCZͱOHY@NSVCZ– Ϣʔεέʔε͕ͪ´– ϗεςΟϯάେखࣾͰͷ࠾༻ࣄҊ– ͕ࣗब৬ͯ͠ӡ༻ͯ͠ΈΔ• ͱʹ͔͘࠷ॳͷҰาΛ౿Έग़ͯ͠ΈΔ• ͳΜͰͳ͍ࣄΛੵΈॏͶ͍ͯ͘• େֶΛमྃ͢Δ3VCZ,BJHJ