[英]How to create durable subscription to ibm mq amqp topic from java program?
我们通过提供clientId
和订阅者名称,使用createDurableSubscriber
以编程方式创建了 IBM MQ AMQP TOPIC 的订阅者。
我们启动程序,让它订阅 TOPIC 并停止程序。 然后将消息发送到主题并再次启动接收器程序,但我们无法接收发送的消息并丢失在持久订阅的情况下不应该发生的消息。
当订阅者使用 mqsc 命令DISPLAY TOPIC
、 DISPLAY TPSTATUS
、 DISPLAY TPSTATUS SUB
、 DISPLAY SUB SUBID
连接时,我们可以看到 amqp 主题及其持久订阅,但在订阅者程序停止时则看不到。 我们已经定义了属性DEFPSIST(YES)
并且客户端(生产者到主题)正在发送持久消息。
由于我们在订阅者的持久队列中看不到消息,消息去了哪里? 它取决于到期属性吗?
连接时为我们的订户输出DISPLAY SUB SUBID
。
AMQ8096: WebSphere MQ subscription inquired.
SUBID("hex sub id")
SUB(:private:CLINET01:TOPIC01) TOPICSTR(TOPIC01)
TOPICOBJ(SYSTEM.BASE.TOPIC) DISTYPE(RESOLVED)
DEST(SYSTEM.MANAGED.DURABLE.5F6B5C2524FB9AED)
DESTQMGR(qm.name) PUBAPPID( )
SELECTOR( ) SELTYPE(NONE)
USERDATA(010)
PUBACCT(***************************************************)
DESTCORL(***************************************************)
DESTCLAS(MANAGED) DURABLE(YES)
EXPIRY(0) PSPROP(MSGPROP)
PUBPRTY(ASPUB) REQONLY(NO)
SUBSCOPE(ALL) SUBLEVEL(1)
SUBTYPE(API) VARUSER(FIXED)
WSCHEMA(TOPIC) SUBUSER(mqm)
CRDATE(2020-09-28) CRTIME(04:14:09)
ALTDATE(2020-09-28) ALTTIME(04:14:09)
订阅者 ID 具有私有(不知道为什么)和客户端 ID,但没有订阅者名称,即 sub4
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Topic;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.lang.String;
import javax.jms.Destination;
import javax.naming.Context;
import org.apache.qpid.jms.JmsConnectionFactory;
import javax.jms.DeliveryMode;
import javax.naming.InitialContext;
import javax.jms.Message;
public class AMQPQueueExample1 implements Runnable {
private static final int DELIVERY_MODE = DeliveryMode.PERSISTENT;
public void run(){
try{
Connection connection = null;
Context context = new InitialContext();
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("myFactoryLookup");
connection = connectionFactory.createConnection();
connection.setClientID("123");//("WHATS_MY_PURPOSE3"); // Why do we need clientID while publishing the TOPIC from consumer / publisher
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic priceTopic = (Topic) context.lookup("myTopicLookup1");
MessageConsumer subscriber1 = session.createDurableSubscriber(priceTopic,"sub420"); //"sub3");
System.out.println("TOPIC "+priceTopic);
connection.start();
while(true){
TextMessage message1 = (TextMessage) subscriber1.receive(1000);
if(message1!=null)
System.out.println("Subscriber 1 received : " + message1.getText());
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
AMQPQueueExample1 amp=new AMQPQueueExample1();
Thread thread = new Thread(amp);
thread.start();
}
}
值取自 jndi.properties 文件,用于上下文工厂和提供程序 url。
从评论中看,您使用的是 MQ 8.0.0.5? 如果是这种情况,则该版本的 MQ 不支持 Apache Qpid JMS 客户端。 我相信在那个版本中,一个非常基本的非持久订阅可能会起作用,但任何其他 JMS 方法都不太可能起作用。
我怀疑正在发生的事情是来自 Qpid JMS 的 AMQP 1.0 流没有被那个版本的 MQ 完全理解,所以订阅的到期时间被设置为 0 而不是无限制。
MQ 9.2 添加了对更多 JMS 2.0 规范的支持——尽管不是每个 JMS 特性。 有关此处支持的方法的更多信息:
https://www.ibm.com/support/knowledgecenter/SSFKSJ_9.2.0/com.ibm.mq.dev.doc/q125050_.htm
创建持久订阅者和/或消费者应该按您的预期工作。
Matthew Whitehead 的一篇文章“ 来自 Microsoft®.NET™ 的 MQ Light 消息传递(第 4 部分) ”陈述如下:
AMQP 通道不支持为 MQ Light 订阅设置无限期。 虽然可以创建具有很长生存时间的订阅,但不可能创建永久存在的订阅。
如果您希望创建永不过期的订阅,您可以通过创建 MQ 管理订阅并让 MQ Light 客户端加入和离开订阅来实现。 这也有助于确保在第一个订阅者连接之前发布到主题的任何消息不会完全丢失。 阅读我之前关于将 MQ Light 客户端加入管理订阅的文章。
相关 AMQP 字段
为了提供上述到期功能,MQ Light 使用了 AMQP 1.0 的 2 个特性:
- 源超时
- 来源到期政策
源超时用于指定订阅到期的时间(以秒为单位)。
源到期策略用于确定是什么导致到期计时器开始。 MQ AMQP 通道仅支持链接分离的过期策略,这意味着一旦最后一个链接与订阅分离,计时器就会启动。
我搜索并找不到有关如何在 Apache QPID 中设置源超时或源到期策略的参考,但链接的博客引用了通过管理定义的订阅设置到期。 根据您问题中的信息,我认为您可以提前定义类似的内容。 我没有指定EXPIRY
因为这将从SYSTEM.DEFAULT.SUB
获取EXPIRY(UNLIMITED)
:
DEFINE SUB(':private:CLINET01:TOPIC01') TOPICOBJ(SYSTEM.BASE.TOPIC) TOPICSTR('TOPIC01') DESTCLAS(MANAGED)
当您然后连接您的 AMQP 订阅者时,它将恢复此现有订阅,并将到期时间设置为UNLIMITED
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.