C# 带有故障转移设置的ActiveMQ上未确认的消息不会重新传递给订阅服务器

C# 带有故障转移设置的ActiveMQ上未确认的消息不会重新传递给订阅服务器,c#,activemq,nms,C#,Activemq,Nms,我正在c#中实现活动MQ发布服务器和订阅服务器。我正在使用Apache.NMS.ActiveMQ.net客户端库与代理进行通信 <package id="Apache.NMS" version="1.7.1" targetFramework="net461" /> <package id="Apache.NMS.ActiveMQ" version="1.7.2" targetFramework="net461" /> 下面是我订阅该主题的方式。此代码的设置使多个

我正在c#中实现活动MQ发布服务器和订阅服务器。我正在使用Apache.NMS.ActiveMQ.net客户端库与代理进行通信

  <package id="Apache.NMS" version="1.7.1" targetFramework="net461" />
  <package id="Apache.NMS.ActiveMQ" version="1.7.2" targetFramework="net461" />
下面是我订阅该主题的方式。此代码的设置使多个共享订阅者可以侦听传入消息。我被告知我必须使用虚拟主题来实现这一点。因此,我将订阅服务器配置为使用虚拟主题,它托管在Windows服务项目中。我使用确认模式来表示ClientAcknowledge,因此除非消息被确认,否则它应该继续返回。下面的代码片段仅代表windows服务的重要订户部分

var brokerUrl = "failover://tcp://103.24.34.225:61616,tcp://103.24.34.226:61616,tcp://103.24.34.346:61616,tcp://103.24.34.347:61616"; 
IConnectionFactory factory = new ConnectionFactory(new Uri(brokerUrl));
IConnection connection = factory.CreateConnection("conn1", "conn$34"))

    connection.ClientId = "TESTSUBSCRIBER";
    connection.AcknowledgementMode = AcknowledgementMode.ClientAcknowledge;
    connection.ConnectionInterruptedListener += OnConnectionInturrupted;
    connection.ExceptionListener += OnConnectionExceptionListener;
    connection.ConnectionResumedListener += OnConnectionResumedListener;
    connection.Start();

    ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
    var queue = new ActiveMQQueue("VT.TESTSUBSCRIBER.ACCOUNT.UPDATE");
    ActiveMQTopic topic = new ActiveMQTopic();
    IMessageConsumer consumer = session.CreateConsumer(queue); 

    consumer.Listener += OnMessage;



private void OnMessage(IMessage message)
{
    var payload = ((ITextMessage)message).Text;
    Log.Info($"Received message for Client TESTSUBSCRIBER - [{payload}]");
    if(payload != "43342_test")
    {
        message.Acknowledge(); 
            Log.Info($"Message acknowledged for Client TESTSUBSCRIBER - [{payload}]");  
    }
}

private void OnConnectionResumedListener()
{
    Log.Info($"Subscriber connection resumed for Client TESTSUBSCRIBER");
}

private void OnConnectionExceptionListener(Exception exception)
{
    Log.Error(exception);
}

private void OnConnectionInturrupted()
{
    Log.Error($"Subscriber connection interrupted for Client TESTSUBSCRIBER");
}
我能够发布和订阅消息。我遇到了一个关于一个特殊案例的问题。假设订阅者从故障转移服务器池建立到(.225代理服务器)的连接。出版商发表了一条消息。用户接收到它,它正在进行中间处理。但是由于一些服务器补丁的维护,windows服务不得不关闭。因此,与代理的订阅服务器连接断开。当windows服务恢复时,这一次订阅服务器建立了与故障转移池中不同代理服务器(.346代理服务器)的连接。发生这种情况时,未确认的消息从未重新传递。但是,如果我重新启动windows服务,并且幸运的是,如果与.225代理(订阅服务器最初连接到的同一服务器)建立了连接,那么现在订阅服务器将收到未确认的消息

我的假设是,在故障转移设置中配置ActiveMQ时,无论订阅服务器能够与故障转移池中的哪个代理服务器建立连接,它都应该始终接收未确认的消息

在某些情况下,故障转移设置似乎正在工作。假设订阅服务器已从故障转移池连接到.346代理服务器。发布服务器从同一池连接到不同的代理服务器(.225代理)并发布消息,订阅服务器正在接收消息。这证明故障转移设置正在工作

但是,一旦订阅者从代理服务器接收到消息,并且如果订阅者在确认消息之前断开连接,它必须重新建立到同一代理服务器的连接,以接收未确认的消息。我觉得这不太对


活动MQ服务器设置是否需要任何其他配置才能使此用例正常工作?

此问题的解决方案不在客户端,而是使用活动MQ服务器配置

对于生产者流控制目标策略,添加ConditionalNetworkBridgeFilter并启用ReplayHennoConsumers

var brokerUrl = "failover://tcp://103.24.34.225:61616,tcp://103.24.34.226:61616,tcp://103.24.34.346:61616,tcp://103.24.34.347:61616"; 
IConnectionFactory factory = new ConnectionFactory(new Uri(brokerUrl));
IConnection connection = factory.CreateConnection("conn1", "conn$34"))

    connection.ClientId = "TESTSUBSCRIBER";
    connection.AcknowledgementMode = AcknowledgementMode.ClientAcknowledge;
    connection.ConnectionInterruptedListener += OnConnectionInturrupted;
    connection.ExceptionListener += OnConnectionExceptionListener;
    connection.ConnectionResumedListener += OnConnectionResumedListener;
    connection.Start();

    ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
    var queue = new ActiveMQQueue("VT.TESTSUBSCRIBER.ACCOUNT.UPDATE");
    ActiveMQTopic topic = new ActiveMQTopic();
    IMessageConsumer consumer = session.CreateConsumer(queue); 

    consumer.Listener += OnMessage;



private void OnMessage(IMessage message)
{
    var payload = ((ITextMessage)message).Text;
    Log.Info($"Received message for Client TESTSUBSCRIBER - [{payload}]");
    if(payload != "43342_test")
    {
        message.Acknowledge(); 
            Log.Info($"Message acknowledged for Client TESTSUBSCRIBER - [{payload}]");  
    }
}

private void OnConnectionResumedListener()
{
    Log.Info($"Subscriber connection resumed for Client TESTSUBSCRIBER");
}

private void OnConnectionExceptionListener(Exception exception)
{
    Log.Error(exception);
}

private void OnConnectionInturrupted()
{
    Log.Error($"Subscriber connection interrupted for Client TESTSUBSCRIBER");
}