Understanding Celluloid Concurrency

前端 未结 2 1045
北恋
北恋 2021-02-20 12:49

Following are my Celluloid codes.

  1. client1.rb One of the 2 clients. (I named it as client 1)

  2. client2.rb 2nd of the 2 clients. (named as client 2

2条回答
  •  天涯浪人
    2021-02-20 13:14

    Managed to reproduce and fix the issue. Deleting my previous answer. Apparently, the problem lies in sleep. Confirmed by adding logs "actor/kernel sleeping" to the local copy of Celluloids.rb's sleep().


    In server1.rb,

    the call to sleep is within server - a class that includes Celluloid.

    Thus Celluloid's implementation of sleep overrides the native sleep.

    class Server
      include Celluloid::ZMQ
    
      ...
    
      def run
        loop { async.handle_message @socket.read }
      end
    
      def handle_message(message)
    
            ...
    
            sleep 60
      end
    end
    

    Note the log actor sleeping from server1.rb. Log added to Celluloids.rb's sleep()

    This suspends only the current "actor" in Celluloid i.e. only the current "Celluloid thread" handling the client1 sleeps.


    In server2.rb,

    the call to sleep is within a different class DisplayMessage that does NOT include Celluloid.

    Thus it is the native sleep itself.

    class DisplayMessage
        def self.message(message)
    
               ...
    
               sleep 60
        end
    end
    

    Note the ABSENCE of any actor sleeping log from server2.rb.

    This suspends the current ruby task i.e. the ruby server sleeps (not just a single Celluloid actor).


    The Fix?

    In server2.rb, the appropriate sleep must be explicitly specified.

    class DisplayMessage
        def self.message(message)
            puts "Received at #{Time.now.strftime('%I:%M:%S %p')} and message is #{message}"
            ## Intentionally added sleep to test whether Celluloid block the main process for 60 seconds or not.
            if message == 'client-1'
               puts 'Going to sleep now'.red
    
               # "sleep 60" will invoke the native sleep.
               # Use Celluloid.sleep to support concurrent execution
               Celluloid.sleep 60
            end
        end
    end
    

提交回复
热议问题