Share
Embed
Transcript
75 slides
-
more slide sponsors Ⰻ鿇ה䙼ג??![[BL@KQ E3VCZח״ⴓ侔٥8FCفؚٗٓىؚٝ ؔ٦ي爡F#PPL4UPSF IUUQFTUPSFPINTIBDPKQUJUMFT1!IJTBTIJN זׁתծTFLJ眍ֶ嚂׃ְֻׁկ䊛䃵歲ך倯כծLBXBTBLJSCծ ZPLPIBNBSCֶ鑐׃ְֻׁկ,ذٖؽך飑ⰅכծTFLJׁ穗歋ד׀湱锑ְ
ֽה׀⼿⸂׃תׅկ!UTVCPJ &NCFS4BQQPSP״׃ֶֻיְָ׃תׅխխխխխխխ IUUQTXXXGBDFCPPLDPNHSPVQTFNCFSTBQQPSP!USJDLOPUFT ְִ٦ְ✌✌؟ٝٓ؎ؤ⳿ꨡד3VCZ8PSME$POGFSFODF遤ֲֿ ٦!ZBODZB -
@m_seki Rubyίϛολ ERB, dRuby, Rindaͷஶऀ લ࠲͕Matz - Ruby committer -
Author of ERB, dRuby, Rinda -
Agenda dRubyͷੜཱ͍ͪ dRubyͷհ ͜Ε͔Β - The birth of dRuby -
Introduction of dRuby - Future -
2005 - ·ͩॳΓങ͑·͢ dRuby ʹΑΔ ؔকढ़ஶ ࢄ ɾ Web ϓϩάϥϛϯά
First printing from 2005 (Still available) -
2000 Perl/Ruby Conference (Kyoto) 2000 ࠷ॳͷߨԋ͜ͷձ ײܹ͍ͯ͠Δ - Perl/Ruby Conference
(Kyoto) - The first talk I gave was in year 2000 at this place. - I am impressed. -
2000-2016 ࠓಉ͡ձͰ·ͨdRubyͷΛ͍ͨ͠ I would like to give a talk about
dRuby again in the same place today. -
dRubyͲ͔͜Β͖ͨͷ dRubyҎલ (Before dRuby: BD) Where did dRuby come from?
- Before dRuby (BD) -
BD8͘Β͍ͷ͜ͱ ੲͬΆ͍UNIXΛͬͨΈࠐΈγεςϜ খ͞ͳσʔϞϯͷΈ߹Θͤ fork, pipe, signal, SystemV IPC select()ͳ͔ͬͨ From
the old days (BD8) - Embedded system using old-fashioned UNIX - Combination of tiny daemons - fork, pipe, signal, SystemV IPC - select() did not exist -
BD8͘Β͍ͷ͜ͱ ܭଌஔ܈Λ੍ޚ ஔ͔ΒσʔλΛऔΔ/੍ޚ͢Δͨ͘͞Μ ͷσʔϞϯͱͦΕΛ·ͱΊΔσʔϞϯ ใΛՄࢹԽ͢ΔΞϓϦέʔγϣϯ ϓϩηεΛ͚Δඞવੑ͕͋ͬͨ From the old days
(BD8) - Controlling a group of measurement devices - Many daemons that extract and control data from devices, and a daemon that controls them in turn - Need to divide between processes -
CGIͷ୯७ͳੈք (BD5) ԶϚΠΫϩαʔϏε࣌ request/response, stateless ͍ΖΜͳγεςϜΛCGIͰॻ͖ͨ͠ Perl, AppleScript A simple
world of CGI - My Microservices era - request/response, stateless - Rewrote various systems using CGI -
Ruby & shttpsrv (BD1) 1998-9 Ruby & shttpsrvʹग़ձ͏ 1998-9, Met
Ruby & shttpsrv -
shttpsrv RubyͰॻ͔ΕͨHTTPαʔό WEBrickΑΓͣͬͱલ খ͍͞ - Web server written in Ruby
- Before WEBrick - Small and extensible -
HTTPΛϓϩηεʹຒΊࠐΉ খ͞ͳΞϓϦʹWebαʔόΛຒΊࠐΉ ΞϓϦؒΛHTTPͰͭͳ͍Ͱָ͠ΜͰͨ Embedding HTTP into processes - Embedding web
server into small apps - Had fun Application communication via HTTP -
ͳΜ͔ؾʹೖΒͳ͍ ͍ͭRubyͱWebͷੈքͷ༁࡞ۀͯͨ͠ HTTPʹ͓͚ΔΦϒδΣΫτͷަͷ੍ Server - Clientͷݻఆతͳؔ ϝιουͱ͍͏ΑΓؔίʔϧ Not so cool
because... - Routine work translating between Ruby and the Web world - HTTP's restriction on how to exchange objects - Fixed relation between Server and Client - More like a functional call rather than a method -
RubyͰ͍ͨ͠ Ruby ObjectͳΜ͔ͩΒɺRubyΆ͍ͨ͘͠ Want to speak in Ruby - Given
that they are Ruby objects, it is tempting to speak in Ruby-ish way -
RubyʹؼΖ RubyͷΑ͏ʹৼΔ͏ࢄΦϒδΣΫτ RPCͰͳ͘RMI Rubyͷϝιουݺͼग़͠ΛsocketͰ֦ு Return to Ruby - Distributed objects
acting like Ruby - No RPC, but RMI - Extending Ruby's method invocation with sockets -
ϩϚϯ RMIΛࢥ͍͍͔ͭͯΒͷࢥߟ࣮ݧ ࢄΦϒδΣΫτ͕͋Δ͔ͷΑ͏ͳԋग़ͱ OOPLͱΦϒδΣΫτΈ͍ͨͳ... Romance - Thought-experiment since the idea
of RMI - How to make it look like there are distributed objects - Something like OOP-language and objects -
ͭ·Γ ؆୯௨৴ϥΠϒϥϦͰͳ͍ ௨৴Λ؆୯ʹ͢Δ͜ͱૂ͍ͬͯͳ͍ طଘͷRPCϓϩτίϧͷϥούʔͰͳ͍ ͬͱॹతͳͷ In other words, Not a
library that makes communication simple - It doesn't aim to make communication simple - It is not a wrapper of an already-existing RPC protocol - Something more poetic -
͠Β͓͍ͪͩ͘͘͞ ✓ ✓ E3VCZલ࢙Λઆ໌ͨ͠ ✓ ͔ͭ͗ΒE3VCZΛհ please wait for
a moment - Done: Pre-history of dRuby - Now, we are on to demonstration -
dRubyͯͳʹʁ ࢄΦϒδΣΫτγεςϜ ϓϩηεӽ͠ʹϝιου͕ݺΔ ϓϩηεؒͰΦϒδΣΫτ͕ૹΕΔ What is dRuby? - Distributed Object
System - Can Invoke methods in different process - Can send objects between process -
ਐΊํ irbͷσϞͰجຊతͳಈ࡞Λઆ໌ ΈΜͳTerminalΛ2ͭ༻ҙͯ͠ʂ unixͷਓwindowsͷਓ! Outline - Basis using irb demo
- Please prepare two teminals! -
dRubyͷ͓͔͛ͰWindowsͰ ࣮ݧͰ͖ΔΑʂ Thanks to the dRuby book, gets on Windows
no longer blocks other threads. -
Demo1 Starting up dRubyΛ͏ͨΊͷ४උ ؆୯ͳRMI Key Value Store Demo1 Starting
Up - Preparing to use dRuby - A simple RMI - Key-Value Store -
start_service start_serviceͰ͡Ί·͢ URIͱΦϒδΣΫτΛࢦఆͯ͠ެ։ ໌ࣔతͳެ։ DRb.start_service('druby://localhost:54321', {}) DRb.uri #=> 'druby://localhost:54321' DRb.front
#=> {} start_service - Begin with start_service - Publicize URI and an object - Explicit publicizing -
ͨͩݺͿ͚ͩ ผϓϩηεͷϝιουݺͼग़͠ Hash#[]=(k, v) kvs['greeting'] = "Hello, World." Just call
the method - Calling method in a different process -
Hashαʔό DRb.start_service('druby://localhost:54321', {}) DRb.front #=> {} DRb.start_service kvs = DRbObject.new_with_uri('druby://localhost:54321')
kvs['greeting'] = "Hello, World." DRb.front #=> {"greeting"=>"Hello, World."} -
ͬͨ͜ͱ DRb.start_serviceͰ͡Ίͨ URIͰproxyΛͭͬͨ͘ ͋ͱݺͿ͚ͩ What we did - Started with
DRb.start_service - Created a proxy with a URI - Then, we just called it -
ͼͬ͘Γͯ͠ʂ dRubyͷ४උstart_service͚ͩ ΠϯλʔϑΣΠεఆٛෆཁ ੲIDLఆٛ͢ΔγεςϜ͕ଟ͔ͬͨ Surprised, aren't you? - Only need
to do start_service to prepare for dRuby - No need to declare interfaces - In the old days, many systems defined IDL -
Demo2 Ͳ͕ͬͪαʔόʁ ҉తʹObjectΛެ։͠·͢ jushi-matzͷ $stdout Λoso-matz͕ݺͼ·͢ server / clientͷཱ͕ೖΕସΘΓ·͢ Demo
2 Which one is the server? - Implicitly publicize an object - oso-matz will call $stdout on jushi-matz - Server/client roles will switch -
ΦϒδΣΫτΛૹΔ ϝιουͷҾͰ$stdoutΛૹΔ ҉తʹެ։ kvs['outlet'] = $stdout Sending objects - Send
$stdout as method arguments - Publicized implicitly -
ٯస ϦϞʔτͷ$stdoutͷϝιουΛݺͿ ϗϯϞϊΛ͍࣋ͬͯΔํ͕αʔόʔ ϝιουΛݺͿํ͕ΫϥΠΞϯτ DRb.front['outlet'].class #=> DRb::DRbObject DRb.front['outlet'].puts('Hello, Again.') Reversal
- Call $stdout methods on the remote - The one that has the read one is the server - The one that calls the method is the client -
Demo2 Ͳ͕ͬͪαʔόʁ DRb.front['outlet'].class #=> DRb::DRbObject DRb.front['outlet'].puts('Hello, Again.') kvs['outlet'] = $stdout
kvs['outlet'] #=> $stdout Demo2 Which one is the server? -
Demo2 Ͳ͕ͬͪαʔόʁ kvs['outlet'] = $stdout kvs['outlet'] #=> $stdout DRb.front['outlet'].class #=>
DRb::DRbObject DRb.front['outlet'].puts('Hello, Again.') -
ͬͨ͜ͱ jushi-matzͷ$stdoutΛoso-matzʹڭ͑ͨ oso-matzͦΕʹputsͨ͠ jushi-matzͷʹҹࣈ͞Εͨ What we did - Taught oso-matz
about $stdout on jushi-matz - oso-matz did puts on it - Printed on a terminal on jushi-matz -
ͳʹ͕͓͖ͨʁ ҉తͳެ։ $stdoutΛࣗಈతʹproxyʹऔΓସ͑ͨ Marshal.dumpͷՄ൱͕݅ dumpՄೳ ➡ ෳ dumpෆՄೳ ➡ proxy
What happened? - Implicit publicization - Replaced $stdout with proxy automatically - Depends on the availability of Marshal.dump - dumpable => duplication - not dumpable => proxy -
Marshal.dump 'outlet'dumpͰ͖Δ ෳ $stdoutdumpͰ͖ͳ͍ proxy Marshal.dump - 'outlet' is dumpable
- duplicating - $stdout cannot be dumped - proxy kvs['outlet'] = $stdout # kvs.[]=('outlet', $stdout) -
͜͜Ͱͷԋग़ RubyͳΒҾΓ͕ෳ͞Εͳ͍ dRubyͰͯ͢proxyʹ͢Δ͖ʁ વͦ͏ࢥ͏ true, false, nil, ... ͜Εproxyʹ͢Δ͖ʁ ͏ʔΜ
Some thinking - In Ruby, arguments and return values are not duplicated - Should dRuby proxy everything? - Yes, of course - true, false, nil, numbers, ... should it also proxy them? - Mmm -
ࣗવʹݟ͑Δଥڠඞཁͩ ӬԕʹProxyͰ͕खʹೖΒͳ͍ Ͳ͔͜ʹڥք͕ඞཁͩ Marshal.dumpʹͨ͠ ͳΜ͔͍͍ײ͡ʹಈ͘ Natural compromise - Using proxy,
we will never get the value - We need a border somewhere - Made it using Marshal.dump - Works good -
OOPͬΆ͞ ΦϒδΣΫτ͕૬ޓʹݺͼ߹͑Δ͜ͱ How to make it look OOP-ish - Let
objects call each other -
ruby-list:15406 1st sampleɹ require 'drb.rb' class DRbEx def initialize @hello
= 'hello' end def hello @hello end def sample(a, b, c) a.to_i + b.to_i + c.to_i end end if __FILE__ == $0 DRb.start_service('druby://localhost:7640', DRbEx.new) DRb.thread.join end require 'drb.rb' class DRbEx2 def initialize(n) @n = n end def _dump raise TypeError, 'can\'t dump' end def to_i @n.to_i end end if __FILE__ == $0 DRb.start_service('druby://localhost:7950') ro = DRbObject.new(nil, 'druby://localhost: 7640') p ro.hello p ro.sample(DRbEx2.new(1), 2, 3) p ro.sample(1, ro.sample(DRbEx2.new(1), 2, 3), DRbEx2.new(3)) end -
OOPͬΆ͞ ΠςϨʔλಉ͡ΈͰಈ͘Α block ro.each do |it| foo(it) end How to
make it look OOP-ish - Iterators also work the same way - block -
Demo3 ࢄQueue QueueΛͬͯͪ߹Θͤ͠·͢ ϓϩηεؒͰpush/pop Demo 3 Distributed Queue - Wait
using queue - push/pop between processes -
ͪ߹Θͤ QueueΛͬͯͪ߹Θͤ jushi-matz͔Βͷσʔλͷ౸ணΛͪ·͢ Waiting - Waiting using queue - Wait
for the data from jushi-matz to arrive -
४උ QueueΛ࡞ͬͯHashʹೖΕ·͢ popͯͪ͠·͢ queue = Queue.new DRb.front['queue'] = queue queue.pop
Preparation - Create a queue, and put it in a Hash - Pop, and wait -
σʔλΛૹΔ Hashαʔό͔ΒQueueΛखʹೖΕΔ pushͰσʔλΛૹΓ·͢ queue = kvs['queue'] queue.push(1.0) Sending data -
Obtain a queue from a hash server - send a data -
Demo3 ࢄQueue queue = Queue.new DRb.front['queue'] = queue queue =
kvs['queue'] queue.push(1.0) queue.pop #=> 1.0 queue.pop #(blocked) queue.push(2.0) queue.pop #=> 2.0 (cont.) Demo 3 Distributed Queue -
Demo3 ࢄQueue queue = Queue.new DRb.front['queue'] = queue queue.pop queue.pop
queue = kvs['queue'] queue.push(1.0) queue.push(2.0) -
ͳʹ͕͓͖ͨʁ HashαʔόΛհͯ͠QueueΛखʹೖΕͨ Name Serivce QueueΛͬͯೋਓ͕ͪ߹Θͤͯͨ͠ What happened? - A queue
was obtained via a hash server - Two people were waiting for each other using a queue -
͜͜Ͱͷԋग़ Queue, Mutex, Monitor ... ThreadಉظϝΧχζϜͦͷ··͑Δ Some thoughts here -
Queue, Mutex, Monitor, ... - We can use the Thread-synchronization mechanism as is -
dRuby͕͘ঢ়گ ण໋ͷҧ͏ใΛѻ͏ ͪ߹ΘͤΛσβΠϯ͢Δ͜ͱ͕ଟ͍ Scenarios suited for dRuby - Handling information
of different life span - A system of waiting -
BD8͘Β͍ͷ͜ͱ ܭଌஔ܈Λ੍ޚ ஔ͔ΒσʔλΛऔΔ/੍ޚ͢Δͨ͘͞Μ ͷσʔϞϯͱͦΕΛ·ͱΊΔσʔϞϯ ใΛՄࢹԽ͢ΔΞϓϦέʔγϣϯ ϓϩηεΛ͚Δඞવੑ͕͋ͬͨ From the old days
(BD8) - Controlling a group of measurement devices - Many daemons that extract and control data from devices, and a daemon that controls them in turn - Need to divide between processes -
Prototyping Twitter ॳظdRuby/RindaͩͬͨΒ͍͠ ͍·ͬͯͳ͍ ࣗͷαʔϏεdRubyͰ͡Ίͯ࠷ޙʹ Θͳ͘ͳΔ͜ͱ͕͋Δ ར༻͞Εͯޮ͋͛Δඞཁ͕Ͱ͔ͯΒ - It looks
like they had used dRuby/Rinda in the beginning. - But not now. - Even I sometimes start some services using dRuby, ending up not using it. - It happened since my services gained popularity, and I needed to make them more efficient. -
հͷ·ͱΊ جຊతͳdRubyͷ͍ํΛհͨ͠ ४උ RMI Queue ࢄΦϒδΣΫτΆ͔ͬͨʁ Interim summary - Introduced
basic uses of dRuby - Preparation - RMI - Queue - Looked like distributed objects? -
͠Β͓͍ͪͩ͘͘͞ ✓ ✓ E3VCZͷσϞΛͨ͠ ✓ ࢄΦϒδΣΫτΆ͍ʁ ✓ ଓ͖ॻ੶Ͱʂ ✓
࣍ݴ͍༁ please wait for a moment - Did demo on dRuby - Looks like distributed objects? - Please buy the book for more information! - Next: the excuses -
͜Ε͔Β ͍ͨ͠ͱ͜Ζ ॳظͷ࣮ʹ͍ͨ͠ͱ͜Ζ͕͍͔ͭ͘ ςετ ܒ͢Δ From now on - Want
to fix: - Several points to revert to the initial implementation - Tests - Enlighten people -
ηΩϡϦςΟͬΆ͍ͷফ͍ͨ͠ ACL, insecure_method ... dRubyRMIͰϝιουݺͼग़͠ͷ֦ு ϝιουݺͼग़͠ͳͷͰ݀ͩΒ͚Ͱྑ͍ ةͳ͍ͷةͳ͘ݟ͑Δ͖ Want to hide
security-ish things - ACL, insecure_method, ... - dRuby extends methods with RMI - It is okay to have loop holes since it is a method call - Dangerous things should look dangerous -
UnitTest ڈakr͞Μʹݴ͍༁ͨ͠ צҧ͍ͯͨ͠ ҰൠతʹAPIͷϝιου୯Ґʹॻ͘ͷ ͩͬͨΒ͍͠ ςετέʔεΛετʔϦʔϨϕϧͰॻ͘ ͖ͩͱࢥͬͯͨ - I made
an excuse to akr last year. - I mistook it. - Turned out that in general, they should be written per API method. - I had thought they should be written at story levels. -
ܒ͢Δ ·͓ͣ͠Ζ͕ͬͯΒ͏ ฒߦॲཧͷצॴ(ʁ)ʹؾ͍ͮͯΒ͏ Enlightening people - Have people enjoy it.
- Let them realize the tips of parallel processing -
͠Β͓͍ͪͩ͘͘͞ ✓ ✓ ඪ४ఴΛଓ͚ͯΒ͏ Α͏ʹΞϐʔϧ͢Δ ✓ ͏ऴΘΓ ✓ εϥΠυӳ༁νʔϜʹ͓
ྱΛ͍͏ please wait for a moment - Appeal to have them continuously attached by default - Almost the end -
History of dRuby (and me) 1999-3 ERB 1999-9 DRb 2003
committer 2010 pokemon-master 2000 Rinda 1998 started ruby 2006 - 2016 Ruby Kaigi -
·ͱΊ 2000ͱಉ͡ॴͰdRubyͷΛͨ͠ dRubyͷੜཱ͍ͪ dRubyͷհ ͜Ε͔Β 21ੈل͓͠Ζ͕ͬͯΒ͑ΔͰ͠ΐ͏͔ Conclusion - I gave
a talk on dRuby at the same place I did in year 2000. - Birth of dRuby - Introduction of dRuby - Future - Will people still have fun with dRuby in the 21st century?