问题描述
以下是我的赛璐codes代码.
Following are my Celluloid codes.
-
client1.rb
2个客户端之一. (我将其命名为客户端1)
client1.rb
One of the 2 clients. (I named it as client 1)
client2.rb
2个客户端中的第二个. (名为客户端2)
client2.rb
2nd of the 2 clients. (named as client 2 )
注意:
上述两个客户端之间的唯一区别是传递到服务器的文本.即(分别为'client-1'
和'client-2'
)
Note:
the only the difference between the above 2 clients is the text that is passed to the server. i.e ('client-1'
and 'client-2'
respectively)
在针对以下2台服务器(一次运行一台)测试这2个客户端(并排运行)时.我发现结果非常奇怪.
On testing this 2 clients (by running them side by side) against following 2 servers (one at time). I found very strange results.
-
server1.rb
(摘自自述文件的基本示例.赛璐ul-zmq的md )
将其用作上述2个客户端的示例服务器导致并行执行任务.
Using this as the example server for the 2 above clients resulted in parallel executions of tasks.
输出
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
注意:
client2.rb 消息在 client1.rb 请求处于睡眠状态时得到处理.(并行性标记)
Note:
the client2.rb message was processed when client1.rb request was on sleep.(mark of parallelism)
将其用作上述2个客户端的示例服务器没有导致并行执行任务.
Using this as the example server for the 2 above clients did not resulted in parallel executions of tasks.
输出
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
注意:
client-2 被要求等待60秒,因为 client-1 处于睡眠状态(睡眠60秒)
Note:
the client-2 was ask to wait 60 seconds since client-1 was sleeping(60 seconds sleep)
我多次运行以上测试,所有测试均导致相同的行为.
I ran the above test multiple times all resulted in same behaviour.
有人可以从上述测试的结果中解释我吗.
Can anyone explain me from the results of the above tests that.
问题:为什么赛璐ul要等待60秒才能处理其他请求(即在server2.rb情况下已注意到?)?
Question: Why is celluloid made to wait for 60 seconds before it can process the other request i.e as noticed in server2.rb case.?
ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
推荐答案
使用您的要点,我验证了此问题可以在MRI 2.2.1
以及jRuby 1.7.21
和Rubinius 2.5.8
中重现.... 和server2.rb
是后者中DisplayMessage
和message
类方法的使用.
Using your gists, I verified this issue can be reproduced in MRI 2.2.1
as well as jRuby 1.7.21
and Rubinius 2.5.8
... The difference between server1.rb
and server2.rb
is the use of the DisplayMessage
and message
class method in the latter.
在server1.rb
中使用sleep
时,实际上使用的是Celluloid.sleep
,但是在server2.rb
中使用时,它使用的是Kernel.sleep
...,这会将邮箱锁定Server
直到60秒已经通过.这样可以防止在邮箱再次处理消息(actor上的方法调用)之前,对该actor上的将来方法调用进行处理.
When sleep
is used in server1.rb
it is using Celluloid.sleep
in actuality, but when used in server2.rb
it is using Kernel.sleep
... which locks up the mailbox for Server
until 60 seconds have passed. This prevents future method calls on that actor to be processed until the mailbox is processing messages ( method calls on the actor ) again.
-
使用
defer {}
或future {}
块.
显式调用 Celluloid.sleep
而不是sleep
(如果未显式调用为Celluloid.sleep
,则使用sleep
会最终调用Kernel.sleep
,因为DisplayMessage
不会像Server
那样include Celluloid
)
Explicitly invoke Celluloid.sleep
rather than sleep
( if not explicitly invoked as Celluloid.sleep
, using sleep
will end up calling Kernel.sleep
since DisplayMessage
does not include Celluloid
like Server
does )
像server1.rb
一样将DisplayMessage.message
的内容带入handle_message
;或至少进入Server
(在Celluloid
范围内),并将使用正确的 sleep
.
Bring the contents of DisplayMessage.message
into handle_message
as in server1.rb
; or at least into Server
, which is in Celluloid
scope, and will use the correct sleep
.
def handle_message(message)
defer {
DisplayMessage.message(message)
}
end
Celluloid.sleep
方法:
The Celluloid.sleep
approach:
class DisplayMessage
def self.message(message)
#de ...
Celluloid.sleep 60
end
end
并不是真正的范围问题;这是关于异步的.
重申一下,更深层的问题不是sleep
的范围...这就是为什么defer
和future
是我的最佳建议的原因.但是要在我的评论中发表一些意见:
Not truly a scope issue; it's about asynchrony.
To reiterate, the deeper issue is not the scope of sleep
... that's why defer
and future
are my best recommendation. But to post something here that came out in my comments:
使用defer
或future
会推动一项任务,该任务会使actor陷入另一个线程.如果使用future
,则可以在任务完成后获取返回值;如果使用defer
,则可以触发&忘了.
Using defer
or future
pushes a task that would cause an actor to become tied up into another thread. If you use future
, you can get the return value once the task is done, if you use defer
you can fire & forget.
但是更好的是,为容易被束缚的任务创建另一个actor,甚至合并其他actor ...如果defer
或future
对您不起作用.
But better yet, create another actor for tasks that tend to get tied up, and even pool that other actor... if defer
or future
don't work for you.
我很乐意回答这个问题带来的后续问题;我们有一个非常有效的邮件列表和IRC频道.您的慷慨解囊值得称赞,但我们中的许多人会纯粹为您提供帮助.
I'd be more than happy to answer follow-up questions brought up by this question; we have a very active mailing list, and IRC channel. Your generous bounties are commendable, but plenty of us would help purely to help you.
这篇关于了解赛璐oid并发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!