延迟例外

时间:2020-03-06 14:37:39  来源:igfitidea点击:

我有一种定期(例如每10秒一次)尝试连接到服务器并从中读取一些数据的方法。该服务器可能并非一直都可用。如果服务器不可用,则该方法将引发异常。

除非服务器至少一分钟不可用,否则实现不引发异常的包装方法的最佳方法是什么?

解决方案

跟踪上一次成功访问服务器的时间。如果服务器抛出异常,请捕获该异常并将其与我们上次访问服务器的时间进行比较。如果该时间超过一分钟,请重新引发异常。

我们将必须记录最初尝试连接服务器的时间,然后捕获异常。如果捕获到异常的时间大于原始时间+ 1分钟,请重新抛出异常。如果不是,请重试。

理想情况下,我们可以在对服务器的呼叫上设置超时。失败的话,在catch块中执行thread.sleep(600),然后重试一次,如果第二个不返回,则失败。

用伪代码。

//Create Timer
//Start Timer
bool connected = false;

while (!connected)

    try {
        //Connect To DB

        connected = true;
    }
    catch (Exception ex) {
       if (more than 1 minute has passed)
          throw new Exception(ex);
    }

}

我们可以有一个重试计数,如果达到了所需的计数(在情况下为6),则抛出异常

int count = 0;

CheckServer(count);

public void CheckServer(count) {
try
{
  // connect to server
}
catch(Exception e)
{
 if(count < MAX_ATTEMPTS) {
    // wait 10 seconds
    CheckServer(count++)
  }
  else {
    throw e;
  }
}
}

我们可以为服务器连接是否成功设置一个布尔变量,然后在异常处理程序中检查它,如下所示:

class ServerTester : public Object
{
  private bool failing;
  private ServerConnection serverConnection;
  private Time firstFailure;

  public ServerTester(): failing(false)
  {
  }

  public void TestServer() throws ServerException
  {
    try
    {
       serverConnection.Connect();
       failing = false;
    }
    catch (ServerException e)
    {
      if (failing)
      {
        if (Time::GetTime() - firstFailure > 60)
        {
          failing = false;
          throw e;
        }
      }
      else
      {
        firstFailure = Time::GetTime();
        failing = true;
      }
    }
  }
}

我不知道实际的时间API是多少,因为我上次使用Java已经有一段时间了。这将满足要求,但似乎不正确。轮询异常会使我有点倒退,但是由于我们正在处理服务器,因此我想不出其他办法。

请记住,异常处理只是通常的"返回"系统的一种非常专业的用法。 (有关更多技术细节,请阅读" monads"。)如果我们要传达的特殊情况不自然地适合Java的异常处理系统,则使用异常可能不合适。

我们可以按照通常的方式跟踪错误情况:保留状态变量,根据需要使用成功/失败信息对其进行更新,并在状态变化时做出适当的响应。