Search in sources :

Example 6 with TopologyMember

use of org.apache.activemq.artemis.api.core.client.TopologyMember in project activemq-artemis by apache.

the class HAPolicyAutoBackupExample method waitForBackups.

private static void waitForBackups(ConnectionFactory cf0, int backups) throws InterruptedException {
    final CountDownLatch latch = new CountDownLatch(backups);
    ((ActiveMQConnectionFactory) cf0).getServerLocator().addClusterTopologyListener(new ClusterTopologyListener() {

        List<TransportConfiguration> backups = new ArrayList<>();

        @Override
        public void nodeUP(TopologyMember member, boolean last) {
            if (member.getBackup() != null && !backups.contains(member.getBackup())) {
                backups.add(member.getBackup());
                latch.countDown();
            }
        }

        @Override
        public void nodeDown(long eventUID, String nodeID) {
        }
    });
    latch.await(30000, TimeUnit.MILLISECONDS);
}
Also used : ClusterTopologyListener(org.apache.activemq.artemis.api.core.client.ClusterTopologyListener) ArrayList(java.util.ArrayList) TransportConfiguration(org.apache.activemq.artemis.api.core.TransportConfiguration) TopologyMember(org.apache.activemq.artemis.api.core.client.TopologyMember) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 7 with TopologyMember

use of org.apache.activemq.artemis.api.core.client.TopologyMember in project activemq-artemis by apache.

the class SharedNothingBackupActivation method run.

