繁体   English   中英

操作失败时如何重试操作

[英]How to retry an operation when it fails

我有以下合同的单身客户

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;
        }
    }
}

我认为重要的是(正如您刚才所做的那样)这是一个糟糕的设计,并且此类计算应该由发布者实现者而不是调用者来完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM