下面是我的细胞密码。
client1.rb是两个客户之一。(我把它命名为客户1)client2.rb是2位客户中的第二位。(命名为客户2)注意:
上述两个客户机之间唯一的区别是传递给服务器的文本。即('client-1'和'client-2' )
在测试这两个客户端时(通过并行运行),对以下两个服务器进行测试(一次)。我发现了非常奇怪的结果。
server1.rb (一个基本的例子,从README.md的赛珍珠-zmq)
使用它作为上述两个客户端的示例服务器,将导致任务的并行执行。输出
ruby server1.rb
Received at 04:59:39 PM and message is client-1
Going to sleep now
Received at 04:59:52 PM and message is client-2注意:
当client1.rb请求处于睡眠状态时,会处理client2.rb消息。
server2.rb
使用它作为上面两个客户端的示例服务器,不会导致任务的并行执行。输出
ruby server2.rb
Received at 04:55:52 PM and message is client-1
Going to sleep now
Received at 04:56:52 PM and message is client-2注意:
客户端-2被要求等待60秒,因为客户端-1正在睡觉(60秒睡眠)
我多次运行上述测试,结果都是相同的行为。
有谁能从上面的测试结果中解释一下。
问题:为什么要等待60秒才能处理另一个请求,如server2.rb中所注意到的那样。
Ruby版本
ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
发布于 2016-01-30 17:52:18
使用你们的专家,我证实了这个问题可以在MRI 2.2.1以及jRuby 1.7.21和Rubinius 2.5.8中复制.server1.rb和server2.rb的区别在于在后者中使用了DisplayMessage和message类方法。
sleep在DisplayMessage中的使用超出了Celluloid的范围。
当sleep在server1.rb中使用时,它实际上使用的是Celluloid.sleep,而在server2.rb中使用的是Kernel.sleep。将邮箱锁定为Server,直到60秒过去。这将防止将来的方法调用要处理的该参与者,直到邮箱再次处理消息(方法调用该参与者)。
解决这一问题有三种方法:
defer {}或future {}块。Celluloid.sleep而不是sleep (如果没有以Celluloid.sleep身份显式调用,则使用sleep将最终调用Kernel.sleep,因为DisplayMessage不像Server那样include Celluloid )DisplayMessage.message的内容像server1.rb那样带到handle_message中;或者至少在Server中,这是Celluloid作用域中的内容,并且将使用正确的sleep。defer {}方法:
def handle_message(message)
defer {
DisplayMessage.message(message)
}
endCelluloid.sleep方法:
class DisplayMessage
def self.message(message)
#de ...
Celluloid.sleep 60
end
end这并不是真正的范围问题,而是异步问题。
重申一下,更深层次的问题不是sleep的范围.这就是为什么defer和future是我最好的推荐。但我要在这里发表我的评论:
使用defer或future会将一个任务推送到另一个线程中,这会导致参与者被捆绑在另一个线程中。如果使用future,任务完成后可以获得返回值,如果使用defer,则可以触发&忘记。
但是更好的是,创造另一个演员来完成那些容易被束缚的任务,甚至把其他的演员集中在一起……如果defer或future不适合你。
我非常乐意回答这个问题引起的后续问题;我们有一个非常活动邮件列表和IRC频道。你慷慨的赏赐是值得称赞的,但我们中的许多人都会帮助你。
https://stackoverflow.com/questions/35061826
复制相似问题