【问题标题】:realtime communication with ruby与 ruby​​ 实时通信
【发布时间】:2013-01-31 09:44:54
【问题描述】:

我即将用 ruby​​ 编写一个游戏服务器。游戏的一项功能包括玩家四处走动,其他人应该能够看到它。

我已经使用事件机器编写了一个纯套接字演示。但由于大部分通信都是基于 http 的,所以我正在寻找一些 http 轮询解决方案。当然,我可以用事件机器编写它,但是已经有适合这种工作的宝石了吗?

我尝试过类似 faye 的方法,但其中大部分是用于消息传递系统的,比如订阅和发布到频道,我似乎无法控制我应该推送到哪些客户端。就我而言,我需要能够推送给特定的客户,比如一个人从 10,10 移动到 20,20,只有他周围的人(可能从 0,0 到 30,30,但不是 40,50 的人) 需要接收消息。

------------前段痉挛

这里有一个快速更新。我正在处理抽筋问题,有 5000 个连接,每秒有 100 个客户端移动,CPU 使用率几乎是 100%。当我把这两个数字加倍时,CPU使用率仍然是100%左右,而且响应很慢。

显然,我并没有使用我拥有的所有资源,而是只占用了一个 CPU 内核。需要更多的工作。

------------Node.js的轮到

@aam1r 实际上 Node.js 比 cramp 做得更好。每秒有 5000 个连接和 100 个客户端移动,CPU 使用率超过 60%。当我翻倍到每秒 10000 个连接和 200 个客户端移动时,CPU 使用率为 100%,响应变慢。同样的问题,无论是 cramp 还是 Node.js,每个进程只能使用一个 cpu 核心。那是个问题。

------------JRuby呢?

由于GIL 的存在,Ruby MRI 无法实现真正​​的多线程同时执行。 Node.js 也没有。所以我要试试 JRuby。

  • 当客户端移动时,使用另一个线程来查找所有其他需要通知的客户端(这是一项占用大量 CPU 的工作)。然后将结果推送到频道。

  • 主线程只是订阅频道。得到结果后,推送给客户端。

不过需要一些时间来编写演示。

【问题讨论】:

    标签: ruby polling


    【解决方案1】:

    我建议将Espresso 与服务器发送的事件一起使用。

    在服务器端定义流式操作:

    class App < E
      map :/
    
      attr_reader :connections
    
      def subscribe
        @connections ||= []
        stream :keep_open do |conn|
          connections << conn
          conn.callback { connections.delete conn }
        end
      end
    
      private
      def communicate_to_clients
        connections.each do |conn|
          conn << 'some message'
        end
    end
    

    :keep_open 选项将指示服务器不要关闭连接。

    然后用Javascript打开一个连接:

    pool = new EventSource('/subscribe');
    pool.on_message = function(msg) {
      // here you receive messages sent by server
      // via communicate_to_clients method
    }
    

    【讨论】:

    • 哇,我怎么从来没有听说过浓缩咖啡?我计划在大多数服务器端使用 Sinatra,但 espresso 看起来是个不错的选择。但是,对于实时的东西,如果我错了,请纠正我,就像其他框架一样,espresso 需要一个单独的进程来处理每个请求,对吗?如果是这样,假设我有 1000 名玩家在线,那么我需要 1000 个进程,每个进程都针对单个玩家,我认为这行不通。
    • @DeanWinchester,不知道为什么你认为你需要多个进程。一个 Espresso 流程可以处理任意数量的请求。在示例中,我展示了一个 Espresso 进程,将连接添加到池并在需要时与它们通信。
    • 哦,那我就错了。我认为它就像其他框架、rails 或 sinatra 一样,使用单个进程来处理每个请求。我会仔细看看。
    • 这个项目似乎已经从地球上消失了。
    【解决方案2】:

    我建议不要使用轮询。轮询会导致过多的开销,因为您每次发出新请求时都会建立新连接。此外,它对您来说不够实时(即您将每 X 秒轮询一次——不是立即)

    相反,我建议使用Cramp 之类的东西。从他们的网站:

    Cramp 是一个完全异步的实时 Web 应用程序框架, 红宝石。它建立在 EventMachine 之上,主要设计用于 处理大量打开的连接并提供 全双工双向通信。

    您的所有客户端都将保持持久连接,通过该连接可以发送/接收消息。每次建立新连接都不会产生开销,并且消息将实时发送,因为客户端不会“每 X 秒”检查一次。

    您也可以使用 Node.js 代替 Cramp。它是一个 Javascript 框架,可用于开发实时应用程序。

    这里还有一些资源可以帮助您:

    【讨论】:

    • Cramp 看起来很有希望。我稍后会尝试。关于 Node.js,我看过一篇文章,比较它和事件机器的性能,这很糟糕。我不确定它是否那么糟糕。你碰巧有过 Node.js 性能方面的经验吗?
    • @DeanWinchester:我玩过 Node.js 框架,但从未构建过需要我担心性能的东西。我会搜索实际使用 Node 进行在线多人游戏的人发布的基准和/或结果。
    • 我应该自己写一个演示,也许明天。我会及时通知你。
    • 如果您仍然对此感到担忧,这里有一个快速更新。我还在努力解决问题,现在只要连接超过 1024,cpu 使用率就会直接达到 100%。我认为这与瘦有关,我现在正在谷歌上搜索。 PS:我怎么不能@你?
    • @DeanWinchester:似乎您必须开始调整您的网络服务器以实现大量连接。如果您在性能调优方面遇到困难,我建议您通过 ServerFault 寻求帮助。 (不确定@ btw)。
    猜你喜欢
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 2013-11-27
    • 2018-08-25
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    相关资源
    最近更新 更多