为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用MySQL + PHP + nginx并行化请求?

如何使用MySQL + PHP + nginx并行化请求?

PHP
森林海 2022-08-05 16:33:59
最近发现在我尝试过的其他所有操作中,我用自定义JavaScript替换了我的JMeter配置文件,该JavaScript在无限循环中依次命中我的每个API端点,然后在不同的浏览器(一个Firefox,一个Chrome,一个Safari)中并行运行此脚本 - 以尝试排除与我来自同一来源的所有连接相关的问题(相同的用户代理, 相同的 Cookie、相同的会话 ID 等)当我这样做时,我注意到我的所有问题都消失了。查询并行运行,该应用程序的响应速度比JMeter让您相信的要快得多。在我看来,JMeter不可能序列化请求,因为它是负载测试的事实标准。所以我开始尝试重现这种行为。为了重新创建JMeter,我创建了以下两个PHP脚本,它们(希望)模拟了我的Yii应用程序:慢.php<?phpsession_start();$_SESSION['some'] = 'value';// Yii is calling session_write_close() almost immediately after// the session is initialized, but to try and exacerbate issues,// I've commented it out:// session_write_close();$dsn = "mysql:host=localhost;dbname=platypus;unix_socket=/tmp/mysql.sock";$pdo = new PDO($dsn, "user", "password");// Yii was using whatever the default persistence behavior was,// but to try and exacerbate issues I set this flag:$pdo->setAttribute(PDO::ATTR_PERSISTENT, true);// Simulate a query running for 1 second by issuing a 1-second sleep$pdo->query("DO SLEEP(1)");echo "Done";快速.php<?phpsession_start();$_SESSION['some'] = 'value';$dsn = "mysql:host=localhost;dbname=platypus;unix_socket=/tmp/mysql.sock";$pdo = new PDO($dsn, "user", "password");$pdo->setAttribute(PDO::ATTR_PERSISTENT, true);// Simulate a query running for 0.1 seconds$pdo->query("DO SLEEP(0.1)");echo "Done";针对这两个新端点运行 JMeter 时,没有序列化请求。一切都是并行运行的。fast.php总是在100-150ms内返回并且速度很慢.php总是在1000-1050ms内返回,即使我扩展到3,4和5个线程也是如此。我能够看到东西在11个线程处崩溃,但那是因为我超过了PHP中的工作线程数。所以总结一下:仅当使用 JMeter 分析我的 API 时,才会出现此问题,而这并不是应用本身所固有的这个问题不仅仅是一个JMeter错误,而是以某种方式与我的应用程序或Yii 1.1有关。我尝试过,但无法提出最小的重现案例尽管在使用其他工具进行分析时不存在该问题,但很多人都做出了回应并提供了许多有用的信息:避免PHP中的持久连接(可能导致多个请求共享一个连接,可能不是)通过尽早呼叫来避免会话锁定session_write_close()确保有足够的 PHP 工作线程来处理同时连接数MySQL完全支持并行请求(如果硬件可以处理它)警惕表锁定(任何具有语句的事务都可能锁定表)UPDATEMyISAM 执行表级锁定而不是行级锁定
查看完整描述

4 回答

?
ibeautiful

TA贡献1993条经验 获得超6个赞

MySQL + PHP + Apache一直非常擅长在“并行”中运行单独的SQL语句。如果单独的用户发出HTTP请求,他们自然会快速通过Apache(可能是按顺序,但很快)并到达单独的PHP实例(假设Apache已经配置了足够的“子级”)。每个PHP脚本都会建立自己的连接MySQL。MySQL将非常快速地接受多个连接(假设足够高,这是默认的)。每个MySQL连接都将独立工作(禁止低级数据库锁,互斥锁等)。每个都将在完成后完成,PHP也是如此,Apache将结果返回给用户。max_connections

我假设(不确定)nginx的工作原理类似。

注意:我建议Apache(和nginx)按顺序做事。但我怀疑将HTTP请求传递给PHP需要一毫秒的数量级,所以这个“串行”步骤不会解释你找到的时间。

