Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/52.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Azure 如何在使用AMQP建立到事件中心的连接时设置x-opt-offset以避免消息重播_Azure_Amqp_Azure Eventhub - Fatal编程技术网

Azure 如何在使用AMQP建立到事件中心的连接时设置x-opt-offset以避免消息重播

Azure 如何在使用AMQP建立到事件中心的连接时设置x-opt-offset以避免消息重播,azure,amqp,azure-eventhub,Azure,Amqp,Azure Eventhub,我的应用程序连接到azure事件中心以接收和处理消息。我发现每次重新启动应用程序时,保留期内的所有消息都会被重放。我阅读了有关偏移量的文章以避免此问题,我有一个方法将与azure事件中心的连接设置为: MessageConsumer connect(){ //设置JNDI上下文 BatchEventHubConfig BatchEventHubConfig=//包含配置的映射 字符串queueName=“EventHub” 字符串connectionFactoryName=“SBCF” //长偏

我的应用程序连接到azure事件中心以接收和处理消息。我发现每次重新启动应用程序时,保留期内的所有消息都会被重放。我阅读了有关偏移量的文章以避免此问题,我有一个方法将与azure事件中心的连接设置为:

MessageConsumer connect(){
//设置JNDI上下文
BatchEventHubConfig BatchEventHubConfig=//包含配置的映射
字符串queueName=“EventHub”
字符串connectionFactoryName=“SBCF”
//长偏移量=batchAccountManager.batchStorageManager.batchJobMsgCheckpointService.get(batchEventHubConfig.namespace,batchEventHubConfig.getMessageQueueAddress(partitionInx,true))?.offset
Hashtable Hashtable=新的Hashtable()
put(“connectionfactory.${connectionFactoryName}”,batchEventHubConfig.getAMQPConnectionURI())
hashtable.put(“queue.${queueName}”,batchEventHubConfig.getMessageQueueAddress(partitionInx))
//put(“apache.org:selector-filter:string”,“amqp.annotation.x-opt-offset>'${offset}'”)
put(Context.INITIAL\u Context\u工厂,“org.apache.qpid.amqp\u 1\u 0.jms.jndi.PropertiesFileInitialContextFactory”)
上下文上下文=新的初始上下文(哈希表)
ConnectionFactory工厂=(ConnectionFactory)上下文。查找(connectionFactoryName)
队列=(目标)上下文。查找(队列名称)
connection=factory.createConnection(batchEventHubConfig.sasPolicyName,batchEventHubConfig.sasPolicyKey)
connection.setExceptionListener(新的BatchExceptionListener(eventHubConnection:this))
connection.start()
session=connection.createSession(false,session.CLIENT\u确认)
messageConsumer=session.createConsumer(队列)
messageConsumer.setMessageListener(messageListener)
消息消费者
}
注释掉的偏移量代码是我在阅读这里之后尝试的:


设置偏移量的正确方法是什么,以便在应用程序重新启动时不会重新播放消息?

Apche QPID不支持AMQP筛选器(底层Apache Proton J不支持)

通过在末尾添加以下行,我修补了AmqpConsumerBuilder.configureSource()方法:

Symbol filterKey = Symbol.valueOf("apache.org:selector-filter:string");
UnknownDescribedType filterValue = new UnknownDescribedType(filterKey, String.format("%s > '%s'",amqp.annotation.x-opt-offset", lastOffset));

filters.put(filterKey, filterValue);
而且它有效


因此,您要么创建一个Apache QPID分支并应用此修补程序,要么将修改后的类放在类路径中以覆盖原始的(非常糟糕的解决方案)

Apche QPID不支持AMQP过滤器(底层的Apache Proton J不支持)

通过在末尾添加以下行,我修补了AmqpConsumerBuilder.configureSource()方法:

Symbol filterKey = Symbol.valueOf("apache.org:selector-filter:string");
UnknownDescribedType filterValue = new UnknownDescribedType(filterKey, String.format("%s > '%s'",amqp.annotation.x-opt-offset", lastOffset));

filters.put(filterKey, filterValue);
而且它有效


因此,要么你使用ApacheQPID的分支并应用此补丁,要么你将修改后的类放在类路径中以覆盖原始的(非常糟糕的解决方案)

这比我想象的要容易得多!找到此链接:

所以我所要做的就是像这样添加过滤条件:

messageConsumer = session.createConsumer(queue, "amqp.annotation.x-opt-offset >= '${messageOffset}'")

这比我想象的要容易得多!找到此链接:

所以我所要做的就是像这样添加过滤条件:

messageConsumer = session.createConsumer(queue, "amqp.annotation.x-opt-offset >= '${messageOffset}'")

受Mourad Zouabi答案的启发,我创建了qpid jms存储库的分支,并对AmqpConsumerBuilder类进行了如下更改,以允许将筛选器传递给MessageConsumer:

   if (resourceInfo.getSelector() != null && !resourceInfo.getSelector().trim().equals("")) {
        if (resourceInfo.getSelector().startsWith("x-opt-offset") || resourceInfo.getSelector().startsWith("x-opt-enqueued-time")) {
            // support Azure Event HUB filters
            // see: https://azure.github.io/amqpnetlite/articles/azure_eventhubs.html
            Symbol filterKey = Symbol.valueOf("apache.org:selector-filter:string");
            UnknownDescribedType filterValue = new UnknownDescribedType(filterKey,"amqp.annotation." + resourceInfo.getSelector().trim());
            filters.put(filterKey, filterValue);
        } else {
            filters.put(JMS_SELECTOR_SYMBOL, new AmqpJmsSelectorType(resourceInfo.getSelector()));
        }
    }
    if (!filters.isEmpty()) {
        source.setFilter(filters);
    }
MessageConsumer consumer = session.createConsumer(queue,  String.format("x-opt-offset > %s", offset));
现在,可以在创建MessageConsumer时传递筛选器:

   if (resourceInfo.getSelector() != null && !resourceInfo.getSelector().trim().equals("")) {
        if (resourceInfo.getSelector().startsWith("x-opt-offset") || resourceInfo.getSelector().startsWith("x-opt-enqueued-time")) {
            // support Azure Event HUB filters
            // see: https://azure.github.io/amqpnetlite/articles/azure_eventhubs.html
            Symbol filterKey = Symbol.valueOf("apache.org:selector-filter:string");
            UnknownDescribedType filterValue = new UnknownDescribedType(filterKey,"amqp.annotation." + resourceInfo.getSelector().trim());
            filters.put(filterKey, filterValue);
        } else {
            filters.put(JMS_SELECTOR_SYMBOL, new AmqpJmsSelectorType(resourceInfo.getSelector()));
        }
    }
    if (!filters.isEmpty()) {
        source.setFilter(filters);
    }
MessageConsumer consumer = session.createConsumer(queue,  String.format("x-opt-offset > %s", offset));


请参阅以获取工作分叉。

受Mourad Zouabi答案的启发,我创建了qpid jms存储库的分叉,并更改了AmqpConsumerBuilder类,如下所示,以允许将筛选器传递给MessageConsumer:

   if (resourceInfo.getSelector() != null && !resourceInfo.getSelector().trim().equals("")) {
        if (resourceInfo.getSelector().startsWith("x-opt-offset") || resourceInfo.getSelector().startsWith("x-opt-enqueued-time")) {
            // support Azure Event HUB filters
            // see: https://azure.github.io/amqpnetlite/articles/azure_eventhubs.html
            Symbol filterKey = Symbol.valueOf("apache.org:selector-filter:string");
            UnknownDescribedType filterValue = new UnknownDescribedType(filterKey,"amqp.annotation." + resourceInfo.getSelector().trim());
            filters.put(filterKey, filterValue);
        } else {
            filters.put(JMS_SELECTOR_SYMBOL, new AmqpJmsSelectorType(resourceInfo.getSelector()));
        }
    }
    if (!filters.isEmpty()) {
        source.setFilter(filters);
    }
MessageConsumer consumer = session.createConsumer(queue,  String.format("x-opt-offset > %s", offset));
现在,可以在创建MessageConsumer时传递筛选器:

   if (resourceInfo.getSelector() != null && !resourceInfo.getSelector().trim().equals("")) {
        if (resourceInfo.getSelector().startsWith("x-opt-offset") || resourceInfo.getSelector().startsWith("x-opt-enqueued-time")) {
            // support Azure Event HUB filters
            // see: https://azure.github.io/amqpnetlite/articles/azure_eventhubs.html
            Symbol filterKey = Symbol.valueOf("apache.org:selector-filter:string");
            UnknownDescribedType filterValue = new UnknownDescribedType(filterKey,"amqp.annotation." + resourceInfo.getSelector().trim());
            filters.put(filterKey, filterValue);
        } else {
            filters.put(JMS_SELECTOR_SYMBOL, new AmqpJmsSelectorType(resourceInfo.getSelector()));
        }
    }
    if (!filters.isEmpty()) {
        source.setFilter(filters);
    }
MessageConsumer consumer = session.createConsumer(queue,  String.format("x-opt-offset > %s", offset));


请参阅以获取工作分叉。

这对我不起作用,将导致如下异常:javax.jms.InvalidSelectorException:amqp.annotation.x-opt-offset>='1'它必须是有效的偏移量值,如果以空队列开始,则该值应为-1。使用qpid jms客户端时,名称中带有点的过滤器,将导致无效的SelectorException。关于空队列,你是对的。我也遇到了。但这将导致另一个错误。使用我显示为答案的分叉版本,可以与qpid jms客户端配合使用这对我不起作用,并将导致如下异常:javax.jms.InvalidSelectorException:amqp.annotation.x-opt-offset>='1'它必须是有效的偏移量值,如果以空队列开始,则该值应为-1。使用qpid jms客户端时,名称中带有点的筛选器将导致InvalidSelectorException。关于空队列,你是对的。我也遇到了。但这将导致另一个错误。使用我作为答案展示的分叉版本,可以很好地与qpid jms客户机配合使用