Search in sources :

Example 6 with Channel

use of com.rabbitmq.client.Channel in project cloudstack by apache.

the class RabbitMQEventBus method subscribe.

/** Call to subscribe to interested set of events
     *
     * @param topic defines category and type of the events being subscribed to
     * @param subscriber subscriber that intends to receive event notification
     * @return UUID that represents the subscription with event bus
     * @throws EventBusException
     */
@Override
public UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws EventBusException {
    if (subscriber == null || topic == null) {
        throw new EventBusException("Invalid EventSubscriber/EventTopic object passed.");
    }
    // create a UUID, that will be used for managing subscriptions and also used as queue name
    // for on the queue used for the subscriber on the AMQP broker
    UUID queueId = UUID.randomUUID();
    String queueName = queueId.toString();
    try {
        String bindingKey = createBindingKey(topic);
        // store the subscriber details before creating channel
        s_subscribers.put(queueName, new Ternary(bindingKey, null, subscriber));
        // create a channel dedicated for this subscription
        Connection connection = getConnection();
        Channel channel = createChannel(connection);
        // create a queue and bind it to the exchange with binding key formed from event topic
        createExchange(channel, amqpExchangeName);
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName, amqpExchangeName, bindingKey);
        // register a callback handler to receive the events that a subscriber subscribed to
        channel.basicConsume(queueName, s_autoAck, queueName, new DefaultConsumer(channel) {

            @Override
            public void handleDelivery(String queueName, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                Ternary<String, Channel, EventSubscriber> queueDetails = s_subscribers.get(queueName);
                if (queueDetails != null) {
                    EventSubscriber subscriber = queueDetails.third();
                    String routingKey = envelope.getRoutingKey();
                    String eventSource = getEventSourceFromRoutingKey(routingKey);
                    String eventCategory = getEventCategoryFromRoutingKey(routingKey);
                    String eventType = getEventTypeFromRoutingKey(routingKey);
                    String resourceType = getResourceTypeFromRoutingKey(routingKey);
                    String resourceUUID = getResourceUUIDFromRoutingKey(routingKey);
                    Event event = new Event(eventSource, eventCategory, eventType, resourceType, resourceUUID);
                    event.setDescription(new String(body));
                    // deliver the event to call back object provided by subscriber
                    subscriber.onEvent(event);
                }
            }
        });
        // update the channel details for the subscription
        Ternary<String, Channel, EventSubscriber> queueDetails = s_subscribers.get(queueName);
        queueDetails.second(channel);
        s_subscribers.put(queueName, queueDetails);
    } catch (AlreadyClosedException closedException) {
        s_logger.warn("Connection to AMQP service is lost. Subscription:" + queueName + " will be active after reconnection");
    } catch (ConnectException connectException) {
        s_logger.warn("Connection to AMQP service is lost. Subscription:" + queueName + " will be active after reconnection");
    } catch (Exception e) {
        throw new EventBusException("Failed to subscribe to event due to " + e.getMessage());
    }
    return queueId;
}
Also used : EventSubscriber(org.apache.cloudstack.framework.events.EventSubscriber) DefaultConsumer(com.rabbitmq.client.DefaultConsumer) Ternary(com.cloud.utils.Ternary) Channel(com.rabbitmq.client.Channel) Connection(com.rabbitmq.client.Connection) IOException(java.io.IOException) AlreadyClosedException(com.rabbitmq.client.AlreadyClosedException) Envelope(com.rabbitmq.client.Envelope) ConfigurationException(javax.naming.ConfigurationException) ShutdownSignalException(com.rabbitmq.client.ShutdownSignalException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) ConnectException(java.net.ConnectException) EventBusException(org.apache.cloudstack.framework.events.EventBusException) IOException(java.io.IOException) AlreadyClosedException(com.rabbitmq.client.AlreadyClosedException) AMQP(com.rabbitmq.client.AMQP) Event(org.apache.cloudstack.framework.events.Event) EventBusException(org.apache.cloudstack.framework.events.EventBusException) UUID(java.util.UUID) ConnectException(java.net.ConnectException)