@Override
public void run() {
    try {
        logger.trace("SharedNothingBackupActivation..start");
        synchronized (activeMQServer) {
            activeMQServer.setState(ActiveMQServerImpl.SERVER_STATE.STARTED);
        }
        // move all data away:
        activeMQServer.getNodeManager().stop();
        activeMQServer.moveServerData(replicaPolicy.getMaxSavedReplicatedJournalsSize());
        activeMQServer.getNodeManager().start();
        synchronized (this) {
            if (closed) {
                logger.trace("SharedNothingBackupActivation is closed, ignoring activation!");
                return;
            }
        }
        boolean scalingDown = replicaPolicy.getScaleDownPolicy() != null && replicaPolicy.getScaleDownPolicy().isEnabled();
        if (!activeMQServer.initialisePart1(scalingDown)) {
            if (logger.isTraceEnabled()) {
                logger.trace("could not initialize part1 " + scalingDown);
            }
            return;
        }
        logger.trace("Waiting for a synchronize now...");
        synchronized (this) {
            logger.trace("Entered a synchronized");
            if (closed)
                return;
            backupQuorum = new SharedNothingBackupQuorum(activeMQServer.getStorageManager(), activeMQServer.getNodeManager(), activeMQServer.getScheduledPool(), networkHealthCheck, replicaPolicy.getQuorumSize(), replicaPolicy.getVoteRetries(), replicaPolicy.getVoteRetryWait());
            activeMQServer.getClusterManager().getQuorumManager().registerQuorum(backupQuorum);
            activeMQServer.getClusterManager().getQuorumManager().registerQuorumHandler(new ServerConnectVoteHandler(activeMQServer));
        }
        // use a Node Locator to connect to the cluster
        LiveNodeLocator nodeLocator;
        if (activationParams.get(ActivationParams.REPLICATION_ENDPOINT) != null) {
            TopologyMember member = (TopologyMember) activationParams.get(ActivationParams.REPLICATION_ENDPOINT);
            nodeLocator = new NamedNodeIdNodeLocator(member.getNodeId(), new Pair<>(member.getLive(), member.getBackup()));
        } else {
            nodeLocator = replicaPolicy.getGroupName() == null ? new AnyLiveNodeLocatorForReplication(backupQuorum, activeMQServer) : new NamedLiveNodeLocatorForReplication(replicaPolicy.getGroupName(), backupQuorum);
        }
        ClusterController clusterController = activeMQServer.getClusterManager().getClusterController();
        clusterController.addClusterTopologyListenerForReplication(nodeLocator);
        logger.trace("Waiting on cluster connection");
        clusterController.awaitConnectionToReplicationCluster();
        logger.trace("Cluster Connected");
        clusterController.addIncomingInterceptorForReplication(new ReplicationError(nodeLocator));
        // nodeManager.startBackup();
        if (logger.isTraceEnabled()) {
            logger.trace("Starting backup manager");
        }
        activeMQServer.getBackupManager().start();
        if (logger.isTraceEnabled()) {
            logger.trace("Set backup Quorum");
        }
        replicationEndpoint.setBackupQuorum(backupQuorum);
        replicationEndpoint.setExecutor(activeMQServer.getExecutorFactory().getExecutor());
        EndpointConnector endpointConnector = new EndpointConnector();
        if (logger.isTraceEnabled()) {
            logger.trace("Starting Backup Server");
        }
        ActiveMQServerLogger.LOGGER.backupServerStarted(activeMQServer.getVersion().getFullVersion(), activeMQServer.getNodeManager().getNodeId());
        activeMQServer.setState(ActiveMQServerImpl.SERVER_STATE.STARTED);
        if (logger.isTraceEnabled())
            logger.trace("Setting server state as started");
        SharedNothingBackupQuorum.BACKUP_ACTIVATION signal;
        do {
            if (closed) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Activation is closed, so giving up");
                }
                return;
            }
            if (logger.isTraceEnabled()) {
                logger.trace("looking up the node through nodeLocator.locateNode()");
            }
            // locate the first live server to try to replicate
            nodeLocator.locateNode();
            Pair<TransportConfiguration, TransportConfiguration> possibleLive = nodeLocator.getLiveConfiguration();
            nodeID = nodeLocator.getNodeID();
            if (logger.isTraceEnabled()) {
                logger.trace("nodeID = " + nodeID);
            }
            // in a normal (non failback) scenario if we couldn't find our live server we should fail
            if (!attemptFailBack) {
                if (logger.isTraceEnabled()) {
                    logger.trace("attemptFailback=false, nodeID=" + nodeID);
                }
                // this shouldn't happen
                if (nodeID == null) {
                    logger.debug("Throwing a RuntimeException as nodeID==null ant attemptFailback=false");
                    throw new RuntimeException("Could not establish the connection");
                }
                activeMQServer.getNodeManager().setNodeID(nodeID);
            }
            try {
                if (logger.isTraceEnabled()) {
                    logger.trace("Calling clusterController.connectToNodeInReplicatedCluster(" + possibleLive.getA() + ")");
                }
                clusterControl = clusterController.connectToNodeInReplicatedCluster(possibleLive.getA());
            } catch (Exception e) {
                logger.debug(e.getMessage(), e);
                if (possibleLive.getB() != null) {
                    try {
                        clusterControl = clusterController.connectToNodeInReplicatedCluster(possibleLive.getB());
                    } catch (Exception e1) {
                        clusterControl = null;
                    }
                }
            }
            if (clusterControl == null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("sleeping " + clusterController.getRetryIntervalForReplicatedCluster() + " it should retry");
                }
                // its ok to retry here since we haven't started replication yet
                // it may just be the server has gone since discovery
                Thread.sleep(clusterController.getRetryIntervalForReplicatedCluster());
                signal = SharedNothingBackupQuorum.BACKUP_ACTIVATION.ALREADY_REPLICATING;
                continue;
            }
            activeMQServer.getThreadPool().execute(endpointConnector);
            /**
             * Wait for a signal from the the quorum manager, at this point if replication has been successful we can
             * fail over or if there is an error trying to replicate (such as already replicating) we try the
             * process again on the next live server.  All the action happens inside {@link BackupQuorum}
             */
            signal = backupQuorum.waitForStatusChange();
            if (logger.isTraceEnabled()) {
                logger.trace("Got a signal " + signal + " through backupQuorum.waitForStatusChange()");
            }
            /**
             * replicationEndpoint will be holding lots of open files. Make sure they get
             * closed/sync'ed.
             */
            ActiveMQServerImpl.stopComponent(replicationEndpoint);
            // time to give up
            if (!activeMQServer.isStarted() || signal == STOP) {
                if (logger.isTraceEnabled()) {
                    logger.trace("giving up on the activation:: activemqServer.isStarted=" + activeMQServer.isStarted() + " while signal = " + signal);
                }
                return;
            } else if (signal == FAIL_OVER) {
                // time to fail over
                if (logger.isTraceEnabled()) {
                    logger.trace("signal == FAIL_OVER, breaking the loop");
                }
                break;
            } else if (signal == SharedNothingBackupQuorum.BACKUP_ACTIVATION.FAILURE_REPLICATING) {
                // something has gone badly run restart from scratch
                if (logger.isTraceEnabled()) {
                    logger.trace("Starting a new thread to stop the server!");
                }
                Thread startThread = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Calling activeMQServer.stop() and start() to restart the server");
                            }
                            activeMQServer.stop();
                            activeMQServer.start();
                        } catch (Exception e) {
                            ActiveMQServerLogger.LOGGER.errorRestartingBackupServer(e, activeMQServer);
                        }
                    }
                });
                startThread.start();
                return;
            }
            // ok, this live is no good, let's reset and try again
            // close this session factory, we're done with it
            clusterControl.close();
            backupQuorum.reset();
            if (replicationEndpoint.getChannel() != null) {
                replicationEndpoint.getChannel().close();
                replicationEndpoint.setChannel(null);
            }
        } while (signal == SharedNothingBackupQuorum.BACKUP_ACTIVATION.ALREADY_REPLICATING);
        if (logger.isTraceEnabled()) {
            logger.trace("Activation loop finished, current signal = " + signal);
        }
        activeMQServer.getClusterManager().getQuorumManager().unRegisterQuorum(backupQuorum);
        if (!isRemoteBackupUpToDate()) {
            logger.debug("throwing exception for !isRemoteBackupUptoDate");
            throw ActiveMQMessageBundle.BUNDLE.backupServerNotInSync();
        }
        if (logger.isTraceEnabled()) {
            logger.trace("@@@ setReplicaPolicy::" + replicaPolicy);
        }
        replicaPolicy.getReplicatedPolicy().setReplicaPolicy(replicaPolicy);
        activeMQServer.setHAPolicy(replicaPolicy.getReplicatedPolicy());
        synchronized (activeMQServer) {
            if (!activeMQServer.isStarted()) {
                logger.trace("Server is stopped, giving up right before becomingLive");
                return;
            }
            ActiveMQServerLogger.LOGGER.becomingLive(activeMQServer);
            logger.trace("stop backup");
            activeMQServer.getNodeManager().stopBackup();
            logger.trace("start store manager");
            activeMQServer.getStorageManager().start();
            logger.trace("activated");
            activeMQServer.getBackupManager().activated();
            if (scalingDown) {
                logger.trace("Scalling down...");
                activeMQServer.initialisePart2(true);
            } else {
                logger.trace("Setting up new activation");
                activeMQServer.setActivation(new SharedNothingLiveActivation(activeMQServer, replicaPolicy.getReplicatedPolicy()));
                logger.trace("initialize part 2");
                activeMQServer.initialisePart2(false);
                if (activeMQServer.getIdentity() != null) {
                    ActiveMQServerLogger.LOGGER.serverIsLive(activeMQServer.getIdentity());
                } else {
                    ActiveMQServerLogger.LOGGER.serverIsLive();
                }
            }
            logger.trace("completeActivation at the end");
            activeMQServer.completeActivation();
        }
    } catch (Exception e) {
        if (logger.isTraceEnabled()) {
            logger.trace(e.getMessage() + ", serverStarted=" + activeMQServer.isStarted(), e);
        }
        if ((e instanceof InterruptedException || e instanceof IllegalStateException) && !activeMQServer.isStarted())
            // do not log these errors if the server is being stopped.
            return;
        ActiveMQServerLogger.LOGGER.initializationError(e);
    }
}
Also used : TransportConfiguration(org.apache.activemq.artemis.api.core.TransportConfiguration) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ActiveMQInternalErrorException(org.apache.activemq.artemis.api.core.ActiveMQInternalErrorException) ClusterController(org.apache.activemq.artemis.core.server.cluster.ClusterController) SharedNothingBackupQuorum(org.apache.activemq.artemis.core.server.cluster.qourum.SharedNothingBackupQuorum) LiveNodeLocator(org.apache.activemq.artemis.core.server.LiveNodeLocator) TopologyMember(org.apache.activemq.artemis.api.core.client.TopologyMember) Pair(org.apache.activemq.artemis.api.core.Pair)

