1

我想设计一个可以处理大量消息的简单应用程序(没有 j2ee 和 jms)(比如在交易系统中)

我创建了一个服务,可以接收消息并将它们放入队列中,以便系统在过载时不会卡住。

然后我创建了一个包装队列的服务(QueueService),并有一个从队列中弹出消息的pop方法,如果没有消息返回null,则将此方法标记为“已同步”以进行下一步。

我创建了一个知道如何处理消息的类(MessageHandler)和另一个可以“侦听”新线程中的消息的类(MessageListener)。该线程有一个“while(true)”,并且一直试图弹出一条消息。

如果返回了一条消息,线程调用 MessageHandler 类,完成后,他会请求另一条消息。

现在,我已将应用程序配置为打开 10 个 MessageListener 以允许多消息处理。

我现在有 10 个线程一直处于循环状态。

这样的设计好吗??

任何人都可以参考一些书籍或网站如何处理这种情况吗?

谢谢,罗尼

4

7 回答 7

5

从您的描述看来,您走在正确的道路上,但有一点例外。您在从队列中检索消息时实现了忙碌等待。

popMessage()更好的方法是在同步方法中阻止线程,在wait()无法弹出更多消息时对队列资源执行操作。当向队列添加(a)条消息时,等待的线程通过 a 被唤醒notifyAll(),一个或多个线程将收到一条消息,其余线程重新进入wait()状态。

这样CPU资源的分配会更顺畅。

于 2009-11-23T15:15:25.643 回答
3

我知道像 Websphere 和 Sonic 这样的排队服务提供商需要花钱,但总是有 JBoss Messaging、FUSE with ApacheMQ 等。不要尝试制作比 JMS 更好的 JMS。大多数 JMS 提供程序都具有持久性功能,可在队列或应用服务器死机时提供容错功能。不要重新发明轮子。

于 2009-11-23T14:58:49.747 回答
2

在字里行间稍微读一下,这听起来像是您没有使用 MQ 之类的 JMS 提供程序。您的解决方案在大多数情况下都可以,但是我会质疑您不使用 JMS 的原因。

你提到了一些关于交易的事情,我可以确认很多交易系统都使用带有和不带有 j2ee 的 JMS。如果您真的想要高性能、可靠性和头脑清醒,请不要通过编写自己的排队系统来重新发明轮子,请查看一些 JMS 提供程序及其客户端 API。

卡尔

于 2009-11-23T14:53:12.723 回答
2

事件循环

改用事件循环/消息泵怎么样?实际上,我是通过观看 Ryan 提供的出色的node.js视频演示来学习这种技术的,我认为如果还没有观看的话,我认为你应该真正观看。

您最多将 10 条消息从Thread a, 推送到Thread b(如果已满则阻塞)。线程 a 有一个无界的[LinkedBlockingQueue][3](). 线程 b 的边界[ArrayBlocking][4]大小为 10 ( new ArrayBlockingQueue(10))。两者thread a都有thread b一个无休止的“while循环”。Thread b将处理来自ArrayBlockingQueue. 这样,您将只有 2 个无休止的“while 循环”。作为旁注,由于以下句子,在阅读规范时使用 2 arrayBlockingQueues 可能会更好:

链接队列通常比基于数组的队列具有更高的吞吐量,但在大多数并发应用程序中性能更不可预测。

当然,数组支持的队列有一个缺点,它会使用更多内存,因为您必须事先设置大小(太小不好,因为它会在满时阻塞,如果内存不足,太大也可能是一个问题)使用.

接受的解决方案:

在我看来,您应该更喜欢我的解决方案而不是公认的解决方案。原因是,如果一切可能,您应该只使用该java.util.concurrent包。编写正确的线程代码很难。当你犯错时,你最终会陷入僵局、饥饿等。

雷迪斯:

像已经提到的其他人一样,您应该为此使用 JMS。我的建议与此类似,但我认为使用/安装更简单。首先,我假设您的服务器正在运行 Linux。我建议你安装 Redis。Redis 真的很棒/很快,你也应该把它用作你的数据存储。它具有您可以使用的阻止列表操作。Redis 会将你的结果存储到磁盘上,但是以一种非常有效的方式。


祝你好运!

于 2010-05-02T23:57:26.753 回答
1

虽然现在已经过时了,但适用于金融市场的实用 .NET展示了在开发金融交易系统时应该考虑的一些通用概念。虽然它面向 .Net,但您应该能够将一般概念转换为 Java。

于 2009-11-23T14:53:10.337 回答
1

监听消息和处理消息的分离对我来说似乎是明智的。拥有可扩展数量的处理线程也很好,您可以在发现平台上的并行处理数量时调整数量。

我不太满意的一点是线程轮询消息到达的方式 - 在这里你正在做繁忙的工作,如果你添加睡眠来减少它,那么你不会立即对消息到达做出反应。JMS API 和 MDB 采用更多的事件驱动方法。我将看看它是如何在开源 JMS 中实现的,以便您可以看到替代方案。[我也赞同为自己重新发明 JMS 可能是一个坏主意的观点。]要记住的是,随着系统变得越来越复杂,您会添加更多队列并且处理更多繁忙的工作会产生更大的影响。

我担心的另一个问题是你会遇到使用单台机器的限制,首先你可以允许更大的可伸缩性,允许听众在多台机器上。其次,您有单点故障。显然,解决这类问题是消息传递供应商赚钱的地方。这是购买而不是构建往往是复杂中间件的胜利的另一个原因。

于 2009-11-23T14:59:02.897 回答
1

您需要非常轻便、超快速、可扩展的排队系统。试试Hazelcast分布式队列!

它是一个分布式实现java.util.concurrent.BlockingQueue。查看文档以了解详细信息。

Hazelcast 实际上不仅仅是一个分布式队列。它是 Java 的队列、主题、映射、多映射、锁、执行器服务的事务性分布式实现。

它是在 Apache 许可下发布的。

于 2010-05-02T22:52:43.950 回答