Example 7 with Channel

use of com.rabbitmq.client.Channel in project cloudstack by apache.

the class RabbitMQEventBus method unsubscribe.

@Override
public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws EventBusException {
    try {
        String classname = subscriber.getClass().getName();
        String queueName = UUID.nameUUIDFromBytes(classname.getBytes()).toString();
        Ternary<String, Channel, EventSubscriber> queueDetails = s_subscribers.get(queueName);
        Channel channel = queueDetails.second();
        channel.basicCancel(queueName);
        s_subscribers.remove(queueName, queueDetails);
    } catch (Exception e) {
        throw new EventBusException("Failed to unsubscribe from event bus due to " + e.getMessage());
    }
}
Also used : EventSubscriber(org.apache.cloudstack.framework.events.EventSubscriber) Channel(com.rabbitmq.client.Channel) EventBusException(org.apache.cloudstack.framework.events.EventBusException) ConfigurationException(javax.naming.ConfigurationException) ShutdownSignalException(com.rabbitmq.client.ShutdownSignalException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) ConnectException(java.net.ConnectException) EventBusException(org.apache.cloudstack.framework.events.EventBusException) IOException(java.io.IOException) AlreadyClosedException(com.rabbitmq.client.AlreadyClosedException)

Example 8 with Channel

use of com.rabbitmq.client.Channel in project druid by druid-io.

the class RabbitMQFirehoseFactory method connect.

@Override
public Firehose connect(final ByteBufferInputRowParser firehoseParser) throws IOException {
    ConnectionOptions lyraOptions = new ConnectionOptions(this.connectionFactory);
    Config lyraConfig = new Config().withRecoveryPolicy(new RetryPolicy().withMaxRetries(config.getMaxRetries()).withRetryInterval(Duration.seconds(config.getRetryIntervalSeconds())).withMaxDuration(Duration.seconds(config.getMaxDurationSeconds())));
    String queue = config.getQueue();
    String exchange = config.getExchange();
    String routingKey = config.getRoutingKey();
    boolean durable = config.isDurable();
    boolean exclusive = config.isExclusive();
    boolean autoDelete = config.isAutoDelete();
    final Connection connection = Connections.create(lyraOptions, lyraConfig);
    connection.addShutdownListener(new ShutdownListener() {

        @Override
        public void shutdownCompleted(ShutdownSignalException cause) {
            log.warn(cause, "Connection closed!");
        }
    });
    final Channel channel = connection.createChannel();
    channel.queueDeclare(queue, durable, exclusive, autoDelete, null);
    channel.queueBind(queue, exchange, routingKey);
    channel.addShutdownListener(new ShutdownListener() {

        @Override
        public void shutdownCompleted(ShutdownSignalException cause) {
            log.warn(cause, "Channel closed!");
        }
    });
    // We create a QueueingConsumer that will not auto-acknowledge messages since that
    // happens on commit().
    final QueueingConsumer consumer = new QueueingConsumer(channel);
    channel.basicConsume(queue, false, consumer);
    return new Firehose() {

        /**
       * Storing the latest delivery as a member variable should be safe since this will only be run
       * by a single thread.
       */
        private Delivery delivery;

        /**
       * Store the latest delivery tag to be able to commit (acknowledge) the message delivery up to
       * and including this tag. See commit() for more detail.
       */
        private long lastDeliveryTag;

        @Override
        public boolean hasMore() {
            delivery = null;
            try {
                // Wait for the next delivery. This will block until something is available.
                delivery = consumer.nextDelivery();
                if (delivery != null) {
                    lastDeliveryTag = delivery.getEnvelope().getDeliveryTag();
                    // If delivery is non-null, we report that there is something more to process.
                    return true;
                }
            } catch (InterruptedException e) {
                // A little unclear on how we should handle this.
                // At any rate, we're in an unknown state now so let's log something and return false.
                log.wtf(e, "Got interrupted while waiting for next delivery. Doubt this should ever happen.");
            }
            // nothing more to process.
            return false;
        }

        @Override
        public InputRow nextRow() {
            if (delivery == null) {
                //Just making sure.
                log.wtf("I have nothing in delivery. Method hasMore() should have returned false.");
                return null;
            }
            return firehoseParser.parse(ByteBuffer.wrap(delivery.getBody()));
        }

        @Override
        public Runnable commit() {
            // acknowledge values up to and including that value.
            return new Runnable() {

                // Store (copy) the last delivery tag to "become" thread safe.
                final long deliveryTag = lastDeliveryTag;

                @Override
                public void run() {
                    try {
                        log.info("Acknowledging delivery of messages up to tag: " + deliveryTag);
                        // Acknowledge all messages up to and including the stored delivery tag.
                        channel.basicAck(deliveryTag, true);
                    } catch (IOException e) {
                        log.error(e, "Unable to acknowledge message reception to message queue.");
                    }
                }
            };
        }

        @Override
        public void close() throws IOException {
            log.info("Closing connection to RabbitMQ");
            channel.close();
            connection.close();
        }
    };
}
Also used : Config(net.jodah.lyra.config.Config) Firehose(io.druid.data.input.Firehose) Channel(com.rabbitmq.client.Channel) Connection(com.rabbitmq.client.Connection) IOException(java.io.IOException) ShutdownListener(com.rabbitmq.client.ShutdownListener) ShutdownSignalException(com.rabbitmq.client.ShutdownSignalException) ConnectionOptions(net.jodah.lyra.ConnectionOptions) Delivery(com.rabbitmq.client.QueueingConsumer.Delivery) RetryPolicy(net.jodah.lyra.retry.RetryPolicy)

