【问题标题】:php - try, catch, and retryphp - 尝试、捕获和重试
【发布时间】:2014-07-28 18:47:34
【问题描述】:

有时我的代码会中断并且我无法控制

我将如何执行以下操作?

try {
//do my stuff
}
catch {
//sleep and try again
}

代码不多,所以都是一个函数,所以我不想制作和调用另一个函数,如果我不需要的话

【问题讨论】:

  • 同一操作要重试多少次?为什么要重试失败的操作?究竟什么是你无法控制的?
  • 几次。我使用的第三方 api 每隔一段时间就会下降几分钟。
  • @oliakaoil,如果那个“你为什么要重试失败的操作?”在一般意义上被问到:如果发生 可恢复的错误,则 ex.处理程序可以解决问题并通过重试让正常流程继续进行。事实上,现在甚至有一个retry 的 RFC:wiki.php.net/rfc/retry-keyword

标签: php try-catch


【解决方案1】:

你可以试试这样的:

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

$NUM_OF_ATTEMPTS = 5;
$attempts = 0;

do {

    try
    {
        executeCode();
    } catch (Exception $e) {
        $attempts++;
        sleep(1);
        continue;
    }

    break;

} while($attempts < $NUM_OF_ATTEMPTS);

function executeCode(){
    echo "Hello world!";
}

在这里,我们执行do...while 循环,以便代码至少执行一次。如果executeCode() 函数遇到错误,它将抛出Exception try...catch 块将捕获的。然后catch 块将变量$attempt 加一并调用continue 来测试下一次迭代的while 条件。如果已经进行了五次尝试,则循环将退出并且脚本可以继续。如果没有错误,即catch块中的continue语句没有被执行,循环将break,从而完成脚本。

注意set_error_handler 函数的使用取自here。我们这样做是为了捕获 executeCode() 函数中的所有错误,即使我们自己没有手动抛出错误。

如果您认为您的代码可能会多次失败,那么在 continue 语句之前使用 sleep() 函数可能会有所帮助。 “减慢”可能的无限循环将有助于降低您的CPU Usage

让脚本在成功之前无限运行并不是一个好主意,因为循环的前 100 次迭代中出现的错误不太可能得到解决,从而导致脚本“冻结”向上。通常情况下,最好重新评估您希望在出现错误时多次运行的代码,并对其进行改进以正确处理出现的任何错误。

【讨论】:

  • 这只是暂时的,所以我会一直使用它,直到找到解决方案。我已经对其进行了一些编辑以供我使用。谢谢
  • 很好的例子(这个线程中最好的),但我不认为set_error_handler() 调用是绝对必要的,除非你特别想捕捉每个 PHP 通知、警告和语法错误 in除了 通常的例外。常规的 try/catch 仍然会捕获 PHP 内部函数中抛出的异常,以及您自己抛出的异常。
【解决方案2】:

简单地说:

function doSomething($params, $try = 1){
    try{
        //do something
        return true;
    }
    catch(Exception $e){
        if($try <5){
             sleep(10);
             //optionnaly log or send notice mail with $e and $try
             doSomething($params, $try++);
        }
        else{ 
             return false;
        }
    }
}

【讨论】:

    【解决方案3】:

    这是一个简单的算法:

        do{
            try {
                $tryAgain = false;
                /* Do everything that throws error here */
    
            }
            catch(Exception $e) {
                $tryAgain = true;
                /* Do error reporting/archiving/logs here */
    
            }
        } while($tryAgain);
    

    【讨论】:

      【解决方案4】:

      我不完全理解您为什么要这样做,因为您很有可能会创建一个无限循环。但是,如果代码在小睡后很可能会成功,无论出于何种原因,下面是一个解决方案

      while(true){
          // execute the code you are attempting
          if(some condition to signal success){
              break; // exit the loop
          }
      
          sleep(2); // 2 seconds
      }
      

      【讨论】:

      • 在处理外部服务时,在睡眠后重试(但通常有最大尝试次数以避免无限循环)是很常见的,可能会停机
      • 这只是有条件的重试。我认为主要要求是如何使用 try catch 重试?只检查某个条件肯定远不能阻止所有异常的 try catch。
      【解决方案5】:

      这个库看起来很酷,它有不同的退避策略可供您选择,并且让您不必每次都实现重试逻辑。

      https://github.com/stechstudio/backoff

      示例代码:

      $result = backoff(function() {
          return doSomeWorkThatMightFail();
      });
      

      【讨论】:

        【解决方案6】:

        我推荐这个库:PHP Backoff

        它允许他们执行代码,如果由于某种原因发生并失败,它会自动作为任务重新运行。它有多种配置,因此您可以根据自己的需要进行调整。

        安装:

        composer require stechstudio/backoff
        

        快速入门

        $result = backoff(function() {
            // Here is the function they want to execute.
            return doSomeWorkThatMightFail();
        });
        

        所有文档都在这里: https://github.com/stechstudio/backoff

        【讨论】:

          【解决方案7】:

          为了能够捕获异常,您必须先抛出一个异常。 像这样的东西。

          <?php
          function inverse($x) {
              if (!$x) {
                  throw new Exception('Division by zero.');
              }
              return 1/$x;
          }
          
          try {
              echo inverse(5) . "\n";
              echo inverse(0) . "\n";
          } catch (Exception $e) {
              echo 'Caught exception: ',  $e->getMessage(), "\n";
          }
          
          // Continue execution
          echo "Hello World\n";
          ?>
          

          有某些内置异常:http://php.net/manual/en/spl.exceptions.php

          【讨论】:

            猜你喜欢
            • 2018-01-10
            • 2014-07-16
            • 2011-03-21
            • 1970-01-01
            • 2017-09-12
            • 2014-05-11
            • 2014-01-24
            • 2011-12-05
            • 1970-01-01
            相关资源
            最近更新 更多