Example 8 with TopologyMember

use of org.apache.activemq.artemis.api.core.client.TopologyMember in project activemq-artemis by apache.

the class OpenWireProtocolManager method generateMembersURI.

private String generateMembersURI(boolean flip) {
    String uri;
    StringBuffer connectedBrokers = new StringBuffer();
    String separator = "";
    synchronized (members) {
        if (members.size() > 0) {
            for (TopologyMember member : members) {
                connectedBrokers.append(separator).append(member.toURI());
                separator = ",";
            }
            // in case of failures you won't get all the connections failing to a single server.
            if (flip && members.size() > 1) {
                members.addLast(members.removeFirst());
            }
        }
    }
    uri = connectedBrokers.toString();
    return uri;
}
Also used : SimpleString(org.apache.activemq.artemis.api.core.SimpleString) TopologyMember(org.apache.activemq.artemis.api.core.client.TopologyMember)

Example 9 with TopologyMember

use of org.apache.activemq.artemis.api.core.client.TopologyMember in project activemq-artemis by apache.

the class SharedNothingReplicationTest method testReplicateFromSlowLive.

@Test
public void testReplicateFromSlowLive() throws Exception {
    // start live
    Configuration liveConfiguration = createLiveConfiguration();
    ActiveMQServer liveServer = ActiveMQServers.newActiveMQServer(liveConfiguration);
    liveServer.start();
    Wait.waitFor(() -> liveServer.isStarted());
    CoreMessagePersister.theInstance = SlowMessagePersister._getInstance();
    final CountDownLatch replicated = new CountDownLatch(1);
    ServerLocator locator = ServerLocatorImpl.newLocator("tcp://localhost:61616");
    locator.setCallTimeout(60_000L);
    locator.setConnectionTTL(60_000L);
    locator.addClusterTopologyListener(new ClusterTopologyListener() {

        @Override
        public void nodeUP(TopologyMember member, boolean last) {
            logger.infof("nodeUP fired last=%s, live=%s, backup=%s", last, member.getLive(), member.getBackup());
            if (member.getBackup() != null) {
                replicated.countDown();
            }
        }

        @Override
        public void nodeDown(long eventUID, String nodeID) {
        }
    });
    final ClientSessionFactory csf = locator.createSessionFactory();
    ClientSession sess = csf.createSession();
    sess.createQueue("slow", RoutingType.ANYCAST, "slow", true);
    sess.close();
    Executor sendMessageExecutor = Executors.newCachedThreadPool();
    // let's write some messages
    int i = 0;
    final int j = 50;
    final CountDownLatch allMessageSent = new CountDownLatch(j);
    while (i < 5) {
        sendMessageExecutor.execute(() -> {
            try {
                ClientSession session = csf.createSession(true, true);
                ClientProducer producer = session.createProducer("slow");
                ClientMessage message = session.createMessage(true);
                // this will make journal's append executor busy
                message.putLongProperty("delay", 500L);
                logger.infof("try to send a message before replicated");
                producer.send(message);
                logger.info("send message done");
                producer.close();
                session.close();
                allMessageSent.countDown();
            } catch (ActiveMQException e) {
                logger.error("send message", e);
            }
        });
        i++;
    }
    // start backup
    Configuration backupConfiguration = createBackupConfiguration();
    ActiveMQServer backupServer = ActiveMQServers.newActiveMQServer(backupConfiguration);
    backupServer.start();
    Wait.waitFor(() -> backupServer.isStarted());
    Assert.assertTrue("can not replicate in 30 seconds", replicated.await(30, TimeUnit.SECONDS));
    while (i < j) {
        sendMessageExecutor.execute(() -> {
            try {
                ClientSession session = csf.createSession(true, true);
                ClientProducer producer = session.createProducer("slow");
                ClientMessage message = session.createMessage(true);
                message.putLongProperty("delay", 0L);
                logger.infof("try to send a message after replicated");
                producer.send(message);
                logger.info("send message done");
                producer.close();
                session.close();
                allMessageSent.countDown();
            } catch (ActiveMQException e) {
                logger.error("send message", e);
            }
        });
        i++;
    }
    Assert.assertTrue("all message sent", allMessageSent.await(30, TimeUnit.SECONDS));
    csf.close();
    locator.close();
    backupServer.stop(true);
    liveServer.stop(true);
    SequentialFileFactory fileFactory;
    File liveJournalDir = brokersFolder.getRoot().toPath().resolve("live").resolve("data").resolve("journal").toFile();
    fileFactory = new MappedSequentialFileFactory(liveConfiguration.getJournalLocation(), liveConfiguration.getJournalFileSize(), false, liveConfiguration.getJournalBufferSize_NIO(), liveConfiguration.getJournalBufferTimeout_NIO(), null);
    JournalImpl liveMessageJournal = new JournalImpl(liveConfiguration.getJournalFileSize(), liveConfiguration.getJournalMinFiles(), liveConfiguration.getJournalPoolFiles(), liveConfiguration.getJournalCompactMinFiles(), liveConfiguration.getJournalCompactPercentage(), fileFactory, "activemq-data", "amq", fileFactory.getMaxIO());
    liveMessageJournal.start();
    final AtomicInteger liveJournalCounter = new AtomicInteger();
    liveMessageJournal.load(new AddRecordLoaderCallback() {

        @Override
        public void addRecord(RecordInfo info) {
            if (!(info.userRecordType == JournalRecordIds.ADD_MESSAGE_PROTOCOL)) {
            // ignore
            }
            logger.infof("got live message %d", info.id);
            liveJournalCounter.incrementAndGet();
        }
    });
    // read backup's journal
    File backupJournalDir = brokersFolder.getRoot().toPath().resolve("backup").resolve("data").resolve("journal").toFile();
    fileFactory = new MappedSequentialFileFactory(backupConfiguration.getJournalLocation(), backupConfiguration.getJournalFileSize(), false, backupConfiguration.getJournalBufferSize_NIO(), backupConfiguration.getJournalBufferTimeout_NIO(), null);
    JournalImpl backupMessageJournal = new JournalImpl(backupConfiguration.getJournalFileSize(), backupConfiguration.getJournalMinFiles(), backupConfiguration.getJournalPoolFiles(), backupConfiguration.getJournalCompactMinFiles(), backupConfiguration.getJournalCompactPercentage(), fileFactory, "activemq-data", "amq", fileFactory.getMaxIO());
    backupMessageJournal.start();
    final AtomicInteger replicationCounter = new AtomicInteger();
    backupMessageJournal.load(new AddRecordLoaderCallback() {

        @Override
        public void addRecord(RecordInfo info) {
            if (!(info.userRecordType == JournalRecordIds.ADD_MESSAGE_PROTOCOL)) {
            // ignore
            }
            logger.infof("replicated message %d", info.id);
            replicationCounter.incrementAndGet();
        }
    });
    logger.infof("expected %d messages, live=%d, backup=%d", j, liveJournalCounter.get(), replicationCounter.get());
    Assert.assertEquals("Live lost journal record", j, liveJournalCounter.get());
    Assert.assertEquals("Backup did not replicated all journal", j, replicationCounter.get());
    // if this ever happens.. you need to make sure this persister is registered instead of the CoreMessagePersister
    Assert.assertTrue("The test is not valid, slow persister stopped being used", SlowMessagePersister._getInstance().used);
}
Also used : Configuration(org.apache.activemq.artemis.core.config.Configuration) ClusterConnectionConfiguration(org.apache.activemq.artemis.core.config.ClusterConnectionConfiguration) ReplicatedPolicyConfiguration(org.apache.activemq.artemis.core.config.ha.ReplicatedPolicyConfiguration) ReplicaPolicyConfiguration(org.apache.activemq.artemis.core.config.ha.ReplicaPolicyConfiguration) ClusterTopologyListener(org.apache.activemq.artemis.api.core.client.ClusterTopologyListener) RecordInfo(org.apache.activemq.artemis.core.journal.RecordInfo) MappedSequentialFileFactory(org.apache.activemq.artemis.core.io.mapped.MappedSequentialFileFactory) ClientMessage(org.apache.activemq.artemis.api.core.client.ClientMessage) CountDownLatch(java.util.concurrent.CountDownLatch) SequentialFileFactory(org.apache.activemq.artemis.core.io.SequentialFileFactory) MappedSequentialFileFactory(org.apache.activemq.artemis.core.io.mapped.MappedSequentialFileFactory) ActiveMQServer(org.apache.activemq.artemis.core.server.ActiveMQServer) Executor(java.util.concurrent.Executor) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) TopologyMember(org.apache.activemq.artemis.api.core.client.TopologyMember) ClientSessionFactory(org.apache.activemq.artemis.api.core.client.ClientSessionFactory) ClientProducer(org.apache.activemq.artemis.api.core.client.ClientProducer) File(java.io.File) ServerLocator(org.apache.activemq.artemis.api.core.client.ServerLocator) JournalImpl(org.apache.activemq.artemis.core.journal.impl.JournalImpl) Test(org.junit.Test)

