我正在设计一个将在 OSGi 容器(目前是 Equinox)中运行的应用程序。它将通过 RabbitMQ 接收消息并在内部处理它们。该应用程序将作为服务器持续运行。我目前的计划是使用 QueueingConsumer
并在它们自己的线程中运行,让 RabbitMQ 监听器包配置其队列并在其上放置监听器。监听器将调用一个或多个处理服务来处理消息。处理器需要进行 JDBC 调用以访问数据库。我希望能够控制调用处理器的顺序。如果能够在以后灵活地添加更多服务而无需重新编码 RabbitMQ 监听器,那就太好了。
我面临的问题是消息可能是突发的,也可能是缓慢的。我希望能够使用 PreparedStatement
来加速数据库访问,但我也不希望在没有任何事情发生的情况下长期保持连接打开。我考虑过直接子类化 DefaultConsumer
并让它在 RabbitMQ Connection
中的线程上运行,但后来我失去了知道什么时候没有发生的能力。我最初的想法是让消息处理器作为 OSGi 服务完全独立,并且在每次调用时都从池中获取一个数据库连接,但这失去了准备好的语句的优势。我正在使用 Tomcat JDBC 池,它似乎没有准备好的语句缓存。此外,我不确定为每次调用创建准备好的语句会花费多少,但这似乎很浪费。
到目前为止,我想到的最好的想法是让我的监听器在双循环中处理。外循环等待消息,然后调用内循环建立数据库连接和准备好的语句并运行,直到在指定的超时时间内没有更多消息传入,然后关闭其连接并返回到外循环。我得到这个来处理一点点,但是如果我有多个处理器可能有不同的准备语句,我很难想象如何管理它。
也许我必须放弃多个服务的想法,并将处理过程硬编码到我的监听器中。
有什么建议吗?谢谢!
最佳答案
为什么不将服务用作监听器并向它们传递它们应该使用的 JDBC 连接?然后,一段代码将队列分派(dispatch)给您的服务。这个中央调度程序可以简单地维护准备好的 JDBC 连接池。如果不想在 API 中看到 JDBC 连接,请使用 Coordinator 服务来保持连接。然后,“感知”服务可以获得优化的 JDBC 连接。
或者,将数据源注册为您的监听器服务的服务并实现您自己的池策略。由于您知道 OSGi 服务调用中的调用者,因此您可以进行各种优化,例如从包的 jar 中读取准备好的语句并相应地缓存它们。
我不会放弃这里的服务,你得到的解耦效果很好,我从经验中知道。由于在此模型中,服务监听器不依赖于 RabbitMQ,因此您可以轻松地测试它们和/或切换到另一种队列技术。
话又说回来,在这些情况下,最好的办法是采用您能想到的最简单的解决方案。如果您遇到性能问题,请测量并修复瓶颈。过早的解决方案浪费了大量的精力......我可以告诉你很多我浪费时间的愚蠢的过早优化。
关于java - 在使用 PreparedStatement 的同时使用 RabbitMQ 设计 Java OSGi 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12681833/