操作失败时如何重试



我有一个具有以下合同的单例客户端

public interface MQPublisher {
void publish(String message) throws ClientConnectionException, ClientErrorException;
void start() throws ClientException;
void stop();
}

使用此发布者的类如下:

public class MessagePublisher {
@Autowired
private MQPublisher publisher;
private AtomicBoolean isPublisherRunning;
public void startPublisher() {
if (!isPublisherRunning.get()) {
publisher.start();
isPublisherRunning.compareAndSet(false, true);
}
}
@Retry(RETRY_MSG_UPLOAD)
public void sendMessage(String msg) {
try {
startPublisher();
publisher.publish(msg); // when multiple requests fail with the same exception, what will happen??
} catch (Exception e) {
log.error("Exception while publishing message : {}", msg, e);
publisher.stop();
isPublisherRunning.compareAndSet(true, false);
throw e;
}
}

我们正在使用resilience4j重试功能来重试sendMessage方法。这在单个请求的情况下工作得很好。考虑这样一种情况:多个请求被并行处理,所有请求都失败并出现异常。在这种情况下,这些请求将被重试,并且有可能一个线程将启动发布者,而另一个线程将停止它,并且它将再次抛出异常。如何以更简洁的方式处理这种情况?

不清楚为什么要在失败的情况下停止整个出版商。尽管如此,如果确实有这样的原因,我会将stop方法更改为使用原子计时器,该计时器将在每次消息发送时重新启动,并在消息发送后至少5秒(或成功发送消息所需的时间)后停止发布者。像这样:

@Slf4j
public class MessagePublisher {
private static final int RETRY_MSG_UPLOAD = 10;
@Autowired
private MQPublisher publisher;
private AtomicBoolean isPublisherRunning;
private AtomicLong publishStart;

public void startPublisher() {
if (!isPublisherRunning.get()) {
publisher.start();
isPublisherRunning.compareAndSet(false, true);
}
}
@Retryable(maxAttempts = RETRY_MSG_UPLOAD)
public void sendMessage(String msg) throws InterruptedException {
try {
startPublisher();
publishStart.set(System.nanoTime());
publisher.publish(msg); // when multiple requests fail with the same exception, what will happen??
} catch (Exception e) {
log.error("Exception while publishing message : {}", msg, e);
while (System.nanoTime() < publishStart.get() + 5000000000L) {
Thread.sleep(1000);
}
publisher.stop();
isPublisherRunning.compareAndSet(true, false);
throw e;
}
}
}

我认为有必要指出(就像你刚才说的)这是一个糟糕的设计,这样的计算应该由发布者实现者来完成,而不是由调用者来完成。

最新更新