我的结论是,其中一个并没有真正发生:

  • 每个步骤的配置不允许3个子/连接/等,或者

  • 有 3 个单独的 HTTP 请求。

  • 有 3 个单独的 PHP 脚本。

  • 这 3 个 SQL 语句不会相互阻止。(请提供 SQL。注意:使用表锁定;仅此一点,就可以解释问题所在。(请提供 。ENGINE=MyISAMSHOW CREATE TABLE

也许有可能(在看到SQL之后)加速SQL,从而减少整体的迟钝问题。

查询

假设 是每个表的,那么这些其他索引可能有利于加速查询 2:idPRIMARY KEY

backup_broadcast:  (deletion, id)

shares:  (media_type, media_id, site_id)

broadcast:  (site_id, id)

video:  (deletion, id)

playlists_playlists:  (playlist_id, broadcast_id)

playlist_broadcast闻起来像一个“多对多映射”表。如果是这样,我建议按照 http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table 中的提示进行操作。(同上,对于任何类似的表。

OR并且往往是低效的结构。但听起来您无法控制查询?IN ( SELECT ... )

这是没有?的吗?你关心你得到哪10行吗?这将是不可预测的。LIMITORDER BY

如此大量的列会发生什么?似乎每次运行查询时它们中的大多数都是相同的,因此主要是浪费时间??

对于查询 3,需要(按任一顺序)。但是,将其重新配制为使用或可能会运行得更快。siteINDEX(deletion, customer_id)JOINEXISTS


查看完整回答
反对 回复 2022-08-05
?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

我认为你有一个php会话锁定的问题:你的第二个和第三个查询正在尝试访问相同的php会话,并且正在等待。

尝试尽快调用,以释放您的php会话。尽快:当你确定你不会在你的php会话中写入更多的数据。session_write_close

检查这一点的一种简单方法是尝试使用2个浏览器或匿名/隐身模式:您的cookie不会被共享,您应该有2个会话,而不是相互阻止。


查看完整回答
反对 回复 2022-08-05
?
慕的地8271018

TA贡献1796条经验 获得超4个赞

MySQL可以处理很多并行查询,但你不能一次为每个连接做多个查询。PHP通常的设置方式是每个请求转到不同的线程/进程,因此每个进程都将具有与MySQL的自己的连接,从而避免了提到的问题。除非您在PHP中使用持久连接,否则您可能最终为每个请求使用相同的连接。如果是这种情况,应该很容易禁用它并返回到每个请求模型的标准一个数据库连接。

我的第一个猜测是,端点 2 会触发数据库上的一些锁定,这就是为什么端点 3 查询排队直到 enpoint2 的查询完成的原因。这可以通过更改代码中的逻辑(避免或最小化数据库锁定)或通过更改用于更好地满足应用程序需求的数据库配置或表引擎来解决。示例:InnoDB使用行级锁定,而MyISAM锁定整个表锁定。

如果您不介意配置它,则分析将非常有用。我建议看看 Blackfire.io,New Relic或xdebug分析,如果你走这条路。您将能够通过这种方式更快地找到瓶颈。


查看完整回答
反对 回复 2022-08-05
?
翻阅古今

TA贡献1780条经验 获得超5个赞

嗯......评论太长。

稍微简化一下,每个引擎都有一个队列,它收集要计算的查询,根据硬件的不同,它使用2或3甚至更多的线程来计算每个查询。由于锁,每个查询需要的线程运行的时间更多,就像它使用自动增量插入新行时锁定整个表一样。(通过搜索,您会发现许多锁的示例)。当然,每个查询都需要内存和其他资源,它们必须与服务器上运行的所有计算机软件的其余部分共享。

使用 clustes,您可以支付管理多个 sql 服务器的开销。

所以从sql服务器端来看,它是并行的,但是你需要硬件来支持许多线程/许多引擎(应该非常小心地使用)

当然,你可以在sql中有很多用户,但为了方便起见,你通常每个APP都有一个,有时甚至每个服务器一个。但是同一用户可以同时访问数据库,但您当然可以禁用它。

你的php并行运行,因为Web服务器是为运行paparel请求而构建的,在那里,它是否运行php,Python(django)或javascript(nodejs),apache,IIS,nginx以及更多,每种技术都有好处,并且会导致更多的模块添加到en引擎,它的速度要慢得多。

因此,一切都在一定程度上是平行的,您可以增加诸如在云提供商或虚拟服务器等中看到的此类系统的功能。

只有当口袋妖怪go的引入或新游戏甚至巨大的云提供商崩溃时,您才会注意到这些限制。或者奥巴马医改的灾难,没有任何东西在那种规模上进行测试,无论哪种情况......负责,

并行化这些任务是很困难的,因为在Web服务器和sqlserver的情况下,它具有一定程度的缓存,它们在其中停放经常发出的请求,但通常每个请求都需要自己的数据。

实际上,一切都要复杂得多,从具有3个管道的cpu开始,多个内核和共享内存(导致Meltdown及其兄弟),包括仅驻留在内存中的表或数据库以获得高性能或仅在CPU缓存中运行的Web服务器,这比内存或硬盘驱动器快得多.....


查看完整回答
反对 回复 2022-08-05
  • 4 回答
  • 0 关注
  • 189 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号