Aggregations

TopologyMember (org.apache.activemq.artemis.api.core.client.TopologyMember)9 ActiveMQException (org.apache.activemq.artemis.api.core.ActiveMQException)4 SimpleString (org.apache.activemq.artemis.api.core.SimpleString)4 TransportConfiguration (org.apache.activemq.artemis.api.core.TransportConfiguration)4 CountDownLatch (java.util.concurrent.CountDownLatch)2 ClientSessionFactory (org.apache.activemq.artemis.api.core.client.ClientSessionFactory)2 ClusterTopologyListener (org.apache.activemq.artemis.api.core.client.ClusterTopologyListener)2 Configuration (org.apache.activemq.artemis.core.config.Configuration)2 ActiveMQServer (org.apache.activemq.artemis.core.server.ActiveMQServer)2 File (java.io.File)1 ObjectStreamException (java.io.ObjectStreamException)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Executor (java.util.concurrent.Executor)1 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 ActiveMQIllegalStateException (org.apache.activemq.artemis.api.core.ActiveMQIllegalStateException)1 ActiveMQInternalErrorException (org.apache.activemq.artemis.api.core.ActiveMQInternalErrorException)1 ActiveMQInterruptedException (org.apache.activemq.artemis.api.core.ActiveMQInterruptedException)1 Pair (org.apache.activemq.artemis.api.core.Pair)1