Example 9 with Channel

use of com.rabbitmq.client.Channel in project druid by druid-io.

the class RabbitMQProducerMain method main.

public static void main(String[] args) throws Exception {
    // We use a List to keep track of option insertion order. See below.
    final List<Option> optionList = new ArrayList<Option>();
    optionList.add(OptionBuilder.withLongOpt("help").withDescription("display this help message").create("h"));
    optionList.add(OptionBuilder.withLongOpt("hostname").hasArg().withDescription("the hostname of the AMQP broker [defaults to AMQP library default]").create("b"));
    optionList.add(OptionBuilder.withLongOpt("port").hasArg().withDescription("the port of the AMQP broker [defaults to AMQP library default]").create("n"));
    optionList.add(OptionBuilder.withLongOpt("username").hasArg().withDescription("username to connect to the AMQP broker [defaults to AMQP library default]").create("u"));
    optionList.add(OptionBuilder.withLongOpt("password").hasArg().withDescription("password to connect to the AMQP broker [defaults to AMQP library default]").create("p"));
    optionList.add(OptionBuilder.withLongOpt("vhost").hasArg().withDescription("name of virtual host on the AMQP broker [defaults to AMQP library default]").create("v"));
    optionList.add(OptionBuilder.withLongOpt("exchange").isRequired().hasArg().withDescription("name of the AMQP exchange [required - no default]").create("e"));
    optionList.add(OptionBuilder.withLongOpt("key").hasArg().withDescription("the routing key to use when sending messages [default: 'default.routing.key']").create("k"));
    optionList.add(OptionBuilder.withLongOpt("type").hasArg().withDescription("the type of exchange to create [default: 'topic']").create("t"));
    optionList.add(OptionBuilder.withLongOpt("durable").withDescription("if set, a durable exchange will be declared [default: not set]").create("d"));
    optionList.add(OptionBuilder.withLongOpt("autodelete").withDescription("if set, an auto-delete exchange will be declared [default: not set]").create("a"));
    optionList.add(OptionBuilder.withLongOpt("single").withDescription("if set, only a single message will be sent [default: not set]").create("s"));
    optionList.add(OptionBuilder.withLongOpt("start").hasArg().withDescription("time to use to start sending messages from [default: 2010-01-01T00:00:00]").create());
    optionList.add(OptionBuilder.withLongOpt("stop").hasArg().withDescription("time to use to send messages until (format: '2013-07-18T23:45:59') [default: current time]").create());
    optionList.add(OptionBuilder.withLongOpt("interval").hasArg().withDescription("the interval to add to the timestamp between messages in seconds [default: 10]").create());
    optionList.add(OptionBuilder.withLongOpt("delay").hasArg().withDescription("the delay between sending messages in milliseconds [default: 100]").create());
    // An extremely silly hack to maintain the above order in the help formatting.
    HelpFormatter formatter = new HelpFormatter();
    // Add a comparator to the HelpFormatter using the ArrayList above to sort by insertion order.
    formatter.setOptionComparator(new Comparator() {

        @Override
        public int compare(Object o1, Object o2) {
            // I know this isn't fast, but who cares! The list is short.
            return optionList.indexOf(o1) - optionList.indexOf(o2);
        }
    });
    // Now we can add all the options to an Options instance. This is dumb!
    Options options = new Options();
    for (Option option : optionList) {
        options.addOption(option);
    }
    CommandLine cmd = null;
    try {
        cmd = new BasicParser().parse(options, args);
    } catch (ParseException e) {
        formatter.printHelp("RabbitMQProducerMain", e.getMessage(), options, null);
        System.exit(1);
    }
    if (cmd.hasOption("h")) {
        formatter.printHelp("RabbitMQProducerMain", options);
        System.exit(2);
    }
    ConnectionFactory factory = new ConnectionFactory();
    if (cmd.hasOption("b")) {
        factory.setHost(cmd.getOptionValue("b"));
    }
    if (cmd.hasOption("u")) {
        factory.setUsername(cmd.getOptionValue("u"));
    }
    if (cmd.hasOption("p")) {
        factory.setPassword(cmd.getOptionValue("p"));
    }
    if (cmd.hasOption("v")) {
        factory.setVirtualHost(cmd.getOptionValue("v"));
    }
    if (cmd.hasOption("n")) {
        factory.setPort(Integer.parseInt(cmd.getOptionValue("n")));
    }
    String exchange = cmd.getOptionValue("e");
    String routingKey = "default.routing.key";
    if (cmd.hasOption("k")) {
        routingKey = cmd.getOptionValue("k");
    }
    boolean durable = cmd.hasOption("d");
    boolean autoDelete = cmd.hasOption("a");
    String type = cmd.getOptionValue("t", "topic");
    boolean single = cmd.hasOption("single");
    int interval = Integer.parseInt(cmd.getOptionValue("interval", "10"));
    int delay = Integer.parseInt(cmd.getOptionValue("delay", "100"));
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    Date stop = sdf.parse(cmd.getOptionValue("stop", sdf.format(new Date())));
    Random r = new Random();
    Calendar timer = Calendar.getInstance();
    timer.setTime(sdf.parse(cmd.getOptionValue("start", "2010-01-01T00:00:00")));
    String msg_template = "{\"utcdt\": \"%s\", \"wp\": %d, \"gender\": \"%s\", \"age\": %d}";
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    channel.exchangeDeclare(exchange, type, durable, autoDelete, null);
    do {
        int wp = (10 + r.nextInt(90)) * 100;
        String gender = r.nextBoolean() ? "male" : "female";
        int age = 20 + r.nextInt(70);
        String line = String.format(msg_template, sdf.format(timer.getTime()), wp, gender, age);
        channel.basicPublish(exchange, routingKey, null, line.getBytes());
        System.out.println("Sent message: " + line);
        timer.add(Calendar.SECOND, interval);
        Thread.sleep(delay);
    } while ((!single && stop.after(timer.getTime())));
    connection.close();
}
Also used : Options(org.apache.commons.cli.Options) Calendar(java.util.Calendar) Channel(com.rabbitmq.client.Channel) ArrayList(java.util.ArrayList) Connection(com.rabbitmq.client.Connection) Date(java.util.Date) Comparator(java.util.Comparator) HelpFormatter(org.apache.commons.cli.HelpFormatter) BasicParser(org.apache.commons.cli.BasicParser) CommandLine(org.apache.commons.cli.CommandLine) ConnectionFactory(com.rabbitmq.client.ConnectionFactory) Random(java.util.Random) Option(org.apache.commons.cli.Option) ParseException(org.apache.commons.cli.ParseException) SimpleDateFormat(java.text.SimpleDateFormat)

