我正在尝试设置一个每x分钟/秒/毫秒/无论如何运行的作业,并轮询Amazon SQS队列以处理要处理的消息。我的问题是最好的办法是什么。我应该创建一个带有x个线程的ScheduledThreadPoolExecutor并使用scheduleAtFixedRate方法调度单个任务,并且经常运行它(例如10毫秒),以便在需要时使用多个线程,或者,正如我向同事提议的那样,创建一个ScheduledThreadPoolExecutor具有x个线程,然后以稍微偏移的间隔创建多个计划任务,但运行频率较低。这对我来说听起来像是如何使用STPE。
通常我会使用Spring / Quartz来处理这种类型的事情,但这一点已经过时了。
那你有什么想法?
答案 0 :(得分:1)
我建议您在SQS上使用long polling,这会使ReceiveMessage
来电更像take
上BlockingQueue
的来电(这意味着您不会需要使用计划任务从队列中轮询 - 您只需要一个在无限循环中轮询的单个线程,如果连接超时则重试)
答案 1 :(得分:0)
这取决于任务的频率。如果您只需要及时轮询并且间隔不是很小,那么ScheduledThreadPoolExecutor
scheduleAtFixedRate
是一个不错的选择。
否则我会建议使用netty的HashedWheelTimer
。在繁重的任务下,它可以提供最佳性能。 Akka和play使用它进行安排。这是因为STPE
对于每个添加的任务都需要O(log(n))
,其中HWT
需要O(1)
。
如果你必须使用STPE
,我会推荐一个任务,否则会导致资源过剩。
答案 2 :(得分:0)
长轮询就像一个阻塞队列,只有最大值20 seconds
才会返回呼叫。如果这是轮询周期之间所需的最大延迟,则长轮询就足够了。除此之外,您还需要一个scheduledExector。
线程数实际上取决于您处理收到的消息的速度。如果您可以非常快速地处理消息,则只需要一个线程。我的设置如下
SingleThreadScheduledExecutor
scheduleWithFixedDelay
在上一次完成后执行5分钟对于我的场景,单线程就足够了。如果积压增加(例如,每个可能涉及等待的消息需要网络操作),您可能希望使用多个线程。如果一个处理节点变得资源受限,则可以始终启动另一个实例(可能是EC2)以添加更多容量。