类 DRb::DRbServer
类
代表一个 drb 服务器实例。
在任何传入的 dRuby 调用被接受之前,或者任何本地对象被作为 dRuby 引用传递给远程进程之前,即使这些本地对象从未被远程调用,也必须在本地进程中运行 DRbServer。如果您只进行传出的 dRuby 调用并传递序列化参数,则无需在本地进程中启动 DRbServer。
除非使用多个服务器,否则本地 DRbServer 通常通过调用 DRb.start_service
启动。
常量
- INSECURE_METHOD
不安全方法列表。
这些方法无法通过 dRuby 调用。
属性
此 DRbServer 的配置
DRbServer 的前端对象。
此对象接收对服务器的 URI
以及对象 ID 进行的远程方法调用。
此 DRbServer 的主线程。
这是监听并接受来自客户端的连接的线程,而不是处理每个客户端的请求-响应会话的线程。
此 DRbServer 的 URI
。
公共类方法
设置 :argc_limit 选项的默认值。
参见 new()。初始默认值为 256。
# File lib/drb/drb.rb, line 1361 def self.default_argc_limit(argc) @@argc_limit = argc end
Set
:load_limit 选项的默认值。
参见 new()。初始默认值为 25 MB。
# File lib/drb/drb.rb, line 1368 def self.default_load_limit(sz) @@load_limit = sz end
创建一个新的 DRbServer 实例。
uri
是要绑定的 URI
。通常格式为 ‘druby://<hostname>:<port>’,其中 <hostname> 是本地机器的主机名。如果为 nil,则会绑定到系统默认主机名,端口由系统选择;这些值可以从 uri
属性中获取。‘druby:’ 指定了默认的 dRuby 传输协议:可以指定其他协议,例如 ‘drbunix:’。
front
是服务器的前端对象,即远程方法调用将传递到的对象。如果为 nil,则服务器将不接受远程方法调用。
如果 config_or_acl
是一个哈希表,则它是此服务器要使用的配置。以下选项被识别
- :idconv
-
一个 id 到对象的转换对象。默认值为
DRb::DRbIdConv
类的实例。 - :verbose
-
如果为 true,则服务器中所有对象的远程调用失败都会被记录到 $stdout。默认值为 false。
- :tcp_acl
-
此服务器的访问控制列表。参见主 dRuby 发行版中的
ACL
类。 - :load_limit
-
服务器接受的最大消息大小(以字节为单位)。默认值为 25 MB (26214400)。
- :argc_limit
-
服务器接受的远程方法的最大参数数量。默认值为 256。
这些选项的默认值可以通过类方法 default_argc_limit、default_load_limit、default_acl、default_id_conv 和 verbose=
在类范围内修改。
如果 config_or_acl
不是哈希表,但不是 nil,则假定它是此服务器的访问控制列表。有关更多详细信息,请参见 :tcp_acl 选项。
如果当前没有其他服务器被设置为主服务器,那么它将成为主服务器。
服务器将立即在其自己的线程中开始运行。
# File lib/drb/drb.rb, line 1451 def initialize(uri=nil, front=nil, config_or_acl=nil) if Hash === config_or_acl config = config_or_acl.dup else acl = config_or_acl || @@acl config = { :tcp_acl => acl } end @config = self.class.make_config(config) @protocol = DRbProtocol.open_server(uri, @config) @uri = @protocol.uri @exported_uri = [@uri] @front = front @idconv = @config[:idconv] @grp = ThreadGroup.new @thread = run DRb.regist_server(self) end
获取 :verbose 选项的默认值。
# File lib/drb/drb.rb, line 1394 def self.verbose @@verbose end
Set
:verbose 选项的默认值。
参见 new()。初始默认值为 false。
# File lib/drb/drb.rb, line 1389 def self.verbose=(on) @@verbose = on end
公共实例方法
此服务器是否处于活动状态?
# File lib/drb/drb.rb, line 1506 def alive? @thread.alive? end
检查方法是否可以通过 dRuby 调用。
obj
是我们要在其上调用方法的对象。msg_id
是方法名称,以 Symbol
形式表示。
如果方法是不安全的(参见 insecure_method?
),则会抛出 SecurityError
。如果方法是私有的或未定义的,则会抛出 NameError
。
# File lib/drb/drb.rb, line 1594 def check_insecure_method(obj, msg_id) return true if Proc === obj && msg_id == :__drb_yield raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id) case obj when Object if obj.private_methods.include?(msg_id) desc = any_to_s(obj) raise NoMethodError, "private method `#{msg_id}' called for #{desc}" elsif obj.protected_methods.include?(msg_id) desc = any_to_s(obj) raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" else true end else if Kernel.instance_method(:private_methods).bind(obj).call.include?(msg_id) desc = any_to_s(obj) raise NoMethodError, "private method `#{msg_id}' called for #{desc}" elsif Kernel.instance_method(:protected_methods).bind(obj).call.include?(msg_id) desc = any_to_s(obj) raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" else true end end end
uri
是否是此服务器的 URI
?
# File lib/drb/drb.rb, line 1511 def here?(uri) @exported_uri.include?(uri) end
停止此服务器。
# File lib/drb/drb.rb, line 1516 def stop_service DRb.remove_server(self) if Thread.current['DRb'] && Thread.current['DRb']['server'] == self Thread.current['DRb']['stop_service'] = true else shutdown end end
将本地对象转换为 dRuby 引用。
# File lib/drb/drb.rb, line 1533 def to_id(obj) return nil if obj.__id__ == front.__id__ @idconv.to_id(obj) end
将 dRuby 引用转换为它所引用的本地对象。
# File lib/drb/drb.rb, line 1526 def to_obj(ref) return front if ref.nil? return front[ref.to_s] if DRbURIOption === ref @idconv.to_obj(ref) end
获取服务器是否处于详细模式。
在详细模式下,失败的调用将记录到标准输出。
# File lib/drb/drb.rb, line 1503 def verbose; @config[:verbose]; end
Set
是否以详细模式运行。
在详细模式下,失败的调用将记录到标准输出。
# File lib/drb/drb.rb, line 1498 def verbose=(v); @config[:verbose]=v; end
私有实例方法
将对象强制转换为字符串,如果对象未定义 to_s,则提供我们自己的表示。
# File lib/drb/drb.rb, line 1580 def any_to_s(obj) "#{obj}:#{obj.class}" rescue Kernel.instance_method(:to_s).bind_call(obj) end
# File lib/drb/drb.rb, line 1696 def error_print(exception) exception.backtrace.inject(true) do |first, x| if first $stderr.puts "#{x}: #{exception} (#{exception.class})" else $stderr.puts "\tfrom #{x}" end false end end
方法是否已包含在不安全方法列表中?
# File lib/drb/drb.rb, line 1574 def insecure_method?(msg_id) INSECURE_METHOD.include?(msg_id) end
DRbServer 内部线程执行的主循环。
接受来自客户端的连接,并启动自己的线程来处理它。此线程循环,接收来自客户端的请求,在本地对象上调用它们,并返回响应,直到客户端关闭连接或本地方法调用失败。
# File lib/drb/drb.rb, line 1714 def main_loop client0 = @protocol.accept return nil if !client0 Thread.start(client0) do |client| @grp.add Thread.current Thread.current['DRb'] = { 'client' => client , 'server' => self } DRb.mutex.synchronize do client_uri = client.uri @exported_uri << client_uri unless @exported_uri.include?(client_uri) end _last_invoke_method = nil loop do begin succ = false invoke_method = InvokeMethod.new(self, client) succ, result = invoke_method.perform error_print(result) if !succ && verbose unless DRbConnError === result && result.message == 'connection closed' client.send_reply(succ, result) end rescue Exception => e error_print(e) if verbose ensure _last_invoke_method = invoke_method client.close unless succ if Thread.current['DRb']['stop_service'] shutdown break end break unless succ end end end end
在新的线程中启动 DRb
主循环。
# File lib/drb/drb.rb, line 1555 def run Thread.start do begin while main_loop end ensure @protocol.close if @protocol end end end
# File lib/drb/drb.rb, line 1540 def shutdown current = Thread.current if @protocol.respond_to? :shutdown @protocol.shutdown else [@thread, *@grp.list].each { |thread| thread.kill unless thread == current # xxx: Thread#kill } end @thread.join unless @thread == current end