0

例如,如果我们在 server 上有某个 php 文件getProducts.php。当多个用户同时请求它时,它会被中断吗?例如,如果一个用户询问产品 A 的详细信息,另一个用户询问产品 B 的详细信息,另一个用户询问产品 C 的详细信息,等等...... php 会被中断吗?或者它是一个自我生成的线程系统,可以根据每个请求工作和响应?

谢谢!

4

2 回答 2

8

出乎意料的是,这与 PHP 几乎没有关系。回答用户请求的不是 PHP,而是Web 服务器。例如 Apache、NginX、IIS 等。

然后,Web 服务器将调用路由到一个 PHP 实例,该实例通常独立于在那个确切时刻满足的任何其他请求。并发请求的数量取决于服务器配置、架构和平台能力。所谓的“C10K”服务器被设计为同时提供多达一万个连接。

但是 PHP 并不是从“GET /index.php”到一堆 HTML 的过程中的唯一因素。任何活动页面(PHP 或 ASP 或 Python 等)都可以从例如数据库请求更多资源。在这种情况下会出现并发问题,并且每当两个用户需要获取相同的资源(数据表中的一行、整个表、一个日志文件......)时,某种 信号量系统会使得只有一个他们一次可以获得该特定资源的“锁定”,所有其他人都必须等待轮到他们,即使覆盖的 Web 服务器能够处理数百或数千个并发连接。

性能问题的更新:PHP 中也会发生同样的情况,例如会话。想象一下,您有一个用户请求一个页面,并且该页面有代码来生成另外十个调用(对图像、弹出窗口、广告、AJAX ......)。第一个请求打开一个会话,它是一堆必须保持一致的数据。因此,当其他十个调用都绑定到同一个会话时,PHP 无法知道这些调用中的任何一个是否想要修改会话数据——它没有办法,只能阻止第二个调用继续进行,直到第一次调用已释放会话锁,一旦释放,第二次调用将阻塞第三次,依此类推。要点:避免session_start()如果不需要它(例如用加密强的 GET 令牌替换它或完全不这样做),或者session_commit()在您完成修改_SESSION的值后立即调用,将大大提高性能。(因此将使用更快的会话管理器,或者不使用粗锁的会话管理器:例如redis)。

例如在图像生成中:

session_start();
// This does the magic.
session_commit();
// We can still read session. We just can't write it anymore.

// That's why we needed a session.
if (!isset($_SESSION['authorized'])) {
    Header('HTTP/1.1 403 Forbidden');
    die();
}
// Here the code that generates an image *and sends* it. The session
// lock, if we hadn't committed, will *not* expire until the request
// has been processed by the *client* with network slowness. (Things
// go much better if you use the CGI interface instead of module).

在您的示例中并看到“WAMP”标签,您有一个 Windows Apache 为 PHP 从 MySQL 检索的数据提供服务,并为产品提供服务请求。

Apache 服务器将接收数百个连接,激活数百个 PHP 模块实例(它们将共享大部分代码,因此内存占用不会快速上升),然后所有这些实例都会询问 MySQL,“什么关于产品 XYZ?”。用 MySQL 的话来说,他们会尝试获取一个READ LOCK. 读锁的意思是,“我正在读这个东西,所以请你们不要在我写完之前在上面写字”。但他们都只是在阅读,所以他们都会成功 - 同时。

所以不,不会有任何停留——就在那时。

但假设您还想更新产品视图的计数器。然后每个 PHP 实例也需要一个WRITE LOCK,这意味着,“我想在这个东西上写,所以在我完成之前你们都不要阅读,否则你会冒险阅读半生不熟的数据,当然你们也不要在这里,而我会去的”。

此时,表类型很重要。MyISAM 表具有表锁定功能:如果正在更新产品 A 的统计信息的实例正在写入product_views,则没有其他实例能够对整个表执行任何操作。他们都会排队等候。如果表是InnoDB,则锁是级的——所有更新产品 A 的实例将一个接一个地排队,与更新产品 B、C、D 等的实例并行。因此,如果所有实例都写入不同的记录,它们将并行运行。

这就是为什么你真的想在这些情况下使用 InnoDB 表。

当然,如果您有“页面访问”之类的记录,并且它们都在更新“product-page.php”的行,那么您就存在瓶颈,并且在高流量站点的情况下,您会如果您设计了其他写入该信息的方式(许多解决方法之一是将其存储在共享内存位置中;访问它的众多实例中的一个不时地接收将信息保存到数据库的任务。实例仍然竞争内存锁定,但这比竞争数据库事务要快几个数量级)。

于 2012-11-06T01:55:22.743 回答
3

如果您使用的是 apache,它是一个并发系统。这意味着每个请求都将被并行处理,因此您的 php 脚本不会被中断。

于 2012-11-06T01:51:58.840 回答