延迟例外
时间: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的异常处理系统,则使用异常可能不合适。
我们可以按照通常的方式跟踪错误情况:保留状态变量,根据需要使用成功/失败信息对其进行更新,并在状态变化时做出适当的响应。

