使用RPC的服务器上的多人纸牌游戏

时间:2012-10-18 00:04:58

标签: java python optimization webserver multiplayer

基本上我想要在服务器上运行Java,Python或C ++脚本,监听玩家实例:加入,调用,下注,弃牌,抽牌等等,并且在玩家离开或断开连接时也会超时。

基本上我希望每个动作都是一个小请求,这样玩家可以在同一台机器上与游戏服务器或网络上的机器进行通信。

消息传递的安全性不是问题,这是学习/研究/乐趣。

我的优先事项:

  1. 有一个很好的方案可以检测玩家何时断开连接,还可以在启动/导致丢失之前考虑网络延迟等。
  2. 速度。我将尽可能快地玩这些数百万只手。
  3. 在共享服务器实例上运行(我可能对端口或需要root的东西的访问权限有限)
  4. 我的问题:

    1. 监听端口或使用套接字或HTTP端口80 apache监听脚本? (我对这些之间的差异有点模糊)。
    2. 任何可以解决的好框架?
    3. 消息类型?我在想JSON或Protocol Buffers。
    4. 如何快速制作?
    5. 谢谢你们 - 只是寻找一些指示和建议。我认为这是一个很酷的问题,需要学习很多很好的东西。

3 个答案:

答案 0 :(得分:3)

就框架而言,Ginkgo看起来很有希望构建网络服务(这就是你正在做的事情)。 Python非常简单,gevent启用的异步性允许您执行异步操作而无需担心回调。 gevent核心还允许您访问lot of building blocks

您可以查看 1)良好的邮件队列,如RabbitMQ0mq 2,而不是让大量服务通过端口进行通信)分布式协调服务器,如Zookeeper

话虽这么说,你的目标很难,特别是如果你不熟悉基础知识的话。了解这些基础知识是值得的。

一开始不要担心速度。让它工作,然后使其规模化。当然,有一些方向可以让您在将来更容易扩展。 Zookeeper特别为您提供了易于实现的水平扩展原语(即多个工作者共享负载)。请特别注意Zookeeper recipe book及其相应的python implementations(由基于gevent的客户端库kazoo提供)。

不要忘记“快速”还意味着优化您自己的开发时间,以便更快地进行迭代,并减少诅咒开发环境的时间。所以使用Python,它可以让你现在快速启动和运行,如果你真的开始绑定CPU时间或内存使用,那么稍后进行优化。 (使用此特定应用程序,您更有可能在网络IO上绑定。)

答案 1 :(得分:2)

还有别的吗?也许一杯咖啡可以提出你的问题: - )

从头开始回答你的问题需要几本书的文章,主题从基本的TCP / IP网络到可扩展的架构,但我会尝试给你一些方向。

问题:

  1. 监听端口或使用套接字或HTTP端口80 apache监听脚本? (我对这些之间的差异有点模糊)。
  2. 如果你不清楚每一个的定义可能会设计一个实现“尽可能快地玩这些数百万手”的服务,我会冒昧地说,有点嗯,过度接触?但是,不要让那些阻止你,因为他们说“无知是幸福。”

    1. 任何可以解决的好框架?
    2. 我认为你的项目是Node.js的一个很好的候选人。主要原因是Node.js相对可扩展,并且擅长隐藏该可伸缩性所需的复杂性。 Node.js有缺点,只是谷歌搜索'Node.js可伸缩性批评'。 与使用更通用的框架相反,反对Node.js的主要观点是可伸缩性很难,没有办法绕过它,而Node.js如此高级别和特定性提供了解决问题的更少选项。 另一个缺点是Node.js是Javascript而不是Java或Phyton。

      1. 消息类型?我在想JSON或Protocol Buffers。
      2. 我认为客户端和服务器之间不会有大量的流量,所以我选择JSON并不重要,因为它更普遍。

        1. 如何快速制作?
        2. 真正的问题是如何使其可扩展。运行人类与人类卡片游戏不是计算密集型的,因此在达到任何计算限制之前,您可能会耗尽I / O容量。 克服这些限制是通过在机器之间分配负载来实现的。在多玩家游戏中常见的做法是使列表服务器提供到相同游戏服务器的链接,每个服务器具有可供玩家使用的预定数量的插槽。 这是代理工作者架构的变体,代理机器根据客户端的繁忙程度为客户端分配工作机器。在游戏中,用户希望能够选择他们的服务器,以便他们可以与朋友一起玩。

          相关:

          1. 有一个很好的方案可以检测玩家何时断开连接,还可以在启动/导致丢失之前考虑网络延迟等。
          2. 由于这是人类时间尺度(秒而不是毫秒),客户端应该发送Keepalive说每10秒说30秒会话超时。 Keepalive将是您的应用程序协议中的JSON消息,而不是HTTP,它是较低级别并由框架处理。 框架本身应该为您提供HTTP 1.1连接管理/池,它允许多个http会话(请求/响应)通过相同的连接,但不要求客户端始终连接。这是可靠性和速度之间的良好折衷,对于基于回合的纸牌游戏应该足够好。

答案 2 :(得分:1)

老实说,我从经典的LAMP开始。获取库存Apache服务器和mysql数据库,并将您的Python脚本放在cgi-bin目录中。他们发送和接收JSON而不是HTTP的事实并没有太大的区别。

当然,这显然不是最灵活或可扩展的解决方案,但它会迫使您尽早面对实际问题。

您遇到的第一个问题是游戏状态。你声称没有共享状态,但那不对 - 牌组中的牌,桌上的赌注,轮到它 - 所有状态,在多个玩家之间共享,在服务器。这些命令还有什么用呢?因此,您需要某种方式在CGI脚本的不同实例之间共享状态。经典的解决方案是将状态存储在数据库中。

当然,您还需要首先处理用户会话。细节取决于您选择的会话管理方案,但最大的问题是如何将断开/超时从较低级别传播到应用程序级别。如果有人将20美元放在桌面上然后断开连接,会发生什么?您必须仔细考虑所有可能的用例。

接下来,您需要考虑可扩展性。你想要数以百万计的游戏?好吧,如果有一个具有所有游戏状态的单个数据库,你可以在你面前拥有尽可能多的Web服务器 - John Doe可能在server1上,而Joe Schmoe在server2上,但是他们可以在同样的游戏。另一方面,每个服务器都可以有一个单独的数据库,只要你有办法强迫同一个游戏中的人在同一台服务器上相遇。哪一个更有意义?无论哪种方式,如何在服务器之间进行负载平衡。 (你不仅要让他们忙碌,你要避免4个玩家都准备好去的情况,但是他们会在3个不同的服务器上,所以他们不能互相玩耍......)。

这个过程的最终结果将是一个服务器的大量混乱,运行的容量是你希望的容量的1%,你不知道如何维护。但是你会更详细地思考你的问题空间,并且你也已经学会了服务器开发的基础知识,从长远来看这两者都可能更重要。

如果你有时间,我接下来把整个事情都抛出来,通过设计一个自定义的TCP协议从头开始重写所有内容,在Twisted中实现服务器,保持游戏状态。内存,编写一个简单的自定义代理而不是标准的负载均衡器。