Example 10 with Channel

use of com.rabbitmq.client.Channel in project elasticsearch-river-rabbitmq by elastic.

the class RabbitMQIntegrationTest method launchTest.

private void launchTest(XContentBuilder river, final int numMessages, final int numDocsPerMessage, InjectorHook injectorHook, boolean delete, boolean update) throws Exception {
    final String dbName = getDbName();
    logger.info(" --> create index [{}]", dbName);
    try {
        client().admin().indices().prepareDelete(dbName).get();
    } catch (IndexMissingException e) {
    // No worries.
    }
    try {
        createIndex(dbName);
    } catch (IndexMissingException e) {
    // No worries.
    }
    ensureGreen(dbName);
    logger.info("  -> Checking rabbitmq running");
    // We try to connect to RabbitMQ.
    // If it's not launched, we don't fail the test but only log it
    Channel channel = null;
    Connection connection = null;
    try {
        logger.info(" --> connecting to rabbitmq");
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(AMQP.PROTOCOL.PORT);
        connection = factory.newConnection();
    } catch (ConnectException ce) {
        throw new Exception("RabbitMQ service is not launched on localhost:" + AMQP.PROTOCOL.PORT + ". Can not start Integration test. " + "Launch `rabbitmq-server`.", ce);
    }
    try {
        logger.info("  -> Creating [{}] channel", dbName);
        channel = connection.createChannel();
        logger.info("  -> Creating queue [{}]", dbName);
        channel.queueDeclare(getDbName(), true, false, false, null);
        // We purge the queue in case of something is remaining there
        logger.info("  -> Purging [{}] channel", dbName);
        channel.queuePurge(getDbName());
        logger.info("  -> Put [{}] messages with [{}] documents each = [{}] docs", numMessages, numDocsPerMessage, numMessages * numDocsPerMessage);
        final Set<String> removed = new HashSet<String>();
        int nbUpdated = 0;
        for (int i = 0; i < numMessages; i++) {
            StringBuffer message = new StringBuffer();
            for (int j = 0; j < numDocsPerMessage; j++) {
                if (logger.isTraceEnabled()) {
                    logger.trace("  -> Indexing document [{}] - [{}][{}]", i + "_" + j, i, j);
                }
                message.append("{ \"index\" : { \"_index\" : \"" + dbName + "\", \"_type\" : \"typex\", \"_id\" : \"" + i + "_" + j + "\" } }\n");
                message.append("{ \"field\" : \"" + i + "_" + j + "\",\"numeric\" : " + i * j + " }\n");
                // Sometime we update a document
                if (update && rarely()) {
                    String id = between(0, i) + "_" + between(0, j);
                    // We can only update if it has not been removed :)
                    if (!removed.contains(id)) {
                        logger.debug("  -> Updating document [{}] - [{}][{}]", id, i, j);
                        message.append("{ \"update\" : { \"_index\" : \"" + dbName + "\", \"_type\" : \"typex\", \"_id\" : \"" + id + "\" } }\n");
                        message.append("{ \"doc\": { \"foo\" : \"bar\", \"field2\" : \"" + i + "_" + j + "\" }}\n");
                        nbUpdated++;
                    }
                }
                // Sometime we delete a document
                if (delete && rarely()) {
                    String id = between(0, i) + "_" + between(0, j);
                    if (!removed.contains(id)) {
                        logger.debug("  -> Removing document [{}] - [{}][{}]", id, i, j);
                        message.append("{ \"delete\" : { \"_index\" : \"" + dbName + "\", \"_type\" : \"typex\", \"_id\" : \"" + id + "\" } }\n");
                        removed.add(id);
                    }
                }
            }
            channel.basicPublish("", dbName, null, message.toString().getBytes(StandardCharsets.UTF_8));
        }
        logger.info("  -> We removed [{}] docs and updated [{}] docs", removed.size(), nbUpdated);
        if (injectorHook != null) {
            logger.info("  -> Injecting extra data");
            injectorHook.inject();
        }
        logger.info(" --> create river");
        IndexResponse indexResponse = index("_river", dbName, "_meta", river);
        assertTrue(indexResponse.isCreated());
        logger.info("-->  checking that river [{}] was created", dbName);
        assertThat(awaitBusy(new Predicate<Object>() {

            public boolean apply(Object obj) {
                GetResponse response = client().prepareGet(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
                return response.isExists();
            }
        }, 5, TimeUnit.SECONDS), equalTo(true));
        // Check that docs are still processed by the river
        logger.info(" --> waiting for expected number of docs: [{}]", numDocsPerMessage * numMessages - removed.size());
        assertThat(awaitBusy(new Predicate<Object>() {

            public boolean apply(Object obj) {
                try {
                    refresh();
                    int expected = numDocsPerMessage * numMessages - removed.size();
                    CountResponse response = client().prepareCount(dbName).get();
                    logger.debug("  -> got {} docs, expected {}", response.getCount(), expected);
                    return response.getCount() == expected;
                } catch (IndexMissingException e) {
                    return false;
                }
            }
        }, 20, TimeUnit.SECONDS), equalTo(true));
    } finally {
        if (channel != null && channel.isOpen()) {
            channel.close();
        }
        if (connection != null && connection.isOpen()) {
            connection.close();
        }
        // Deletes the river
        GetResponse response = client().prepareGet(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
        if (response.isExists()) {
            client().prepareDelete(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_meta").get();
            client().prepareDelete(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
        }
        assertThat(awaitBusy(new Predicate<Object>() {

            public boolean apply(Object obj) {
                GetResponse response = client().prepareGet(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
                return response.isExists();
            }
        }, 5, TimeUnit.SECONDS), equalTo(false));
    }
}
Also used : Channel(com.rabbitmq.client.Channel) Connection(com.rabbitmq.client.Connection) CountResponse(org.elasticsearch.action.count.CountResponse) IndexMissingException(org.elasticsearch.indices.IndexMissingException) GetResponse(org.elasticsearch.action.get.GetResponse) ConnectException(java.net.ConnectException) IndexMissingException(org.elasticsearch.indices.IndexMissingException) Predicate(org.elasticsearch.common.base.Predicate) ConnectionFactory(com.rabbitmq.client.ConnectionFactory) IndexResponse(org.elasticsearch.action.index.IndexResponse) ConnectException(java.net.ConnectException) HashSet(java.util.HashSet)

Aggregations

Channel (com.rabbitmq.client.Channel)15 Connection (com.rabbitmq.client.Connection)7 IOException (java.io.IOException)5 ShutdownSignalException (com.rabbitmq.client.ShutdownSignalException)4 ConnectException (java.net.ConnectException)4 Test (org.junit.Test)4 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)3 AMQP (com.rabbitmq.client.AMQP)3 AlreadyClosedException (com.rabbitmq.client.AlreadyClosedException)3 ConfigurationException (javax.naming.ConfigurationException)3 EventBusException (org.apache.cloudstack.framework.events.EventBusException)3 EventSubscriber (org.apache.cloudstack.framework.events.EventSubscriber)3 ConnectionFactory (com.rabbitmq.client.ConnectionFactory)2 Date (java.util.Date)2 RouteBuilder (org.apache.camel.builder.RouteBuilder)2 Ternary (com.cloud.utils.Ternary)1 DeclareOk (com.rabbitmq.client.AMQP.Queue.DeclareOk)1 DefaultConsumer (com.rabbitmq.client.DefaultConsumer)1 Envelope (com.rabbitmq.client.Envelope)1 QueueingConsumer (com.rabbitmq.client.QueueingConsumer)1