Java/Groovy中带重试的反应式事件处理

Java/Groovy中带重试的反应式事件处理,java,events,actor,reactive-programming,Java,Events,Actor,Reactive Programming,我想实现一个微服务,它在收到请求(通过消息队列)后,将尝试通过对外部服务的REST/SOAP调用来执行它。成功时应通过MQ发回回复,但失败时应重新安排请求,以便稍后执行(使用一些自定义算法,如10秒、1分钟、10分钟、超时-放弃)。在指定的时间之后,失败消息应发送回请求者 它应该在Java8和/或Groovy上运行。事件持久性不是必需的 首先,我想到了Executor和Runnable/Future以及ScheduledExecutorService.scheduleWithFixedDelay

我想实现一个微服务,它在收到请求(通过消息队列)后,将尝试通过对外部服务的REST/SOAP调用来执行它。成功时应通过MQ发回回复,但失败时应重新安排请求,以便稍后执行(使用一些自定义算法,如10秒、1分钟、10分钟、超时-放弃)。在指定的时间之后,失败消息应发送回请求者

它应该在
Java8
和/或
Groovy
上运行。事件持久性不是必需的

首先,我想到了
Executor
Runnable/Future
以及
ScheduledExecutorService.scheduleWithFixedDelay
,但对我来说,它的级别要低得多。第二个想法是演员使用Akka和(重新安排时间),但我相信还有其他方法

问题。您将使用什么技术来处理反应性事件,并能够在发生故障时重新安排它们?

“事件”是一个非常模糊的术语,但我遇到的大多数定义都是关于控制反转的技术之一。这段代码的特点是,您不关心何时以及由谁调用某段代码,而是在什么条件下调用。这意味着您将反转(或者更准确地说是“失去”)对执行流的控制

现在,您需要事件驱动的处理(因此您不希望处理时间和由谁处理),但您希望指定失败时的定时(严格连接到时间)行为。这对我来说有点自相矛盾


我想说,如果您使用回调进行反应式编程,您会做得更好,如果失败,您只需启动新线程,该线程将休眠10秒,然后重新运行回调。

最后,我找到了专门为此编写的库。它允许以非常可定制的方式异步重试执行。在内部,它利用ScheduledExecutorService和(或者在必须使用Java 7时使用Guava)

示例用法(来自项目网页):

ScheduledExecutorService scheduler=Executors.newSingleThreadScheduledExecutor();
RetryExecutor executor=新的AsyncRetryExecutor(调度程序)。
retryOn(SocketException.class)。
指数衰减(500,2)//每次重试后500毫秒乘以2次
具有最大延迟(10_000)//10秒
使用UNIFORMJITTER()//随机添加+/-100 ms
最大重试次数(20次);
final CompletableFuture=executor.getWithRetry(()->
新套接字(“本地主机”,8080)
);
未来。然后接受(套接字->
System.out.println(“已连接!”+套接字)
);
您也可以签出。无外部依赖项,支持Java 1.6+,死简单API,支持事件侦听器,异步API集成,等等:

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(SocketException.class);
  .withMaxRetries(20);

Socket socket = Failsafe.with(retryPolicy).get(() -> new Socket("localhost", 8080));

谢谢你的回复。TIMED只需要延迟下一次尝试(使用一些算法),我看不到任何其他方法可以做到这一点。尽管如此,重新调度的事件稍后会被视为任何其他执行(在什么条件下-出现了一个事件并需要处理)。顺便说一句,
线程将睡眠10秒并重新运行回调
-我假设这是一个速记,您不想在睡眠(10000)的情况下暂停线程10秒。谢谢@Jonathan。我最近在其他一些项目中使用了故障保护,效果很好。
RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(SocketException.class);
  .withMaxRetries(20);

Socket socket = Failsafe.with(retryPolicy).get(() -> new Socket("localhost", 8080));