首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DRb::DRbServerNotFound通过Sinatra params

DRb::DRbServerNotFound通过Sinatra params
EN

Stack Overflow用户
提问于 2011-06-05 15:08:42
回答 1查看 572关注 0票数 3

我有一个Sinatra应用程序和DRb服务器对象配对。当我试图将Sinatra params哈希传递给我的服务器对象上的一个方法时,我得到了DRb::DRbConnError … DRb::DRbServerNotFound,但是当我直接传递一个简单的散列时,同样的方法会工作。

  1. 为什么我在辛纳特拉参数散列中得到了这个错误?
  2. 解决这个问题的最简单和最正确的方法是什么?

下面是一个简单的测试用例:

代码语言:javascript
复制
# server.rb
require 'drb'
class Server; def echo( hash ); hash; end; end
DRb.start_service 'druby://localhost:9007', Server.new
DRb.thread.join
代码语言:javascript
复制
# app.rb
require 'sinatra'
require 'drb'    
SERVER  = DRbObject.new_with_uri 'druby://localhost:9007'
get("/params"){ SERVER.echo(params).inspect        }
get("/hash"  ){ SERVER.echo(hello:'world').inspect }

这两者都在它们自己的进程中运行:

代码语言:javascript
复制
phrogz$ curl http://localhost:4567/hash
{:hello=>"world"}

phrogz$ curl http://localhost:4567/params
DRb::DRbConnError - DRb::DRbServerNotFound:
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1653:in `current_server'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1721:in `to_id'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1050:in `initialize'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:642:in `new'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:642:in `make_proxy'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:559:in `rescue in dump'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:556:in `dump'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:603:in `block in send_request'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:602:in `each'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:602:in `send_request'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:903:in `send_request'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1196:in `send_message'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1088:in `block (2 levels) in method_missing'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1172:in `open'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1087:in `block in method_missing'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1105:in `with_friend'
 /usr/local/lib/ruby/1.9.1/drb/drb.rb:1086:in `method_missing'
 app.rb:4:in `block in <main>'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:1152:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:1152:in `block in compile!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:724:in `instance_eval'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:724:in `route_eval'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:708:in `block (2 levels) in route!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:758:in `block in process_route'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:755:in `catch'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:755:in `process_route'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:707:in `block in route!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:706:in `each'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:706:in `route!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:843:in `dispatch!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:644:in `block in call!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:808:in `instance_eval'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:808:in `block in invoke'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:808:in `catch'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:808:in `invoke'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:644:in `call!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:629:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.2.2/lib/rack/head.rb:9:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.2.2/lib/rack/commonlogger.rb:18:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/showexceptions.rb:21:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.2.2/lib/rack/methodoverride.rb:24:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:1272:in `block in call'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:1303:in `synchronize'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:1272:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.2.2/lib/rack/content_length.rb:13:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.2.2/lib/rack/chunked.rb:15:in `call'
 /usr/local/lib/ruby/gems/1.9.1/gems/thin-1.2.11/lib/thin/connection.rb:84:in `block in pre_process'
 /usr/local/lib/ruby/gems/1.9.1/gems/thin-1.2.11/lib/thin/connection.rb:82:in `catch'
 /usr/local/lib/ruby/gems/1.9.1/gems/thin-1.2.11/lib/thin/connection.rb:82:in `pre_process'
 /usr/local/lib/ruby/gems/1.9.1/gems/thin-1.2.11/lib/thin/connection.rb:57:in `process'
 /usr/local/lib/ruby/gems/1.9.1/gems/thin-1.2.11/lib/thin/connection.rb:42:in `receive_data'
 /usr/local/lib/ruby/gems/1.9.1/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in `run_machine'
 /usr/local/lib/ruby/gems/1.9.1/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in `run'
 /usr/local/lib/ruby/gems/1.9.1/gems/thin-1.2.11/lib/thin/backends/base.rb:61:in `start'
 /usr/local/lib/ruby/gems/1.9.1/gems/thin-1.2.11/lib/thin/server.rb:159:in `start'
 /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.2.2/lib/rack/handler/thin.rb:14:in `run'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/base.rb:1234:in `run!'
 /usr/local/lib/ruby/gems/1.9.1/gems/sinatra-1.2.6/lib/sinatra/main.rb:25:in `block in <module:Sinatra>'

这是在OS上的Ruby1.9.2下运行的,但我并不认为这有什么不同。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-05 17:09:05

简短回答

你需要添加

代码语言:javascript
复制
DRb.start_service

在尝试进行远程调用之前访问app.rb

如果你有兴趣解释

当引用缺少的键时,使用关联的块创建Sinatra params散列(这是消息来源)。这意味着有一个与其关联的Proc对象。

Drb通过编组参数来回传递参数。然而,来自元帅医生

有些对象不能转储:如果要转储的对象包括绑定、过程或方法对象、类IO实例或单例对象,则将引发TypeError。

因此,试图在线路上传递这个params散列会出现问题,因为它包含一个可解组的过程对象。

现在进入Drb文档

但是,如果无法对对象进行封送处理,则将传递或返回对其的dRuby引用。这将作为一个DRbObject实例出现在远程端。在此远程代理上调用的所有方法都被转发到本地对象,如DRbObjects讨论中所描述的那样。这具有类似于普通Ruby通过引用传递的语义。

好消息,应该还能用。那怎么了?在Drb文档中,我们可以在示例代码中找到这一点:

代码语言:javascript
复制
# Start a local DRbServer to handle callbacks.
#
# Not necessary for this small example, but will be required
# as soon as we pass a non-marshallable object as an argument
# to a dRuby call.
DRb.start_service

因此,似乎正在发生的是Drb试图获取过程对象传递给服务器的远程引用,但由于没有设置客户端的Drb服务,因此无法实现。

原始答案

(我把这个留在这里,也许我会感兴趣。这是我的旅程中的一个休息点,我想弄清楚这一切。这也是另一种可能的解决方案。有趣的是,我现在似乎是我所提到的更有知识的人,至少在原因方面是这样。)

这里有一个可能的解决办法。问题似乎在于使用块创建哈希来处理丢失的键(哪个Sinatra的params散列是),因此您可以将哈希的内容提取到一个新的哈希中。params.cloneparams.merge({})似乎都保留了proc (您可以使用Hash#default_proc检查),但是{}.merge(params) (或merge!)为您提供了一个与Drb一起工作的干净哈希。

因此,在本例中,执行以下操作:

代码语言:javascript
复制
get("/params"){ SERVER.echo({}.merge params).inspect

为什么这种情况发生在Drb和散列对procs,以及这是最简单或最正确的解决办法,我将留给一个更有知识的人。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6243729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档