[转]介绍分布式的Ruby(DRb)英文
来源:互联网 发布:dbscan聚类算法 java 编辑:程序博客网 时间:2024/04/29 21:35
Introduction to Distributed Ruby (DRb)
DRb allows Ruby programs to communicate with each other on the same machine or over a network. DRb uses remote method invocation (RMI) to pass commands and data between processes.
DRb Basics
We'll start with a simple example DRb service:
Download simple_service.rb
#!/usr/bin/env ruby -w
# simple_service.rb
# A simple DRb service
# load DRb
require 'drb'
# start up the DRb service
DRb.start_service nil, []
# We need the uri of the service to connect a client
puts DRb.uri
# wait for the DRb service to finish before exiting
DRb.thread.join
Now lets go through this line by line. First we load DRb, this should be familiar to everyone. Next we tell DRb to start up. The first nil argument can be a DRb URI, which looks like "druby://localhost:2250". If it is nil, DRb uses the first open port. The second argument is an optional service to provide, in this case an Array. After starting the service, we print the URI to the console. Finally we join the DRb thread. The DRb thread won't exit until an interrupt is sent (such as a ^C).
So what does this really do? Well, it opens up a socket on your machine, and starts listening for requests. If it gets a request, it'll hand back a reference to that Array up there. At that point, the client can do whatever it wants with the Array.
So lets write a client:
#!/usr/bin/env ruby -w
# simple_client.rb
# A simple DRb client
require 'drb'
DRb.start_service
# attach to the DRb server via a URI given on the command line
remote_array = DRbObject.new nil, ARGV.shift
puts remote_array.size
remote_array << 1
puts remote_array.size
If you run simple_server.rb then take the URI it gives you and pass it into simple_client.rb, you'll get the following output:
0
1
How does this work? DRbObject.new nil, ARGV.shift
connects to the URI given on the pathname and connects to the Array there, and acts as a proxy to it. Any calls you make to the DRbObject get passed across to the Array you attached to on the server side.
Now what happens if you run simple_client.rb again with the same URI?
1
2
That's right, its a single instance of the array that is shared among all clients. You can attach any number of clients to the DRb service and have them all work on that one object. (Before you get all up in arms about concurrency issues, we'll get to an excellent way to handle concurrency called a TupleSpace in a future article.)
Biderectional Communication and DRbUndumped
Now you might be wondering why we had to put DRb.start_service in the client. The truth is that every DRb client is also a service. Lets look at another example that calculates the distance between to points:
#!/usr/bin/env ruby -w
# server
require 'drb'
class DistCalc
def find_distance(p1, p2)
Math.sqrt((p1.x - p2.x)**2 + (p1.y - p2.y)**2)
end
end
DRb.start_service nil, DistCalc.new
puts DRb.uri
DRb.thread.join
#!/usr/bin/env ruby -w
# client
require 'drb'
Point = Struct.new 'Point', :x, :y
class Point
include DRbUndumped
def to_s
"(#{x}, #{y})"
end
end
DRb.start_service
dist_calc = DRbObject.new nil, ARGV.shift
p1 = Point.new 0, 0
p2 = Point.new 1, 0
puts "The distance between #{p1} and #{p2} is #{dist_calc.find_distance p1, p2}"
Here the client provides two points to the server, and uses DRbUnumped to present a DRbObject to the server, rather than sending the point across the wire, creating a copy on each side. When the server asks for each point's x and y value, it connects back to the client to retrieve them.
This way the an object is always stored in only one place. If the server were to save the points, then recalulate them again later, the distance would still be accurate, since there is only one instance of each point in the system.
DRbUndumped can also be used to prevent large structures from being transfered. As an example, here is a jukebox server, and a tabletop jukebox console. The tabletop consoles will allow people to select songs to play from their tables.
The server has a list of songs, and the tabletop consoles are able to read those songs and select one to play. It doesn't make sense for the tabletop consoles to pull the entire song across the connection, so we'll only define it on the server.
#!/usr/bin/env ruby -w
# Jukebox Server
require 'drb'
Song = Struct.new 'Song', :title, :artist
class Song
def to_s
"#{title} by #{artist}"
end
end
class Jukebox
attr :songs
def initialize(songs)
@songs = songs
end
def play(index)
puts "playing #{@songs[index]}"
end
end
songs = [
Song.new("Amish Paradise", "Weird Al"),
Song.new("Eat it", "Weird Al")
]
DRb.start_service nil, Jukebox.new(songs)
puts DRb.uri
DRb.thread.join
#!/usr/bin/env ruby -w
# Tabletop client
require 'drb'
DRb.start_service
jukebox = DRbObject.new nil, ARGV.shift
loop do
puts "Select a song:"
jukebox.songs.each_with_index do |s, i|
puts "#{i + 1}) #{s}"
end
print "> "
STDOUT.flush
index = gets.to_i
begin
jukebox.play(index)
puts "Playing: #{jukebox.songs[index]}"
rescue
puts "Invalid selection"
retry
end
end
This looks good, but if you run the server then the client, you'll get an error message like this:
$ ruby client.rb druby://localhost:49812
Select a song:
/Users/drbrain/lib/ruby/drb/drb.rb:124:in `load': undefined class/module Struct::Song (ArgumentError)
from /Users/drbrain/lib/ruby/drb/drb.rb:124:in `load'
from /Users/drbrain/lib/ruby/drb/drb.rb:165:in `recv_reply'
from /Users/drbrain/lib/ruby/drb/drb.rb:299:in `send_message'
from /Users/drbrain/lib/ruby/drb/drb.rb:226:in `method_missing'
from /Users/drbrain/lib/ruby/drb/drb.rb:225:in `open'
from /Users/drbrain/lib/ruby/drb/drb.rb:225:in `method_missing'
from client.rb:11
from client.rb:8:in `loop'
from client.rb:27
When the client retrieves a song and tries to load it, the Song class isn't defined on the client. Since DRb uses Marshall to load and dump objects when sending them between client and server, the class must be defined on both sides of the connection.
There are two ways to resolve this, the obvous one is to define the Song class on both the client side, and the server side. The other way is to use include DRbUndumped on one side of the connection, and hand the other end a DRbObject.
If we add DRbUndumped, our extension to class Song will look like this:
class Song
include DRbUndumped
def to_s
"#{title} by #{artist}"
end
end
The client first attaches a DRbObject to the Jukebox instance on the server. Next the client asks for the songs on the Jukebox, and instead of getting back a Song instance, it instead gets back a DRbObject, since the Song class is now undumpable.
From: http://segment7.net/projects/ruby/drb/introduction.html
- [转]介绍分布式的Ruby(DRb)英文
- [转]介绍分布式的Ruby(DRb)英文
- [转]介绍分布式的Ruby(DRb)英文
- 分布式Ruby解决之道 - DRb
- 用ruby统计英文文章的词频
- 【转】唐三彩 英文介绍
- reSIProcate介绍(英文)
- ruby介绍的好博客
- 关于北京的英文介绍
- <a4j:keeyAlive>的英文介绍
- 中国行政区划的英文介绍
- java分布式的介绍
- Memcache的分布式介绍
- OSCommerce_3 使用的模板技术介绍(英文)
- make英文介绍(实例)
- Java基础介绍(英文)
- 分布式Ruby--杀手级Ruby应用(源于我的Ruby新书)
- 26本 Ruby/Rails 相关英文图书的简评
- 用ant 进行derby数据库开发
- Image与Base64字符串相互转换
- SQL Server 2005 管理员概述
- PHP中路径问题的解决方案
- UML辅助网站规划和设计指南
- [转]介绍分布式的Ruby(DRb)英文
- 面试题五
- 我的Blog开通了!
- JAVA字符集
- 判断DB启动时使用的是spfile还是pfile的方法
- spoolsv解决方法
- 数学趣题
- Struts的动态表单的应用
- 一个简单的PDF文件结构的分析