【问题标题】:PHP dealing with concurrencyPHP处理并发
【发布时间】:2013-05-24 19:21:24
【问题描述】:

我正在运行一个企业级 PHP 应用程序。这是一款浏览器游戏,在我的老板拒绝升级的基础设施上拥有数千名用户在线,并且机器始终以 2-3 系统负载(是的 linux)运行。无论如何,这不是真正的问题。真正的问题是,一些用户等到服务器加载完毕(黄金时间),然后他们带上鼠标点击器,然后点击同一个提交按钮 10 到 20 次,同时发送 10 到 20 个请求,而服务器仍在运行产生初始请求,因此没有更新缓存和数据库。

目前我对每个请求都有一个输出变量,有效期为 2 分钟,并且我有“互斥”锁,它基本上是内存缓存中的一个标志,如果发现它会进一步阻止脚本的执行,但是鼠标点击器会这样做许多请求几乎同时运行,这对我来说是个大问题。

你好吗,大多数 StackOverflow 人都在处理这个问题。我正在考虑标记 cookie/会话,但我认为如果服务器超载,我会遇到同样的问题。优化是不可能的,源已经 7 年了,并且已经非常优化,在大多数页面上都没有查询(运行缓存),并且只在某些用户输入上查询数据库,就像我试图阻止的那样。

是的,它是没有真实对象的程序代码。机器运行 PHP 5,但代码本身更像是 PHP 4。我知道,我知道它已经过时了,但我们无法节省重写这整个混乱的资源,因为大多数原始开发人员都离开了,他们知道事情是如何交织在一起的是的,我基本上是在修补旧漏洞。但据我所知,这是加载的 PHP 网站上的普遍问题。

P.S:在提交时禁用带有 javascript 的按钮不是一个选项。真正的作弊者是高级用户。其中一个人编写了一个机器人点击器并将其打包为 Google Chrome 扩展程序。不要问我是怎么处理的。

【问题讨论】:

  • 你是怎么处理的..? :)
  • 我使用 websockets。按请求处理的模型非常不适合这类事情。
  • 是的,这个应用程序很旧,它没有现代网站使用的那种花哨的 MVC/Bigpipe/JSON/HTML5 History 东西。它有太多的“修补程序”,只是把那个界面放在上面
  • 点击小验证码 (sp?) 会停止除最高级之外的所有操作。我们在一个基于网络的游戏中遇到了同样的问题,我在任何时候都为几百个用户工作过等等,我们最终得到了提交,所以所有的请求都通过了,但是在第一个请求被提交之后,任何进一步的操作(发送相同的舰队多次次)被阻止并丢弃。它仍然会生成初始请求,但只要它们的处理没有发生,它们就无关紧要,提交事件在负载生成中是次要的。如果您正在为 http 负载苦苦挣扎,请考虑将 apache 移至 cherokee/nginx/lighttpd
  • 我再说一遍——问题是你的技术栈。传统的 PHP Web SAPI + Apache + Ajax 一直不是具有高并发性的事件驱动应用程序的好解决方案,因为......嗯......曾经。

标签: php concurrency enterprise


【解决方案1】:

我会在您的代码之外寻找解决方案。

不知道你使用的是哪个服务器,但 apache 有一些模块,例如 mod_evasive。

您还可以限制防火墙中某个 IP 的每秒连接数

【讨论】:

    【解决方案2】:

    我感觉这比其他任何事情都更涉及如何更新遗留代码库。虽然实现某种类型的并发会很好,但旧代码库才是真正的问题。

    我强烈推荐 this video 讨论技术债务。

    观看它,如果您还没有,请用业务术语向您的老板解释什么是技术债务。他很可能会明白这一点。说明由于代码管理不善(债务偿还),技术债务水平非常高。向他/她建议如何通过使用小的增量迭代来改进事情来解决这个问题。

    【讨论】:

    • 这个视频很精彩。
    【解决方案3】:

    限制 IP 连接只会让你的玩家生气。 我用旧式代码修复并重写了一些著名的开源游戏克隆中的很多东西: 好吧,我必须说,作弊总是可以避免执行正确的查询和逻辑。 例如看这里http://www.xgproyect.net/2-9-x-fixes/9407-2-9-9-cheat-buildings-page.html

    无论如何,关于性能,请记住会话中的代码将阻塞所有其他线程,直到当前线程关闭。所以要小心地将所有代码包含在会话中。此外,会话不应包含大量数据。

    关于脚本:在我的游戏中,我有一个 php 模块,它自动重写链接,添加一个保存在数据库中的随机 id,一种 CSRF 保护。人类用户将单击更改的链接,因此他们将看不到更改,但脚本会尝试询问旧链接,并且在尝试后被禁止! 其他脚本使用 DOM,因此很容易避免它们在页面周围插入一些无用的 DIV。

    编辑:您可以使用 https://github.com/facebook/hiphop-php/wiki 提升您的应用程序

    【讨论】:

      【解决方案4】:

      我不知道是否已经有一个实现,但我正在研究编写一个缓存服务器,它负责在缓存未命中时填充自己。这种方法在这种情况下可以很好地工作。

      基本上,您需要一种机制来将缓存槽标记为未命中待处理;读取挂起的值应该导致客户端休眠一小段但随机的时间并重试;传统模型中待处理数据的填充将由遇到未命中而不是待处理的客户端完成。

      在这种情况下,脚本是客户端,而不是浏览器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-11
        • 2011-01-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多