在回答真正的问题之前有一些背景知识:
我正在开发一个由几个不同模块组成的后端应用程序。目前,每个模块都是一个命令行java应用程序,它按需运行" (稍后详细说明)。
每个模块都是一个步骤,是一个更大的过程的一部分,您可以将其视为数据流;第一步从外部源收集数据文件,并将它们推送/加载到一些SQL数据库表中;然后根据不同的条件和事件(时间,数据库中存在数据,通过Web服务/ Web界面完成的消息和详细说明),从(1个或多个)DB表中获取数据,处理它们,并将它们写在不同的表格上。步骤在三个不同的服务器上运行,并从三个不同的DB读取数据,但只能在一个DB中写入。目的是汇总数据,计算指标和统计数据。
目前,每个模块都会定期执行(从第一个模块的几分钟/小时到链中最后一个模块的几天,这需要聚合更多数据,因此需要等待更长的时间"使用cronjob,可以使用它们。 运行一个模块(当前是一个java控制台应用程序),它会检查数据库中给定日期时间窗口中新的未处理信息,并完成其工作。
问题:它有效,但是......我需要扩展和维护它,这种方法开始显示其局限性。
为解决第二个问题,我将介绍" partial"或" incremental"计算:只要我有一组相关信息,我就会处理它。然后,当一些其他链接信息到达时,我计算差异并相应地更新数据,但我还需要通知其他(从属)模块。
- 1)哪种方法最好?
- 2)相关:这是"通知"的最佳方式。其他模块(在我的例子中是java可执行文件)相关数据是否可用?
我可以看到三种方式:
秒>编辑:我确信基于队列的方法是可行的方法,我添加了" table + polling"完整性的选择,但现在我明白这只是一种分心(显然,每个人都会回答"是的,使用队列,轮询是邪恶的" - 这是正确的!)。那么让我重新解释一下这个问题: 在像Redis这样的pub / sub的键值存储上使用MQ有什么优点/缺点?
编辑:特别是,在可能的情况下,它意味着:在某些MQ和/或键值存储中是否有机制,允许我使用" time"?喜欢"在1天内发送"?坚持不懈,几乎一次"交货保证,显然
编辑:这是我最关心的一点:我想"排队"本身激活"模块"基于队列中的消息,类似于MSMQ激活。 这是个好主意吗? Java世界中有什么东西可以实现它,我应该自己实现它(通过MQ还是通过Redis),还是应该将每个模块作为守护进程运行?(即使某些计算通常以突发形式发生,两个一小时的处理,然后是两天的闲置?)
注意:我不能使用重型容器/ EJB(No Glassfish或类似的)
编辑:骆驼对我来说似乎有点太重了。在资源和开发复杂性方面,我在这里寻找非常轻松的东西
答案 0 :(得分:1)
队列任务描述听起来像基于" enterprise integration patterns"的系统。像Apache Camel那样。
delayed message可由常数
表示from("seda:b").delay(1000).to("mock:result");
或变量,例如消息头值
from("seda:a").delay().header("MyDelay").to("mock:result");
答案 1 :(得分:1)
1>我建议使用消息队列,根据您的要求选择队列,但对于大多数情况下任何人都会这样做,我建议您选择基于协议JMS(活动mq)或AMQP(rabbit mq)的队列并编写一个简单的包装器它或使用spring提供的那些 - > spring-jms或spring-amqp
2 - ;您可以编写队列使用者,以便他们通知您的系统新消息到达,例如在Rabbit中您可以实现MessageListener接口
public class MyListener implements MessageListener {
@Override
public void onMessage(Message message) {
/* Handle the message */
}
}
3>如果您使用< 2>中的异步消费者你可以摆脱所有的民意调查和cron工作
4>取决于您的要求 - >如果您有数百万个事件/消息通过您的队列,那么在集中式服务器上运行队列中间件是有意义的。
5个如果资源消耗不是问题,那么让您的消费者/订阅者一直在运行是最简单的方法。如果这些消费者是分发的,那么你可以使用像zookeeper
这样的服务来编排它们6个可伸缩性 - >大多数排队系统都可以轻松分发消息,因此只要您的消费者是无状态的,那么只需添加新的消费者和一些配置即可实现扩展。
答案 2 :(得分:0)
在实施之后,我觉得回答我自己的问题可能对将来会访问StackOverflow的人有好处。
最后,我和Redis一起去了。 真的快速,可扩展。我非常喜欢它的灵活性:它比消息队列更灵活。我是否断言Redis在MQ上比那里的各种MQ更好?嗯,在我的具体情况下,我相信。关键是:如果没有提供开箱即用的东西,你可以构建它(通常,使用MULTI - 但你甚至可以使用LUA进行更高级的自定义!)。
例如,我跟着this good answer实现了一个“持久的”,可恢复的pub / sub(即允许客户端死掉并重新连接而不会丢失消息的pub / sub)。
这对我的可扩展性和我的“可靠性”要求都有帮助:我决定保持管道中的每个部分独立(现在是一个守护进程),但是添加一个监视器来检查Redis上的列表/队列;如果没有消耗(或消耗得太慢),监视器会产生一个新的消费者。我也想要真正“有弹性”,并且在没有工作要做的时候为消费者增添自杀能力。
另一个例子:执行预定的活动。我现在关注this approach,这似乎很受欢迎。但我很想尝试keyspace notifications,看看过期密钥和通知的组合是否是一种更好的方法。
最后,作为一个访问Redis的库,我选择了Jedis:它很受欢迎,支持并提供了一个很好的界面来实现pub / sub作为监听器。它不是Scala的最佳方法(惯用语),但效果很好。