如果方法 A 在 Spring 引导中执行时间超过 X 秒,则回退到方法 B
Fallback to methodB if methodA execution takes more than X seconds in Spring Boot
我有一个 Spring 引导应用程序,我有一个 @Service
非常重,可以执行 0.5 到 5 秒。我希望它在执行时间超过 1 秒时停止执行并回退到回退方法。
/// entry point
public String longLatingMethod(Payload payload) {
/// long lasting operation that can take up to 5 seconds
return value;
}
// I want this method to be executed if `longLatingMethod` takes more than 1 second to execute.
public String fallbackMethod(Payload payload) {
return defaultValue;
}
现在我已经用 Hystrix
框架实现了它,但是由于 Hystrix
已经停产,我想知道还有哪些其他库可以用于此目的?
您必须 运行 在某种线程中执行您的任务,以便您可以继续执行并等待(一定的毫秒数)该进程完成。如果它没有在分配的时间内完成,则中断主要任务和 运行 备份任务。请注意,您的主要任务将必须检查它是否被中断,阻塞操作通常已经检查过并在中断时停止阻塞。
public static void main(String[] args){
Thread t = new Thread(() -> {
// your long running task here...
System.out.println("running primary task");
// simulate it taking too long...
// will need to check if it is interrupted if you want to terminate it sooner
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
System.out.println("primary task interrupted");
}
});
t.start();
// one second threshold
try { t.join(1000); } catch (Exception e) {}
if (t.isAlive()) {
// if the primary task is still running interrupt it
t.interrupt();
// run your backup task
System.out.println("running backup task");
// ...
System.out.println("backup task completed");
} else {
System.out.println("primary task completed");
}
}
输出:
running primary task
running backup task
primary task interrupted
backup task completed
不确定这是否是最佳解决方案,但请检查此问题:Java: set timeout on a certain block of code?
并在超时捕获块中添加回退
final Runnable stuffToDo = new Thread() {
@Override
public void run() {
/* Do stuff here. */
}
};
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future future = executor.submit(stuffToDo);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
future.get(1, TimeUnit.Seconds);
}
catch (InterruptedException ie) {
/* Handle the interruption. Or ignore it. */
}
catch (ExecutionException ee) {
/* Handle the error. Or ignore it. */
}
catch (TimeoutException te) {
return fallbackMethod(payload);
}
您可以使用 Future 特别是方法 V get(long timeout, TimeUnit unit)
:
Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.
并按如下方式使用:
Callable<String> task = () -> {
...
};
public Future<String> myMethod() {
return Executors.submit(task);
}
public String fallBackMethod() {
...
}
String value = null;
try {
Future<String> result = myMethod.get(1, TimeUnit.SECONDS);
value = result.get();
} catch (TimeoutException e) {
value = fallBackMethod();
}
请注意,如果您不修改该方法并定期检查它是否已完成,则您无法在它开始后停止该方法的执行,但通常您不能这样做,例如,如果您询问对于数据库查询,查询需要 5 秒,您无法在 5 秒之前检查。
我有一个 Spring 引导应用程序,我有一个 @Service
非常重,可以执行 0.5 到 5 秒。我希望它在执行时间超过 1 秒时停止执行并回退到回退方法。
/// entry point
public String longLatingMethod(Payload payload) {
/// long lasting operation that can take up to 5 seconds
return value;
}
// I want this method to be executed if `longLatingMethod` takes more than 1 second to execute.
public String fallbackMethod(Payload payload) {
return defaultValue;
}
现在我已经用 Hystrix
框架实现了它,但是由于 Hystrix
已经停产,我想知道还有哪些其他库可以用于此目的?
您必须 运行 在某种线程中执行您的任务,以便您可以继续执行并等待(一定的毫秒数)该进程完成。如果它没有在分配的时间内完成,则中断主要任务和 运行 备份任务。请注意,您的主要任务将必须检查它是否被中断,阻塞操作通常已经检查过并在中断时停止阻塞。
public static void main(String[] args){
Thread t = new Thread(() -> {
// your long running task here...
System.out.println("running primary task");
// simulate it taking too long...
// will need to check if it is interrupted if you want to terminate it sooner
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
System.out.println("primary task interrupted");
}
});
t.start();
// one second threshold
try { t.join(1000); } catch (Exception e) {}
if (t.isAlive()) {
// if the primary task is still running interrupt it
t.interrupt();
// run your backup task
System.out.println("running backup task");
// ...
System.out.println("backup task completed");
} else {
System.out.println("primary task completed");
}
}
输出:
running primary task
running backup task
primary task interrupted
backup task completed
不确定这是否是最佳解决方案,但请检查此问题:Java: set timeout on a certain block of code?
并在超时捕获块中添加回退
final Runnable stuffToDo = new Thread() {
@Override
public void run() {
/* Do stuff here. */
}
};
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future future = executor.submit(stuffToDo);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
future.get(1, TimeUnit.Seconds);
}
catch (InterruptedException ie) {
/* Handle the interruption. Or ignore it. */
}
catch (ExecutionException ee) {
/* Handle the error. Or ignore it. */
}
catch (TimeoutException te) {
return fallbackMethod(payload);
}
您可以使用 Future 特别是方法 V get(long timeout, TimeUnit unit)
:
Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.
并按如下方式使用:
Callable<String> task = () -> {
...
};
public Future<String> myMethod() {
return Executors.submit(task);
}
public String fallBackMethod() {
...
}
String value = null;
try {
Future<String> result = myMethod.get(1, TimeUnit.SECONDS);
value = result.get();
} catch (TimeoutException e) {
value = fallBackMethod();
}
请注意,如果您不修改该方法并定期检查它是否已完成,则您无法在它开始后停止该方法的执行,但通常您不能这样做,例如,如果您询问对于数据库查询,查询需要 5 秒,您无法在 5 秒之前检查。