PHP 8.1上行超时(110:未知错误)

t2a7ltrp  于 11个月前  发布在  PHP
关注(0)|答案(1)|浏览(338)

当有人在2023/03/29到达篮子时,我已经有了一个问题,这是一个不同的PHP错误,导致服务器崩溃。我不得不手动重启PHP服务。内存不足:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/mywebsite/prod/basket/basket_global.inc.php on line 956

所以我给PHP增加了一些内存,从昨天开始我就没有服务器崩溃(Nginx / PHP 8.1 / MySQL)!

memory_limit = 256M

昨天,我的服务器又崩溃了,我不得不手动重启php服务:

systemctl restart php8.1-fpm.service

又一次,就在有人走向篮筐之后:
access.log:

185.230.yyyy.xxx - - [27/May/2023:02:15:09 +0000] "GET /us/basket HTTP/1.1" 200 10466 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16"

error.log

2023/05/27 02:15:09 [error] 3221563#3221563: *18311176 upstream timed out (110: Unknown error) while reading response header from upstream, client: 185.230.yyyy.xxxx, server: mywebsite.com, request: "GET /us/basket/ HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock", host: "mywebsite.com"

然后在日志文件中只显示upstream timed out (110: Unknown error)错误!
它是随机发生的,不经常发生,所以我认为这是因为这个函数从篮子部分用一个无限的while循环来生成唯一的工作代码:

function get_newMerchantReference() {
    global $config, $dataBase;

    while(1) {
        $merchantReference = mt_rand(100, 999).'-'.mt_rand(100, 999).'-'.mt_rand(100, 999);

        $sql = $dataBase->prepare('SELECT count(*) AS num
                                   FROM oo__basket_infos_hext
                                   WHERE merchant_reference LIKE :reference');
        $sql->execute(array('reference'  => $merchantReference));
        $countUniqueId = $sql->fetch();
        $sql->closeCursor();
        $sql = $dataBase->prepare('SELECT count(*) AS num
                                   FROM oo__order_infos_hext
                                   WHERE merchant_reference LIKE :reference');
        $sql->execute(array('reference'  => $merchantReference));
        $countUniqueId2 = $sql->fetch();
        $sql->closeCursor();
        if($countUniqueId['num'] == 0 && $countUniqueId2['num'] == 0) { break; }
    }
    return $merchantReference;
}

这个while(1)循环会以随机的方式出错并导致PHP服务崩溃吗?
如何修改它来生成像213-126-323这样的随机数,这些随机数还没有被使用过,并且存储在oo__basket_infos_hextoo__order_infos_hext中?

kdfy810k

kdfy810k1#

如果您正在为引用生成一个随机数,那么我建议使用不太可能发生冲突的东西,比如UUID v4。碰撞的可能性非常低,你不需要一个循环来检查是否存在,你可以安全地假设没有重复。(不过,仍然要对列设置唯一约束。)
也就是说,如果您无法更改引用的格式,则可以转换为增量格式。从0开始,在数据库中使用自动递增/串行字段,并且每个记录递增1。然后用前导零和破折号格式化该值,因此0变为000- 000-000,依此类推。
如果你不能做到这一点,你需要使用这种格式,并让它是随机的,那么你需要接受它会随着时间的推移变得更慢(取决于音量),你对此无能为力。但仍有一些地方可以改进:
1.从mt_rand()切换到random_int(),它提供加密安全和统一选择的输出。
1.如果第一个查询返回了一行,就不需要执行第二个查询,您可以直接跳到下一个迭代,因为您已经知道您遇到了失败。
1.查询时未检查任何错误。prepare()fetch()可能返回false。
1.确保两个merchant_reference列在数据库中具有唯一约束。这将防止意外重复。
1.确保两个merchant_reference列都在数据库中建立了索引。这将使查找查询更快。
1.对迭代次数设置硬上限:

$cap = 0;
while (true) {
   if (++$cap > 10) {
       throw new Exception('too many tries');
   }
   query1
   if (query1 finds a result) {
        continue;
   }
   query2
   if (query2 finds a result) {
        continue;
   }
   return $value;
}

相关问题