我们目前正在编写一个IT已经为其购买硬件的应用程序.他们的方法是购买我们将部署的大型硬件.为了增加更多处理,他们计划添加具有相同软件的其他服务器.为了适应这种设计,我们使用Terracotta来提供运行多个JVM的能力,就像它是一个大型JVM一样.无论这是否是一种明智的方式(我仍然不相信),这就是我正在处理的情况.
无论如何,我们有一部分应用程序使用标准的生产者/消费者类型队列.使用Terracotta,我们可以创建一个可与多个JVM一起使用的单个队列.这很漂亮,效果很好.
但现在,我们正在寻找额外的机会来运行异步流程.为了使我们的所有排队逻辑更加一致,我们正在考虑使用JMS来抽象出通用逻辑.由于我们不打算将JMS用作远程队列(至少在可预见的未来),我想知道JMS是否只是增加了不必要的复杂性.
有什么建议或想法?我们应该继续将队列构建为并发结构,还是将它们视为单独的可能远程对象?
根据javadoc,如果我在javax.jms.MessageConsumer上调用receive(),它将无限期地阻塞,直到产生消息或消息使用者关闭为止.
我有一个调用receive()的线程.作为线程关闭的一部分,我调用close(),但是消费者仍然在receive()中阻塞,因此线程不会关闭.我的代码的要点是:
public String receiveMessage() {
...
...
System.out.println("About to receive")
TextMessage message = (TextMessage) consumer.receive();
System.out.println("No longer receiving")
...
...
}
public void stop() {
try {
if (consumer != null) {
consumer.close();
}
} catch (JMSException ex) {
throw new IllegalStateException(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
在调试器中,我可以看到正在调用close(),但接收仍然阻塞.如果我使用带有超时的receive()方法,它将一直阻塞,直到超时到期.
一切看起来都对我来说,希望有人可以告诉我我做错了什么.
我是EJB的新手.背景:我有一个使用WebSphere缺省消息传递提供程序的MDB接收具有java.sql.DataSource的MapMessages来做一些工作,使用preparedstatement,jdbc事务等.我在ibm-ejb-bnd.xml中设置了MDB, ejb-jar.xml使用带有激活规范和目标名称的JCA适配器.我在ejb-jar和ibm-ejb-jar-bind中添加了一个java.sql.DataSource.我还在MessageListener中添加了带有@Resource注释的DataSource.
2个场景我无法理解(第一个场景已修复,请参阅更新)......
容器管理的MDB: DataSource驱动程序不兼容XA,因此我在WebSphere中启用了"Last Participant Support".但是,当MDB事务类型设置为Container时,我在提交时收到错误:
[11/28/11 10:56:10:988 MST] 0000002e RegisteredRes E WTRN0063E: An illegal attempt to commit a one phase capable resource with existing two phase capable resources has occurred.
Run Code Online (Sandbox Code Playgroud)
也许这是因为在DataSource提交之后,返回MessageListener,它提交它作为最后一个参与者?我相信WAS 7中的默认消息传递提供程序是XA兼容的,尽管我没有看到任何明确说明的文档.
在第一个错误之后,消息会立即重新运行4次(即使根据WebSphere中的ActivationSpec应该有30秒的延迟).每次抛出相同的错误.根据MessageListener它完成没有错误,所以这个错误是美妙的隐形容器托管事务的一部分.我不认为我需要XA全局事务,因为除了JMS之外只有一个DataSource,我以编程方式处理事务回滚.此外,JMS消息,MDB是异步的,AUTO-ACKNOWLEDGE.收到消息后,可以确认消息.
如果我引入了一个应用程序错误,所以有一个Exception,我立即看到这个错误5次(没有延迟):
[11/28/11 10:16:18:857 MST] 0000002b LocalExceptio E CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "onMessage" on bean...
Run Code Online (Sandbox Code Playgroud)
所以我切换到................
Bean托管MDB: 提交正在运行而没有XA错误,只发生一次.但是,错误处理仍然不像我期望或想要的那样!在MessageListener类中,捕获的异常抛出EJB异常,我认为这应该导致MDB具有我想要的行为: 异常的原因对我来说无关紧要,当MDB抛出捕获的异常时,MDB不应该是根据WebSphereActivationSpec中的属性重试? 相反,消息将立即传递给MessageListener 5次,同时抛出与容器管理的MDB相同的错误:"EJB引发了意外(未声明的)异常......"
如果我抛出RuntimeException,则不会发生"未声明(未声明)的消息"消息,但消息仍然会立即重试4次,而不是等待重试延迟.
感谢阅读,非常感谢任何帮助或见解!
更新: 我最终通过将数据源切换到XA兼容来解决XA兼容性问题.在WAS管理控制台中:Resources-> JDBC Providers-> DB2 Universal JDBC Driver Provider->将实现类名更改为:com.ibm.db2.jcc.DB2XADataSource
但是当消息失败时我仍然遇到同样的问题.它会立即重试,而不是根据WAS中的ActivationSpec.
我正试图ActiveMQ 5.8.0在我的项目中使用.有两种不同的存储配置,KahaDB和LevelDB.根据问题,Kaha可以比Level更快或Level可以比Kaha更快.
它们之间真正的区别是什么?
我最近将服务器从ActiveMQ从5.8升级到最新(5.11.1).从那以后,我偶尔会注意到消息会在特定队列中累积而不会被取消.
我们的架构有一个生产者,一个消费者.我可以看到消费者仍然是连接的,但消息正在从生产者堆积起来.我的解决方案是通过Web控制台删除队列.之后,我立即看到消费者重新连接并再次开始处理消息.
如果它是相关的,在这种情况下,生产者在.NET上运行NMS,而消费者在Java 1.7上运行JMS.
嗨我从JBoss_6.1.0_final迁移到wildfly 10.
在JBoss for Queue名称中,格式如下
<queue name="TEST_QUEUE">
<entry name="/queue/TEST_QUEUE"/>
</queue>
Run Code Online (Sandbox Code Playgroud)
并在MDB注释中
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "queue/TEST_QUEUE")
Run Code Online (Sandbox Code Playgroud)
现在在野生蝇类如下.参考链接
<jms-queue name="TEST_QUEUE" entries="jms/queue/TEST_QUEUE java:jboss/exported/jms/queue/TEST_QUEUE"/>
Run Code Online (Sandbox Code Playgroud)
with activationproperty
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "jms/queue/TEST_QUEUE")
Run Code Online (Sandbox Code Playgroud)
在wildfly中,我尝试通过删除jms/from队列名称和注释,它在具有相同队列名称的wildfly中正常工作,如
<jms-queue name="TEST_QUEUE" entries="queue/TEST_QUEUE java:jboss/exported/queue/TEST_QUEUE"/>
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,是否JMS/有目的地添加了队列名称.
编写没有前缀的队列名称是一种好习惯 jms/
我试图寻找一个QueueConnectionFactory和Queue通过Geronimo的JNDI.在Queue获取返回正常,但QueueConnectionFactory查找始终返回null.它不会抛出一个NamingException,如果JNDI名称不正确,这就是我所期望的.
谁能看到我做错了什么?下面的测试代码输出:
true false
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JndiTest
{
private final static String QUEUE_NAME = "jca:/org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue";
private final static String FACTORY_NAME = "jca:/org.apache.geronimo.configs/activemq-ra/JCAManagedConnectionFactory/DefaultActiveMQConnectionFactory";
public static void main(String[] args) throws NamingException
{
InitialContext ctx = new InitialContext();
QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup(FACTORY_NAME);
Queue queue = (Queue)ctx.lookup(QUEUE_NAME);
System.out.println(factory == null);
System.out.println(queue == null);
}
}
Run Code Online (Sandbox Code Playgroud)
如果它有所不同:我已将openejb-client-3.0.1.jar,geronimo-ejb_3.0_spec-1.0.1.jar和activemq-core-4.1.2-G20090207.jar添加到我的类路径中,并且我的jndi.properties文件具有以下属性:
java.naming.factory.initial = org.apache.openejb.client.RemoteInitialContextFactory java.naming.provider.url = ejbd://127.0.0.1:4201
我们正在使用Apache Camel(Camel 2.10.3,基于Java DSL)构建集成项目.
我们有一个从数据库中提取数据的路径(让我们称之为IN_DB),做一些逻辑并每天插入另一个数据库(OUT_DB),另一个订阅XML数据的JMS主题的路径,做一些逻辑和插入它整天都在同一个数据库(OUT_DB)中.
要求是当JMS主题连接因任何原因而失效时,我们会不断尝试重新连接,一旦重新连接成功,我们需要返回数据库(IN_DB)并进行另一次加载以填补主题的空白失意了.
我的问题是我们怎么能在Camel中做这个逻辑('我已经连接然后我断开连接,现在又连接了')?当主题发生故障时,以主题消费者开头的路线会发生什么,路线会停止吗?或者它会向某个错误队列发出错误消息?我是否必须编写自己的处理程序来监视主题连接,或者当主题重新启动并设置一些消息头时Camel会自动重新连接,或者设置一些上下文变量以指示'我已连接然后我断开了连接现在我再次联系'情景已经发生了?我很高兴围绕调用数据库负载构建路由逻辑我无法找出在Camel中"检测"这种情况发生的最佳方法.
任何建议非常感谢.
JMS 2.0规范说
所述
JMSMessageID报头字段包含唯一标识由提供商发送的每个消息的值.
...和...
唯一性的确切范围是提供者定义的.它应该至少涵盖特定安装提供程序的所有消息,其中安装是一组连接的消息路由器.
规范没有明确声明JMSMessageID从发布API调用返回的内容必须与消息中消息中存在的内容匹配.关于在回复请求时移动JMSMessageID到规范的规范中的讨论JMSCorrelationID意味着两者将是相同的.如果在发布和使用之间更改了消息ID,则此样式的请求/回复将失败.
当然,在JMS 1.1和现在2.0的统一域模型中,JMSMessageID根据目标是队列还是主题,改变行为是没有意义的.在统一的模式下,人们会期望所有目的地在这方面都采取相同的行动.
此外,如果第一段中使用的"提供者"指的是发送消息的内容,那么散布到具有相同JMSMessageID值的10条相同消息的发布将符合规范,因为在发送方测量唯一性.
不幸的是,规范在使用术语"提供者"来描述发送消息的事物与使用它来描述JMS传输的供应商之间切换.这在上面两个引用的段落中很明显.这种模棱两可并不重要.
至少有一个实现(IBM的MQ)采用的方法是,一个发布到10条消息的发布已经创建了10条唯一的新消息,因此每个消息都具有唯一JMSMessageID值.这可以说与第二个引用的段落一致,该段落需要作用于提供者的唯一性,其中"提供者"似乎是指供应商实现而不是发送消息的事物.
我相信,当发布的消息向多个订阅者扇出时,正确的行为将是JMSMessageID在消息的每个实例中保留,以便可以按预期关联回复.换句话说,我认为IBM的实施是不合规的.由于规范在这个问题上是模棱两可的,我正在寻找一个权威的来源,要么直接或强烈地暗示规范所预期的行为,不管是哪种方式.根据响应,我要么退出,要么将IBM的问题作为合规性缺陷提出.
jms ×10
java ×7
ibm-mq ×2
apache-camel ×1
concurrency ×1
difference ×1
ejb ×1
geronimo ×1
java-ee ×1
jms-queue ×1
jndi ×1
leveldb ×1
nms ×1
queue ×1
rmi ×1
terracotta ×1
websphere ×1
wildfly ×1
wildfly-10 ×1