Search in sources :

Example 1 with MultiTopicsConsumerImpl

use of org.apache.pulsar.client.impl.MultiTopicsConsumerImpl in project pulsar by apache.

the class PartitionCreationTest method testCreateMissedPartitions.

@Test(timeOut = 60000, dataProvider = "restCreateMissedPartitions")
public void testCreateMissedPartitions(boolean useRestApi) throws PulsarAdminException, PulsarClientException, MetadataStoreException {
    conf.setAllowAutoTopicCreation(false);
    final String topic = "testCreateMissedPartitions-useRestApi-" + useRestApi;
    int numPartitions = 3;
    // simulate partitioned topic without partitions
    pulsar.getPulsarResources().getNamespaceResources().getPartitionedTopicResources().createPartitionedTopicAsync(TopicName.get(topic), new PartitionedTopicMetadata(numPartitions));
    Consumer<byte[]> consumer = null;
    try {
        consumer = pulsarClient.newConsumer().topic(topic).subscriptionName("sub-1").subscribeAsync().get(3, TimeUnit.SECONDS);
    } catch (Exception e) {
    // ok here, consumer will create failed with 'Topic does not exist'
    }
    Assert.assertNull(consumer);
    if (useRestApi) {
        admin.topics().createMissedPartitions(topic);
    } else {
        final TopicName topicName = TopicName.get(topic);
        for (int i = 0; i < numPartitions; i++) {
            admin.topics().createNonPartitionedTopic(topicName.getPartition(i).toString());
        }
    }
    consumer = pulsarClient.newConsumer().topic(topic).subscriptionName("sub-1").subscribe();
    Assert.assertNotNull(consumer);
    Assert.assertTrue(consumer instanceof MultiTopicsConsumerImpl);
    Assert.assertEquals(((MultiTopicsConsumerImpl) consumer).getConsumers().size(), 3);
}
Also used : MultiTopicsConsumerImpl(org.apache.pulsar.client.impl.MultiTopicsConsumerImpl) PartitionedTopicMetadata(org.apache.pulsar.common.partition.PartitionedTopicMetadata) MetadataStoreException(org.apache.pulsar.metadata.api.MetadataStoreException) PulsarAdminException(org.apache.pulsar.client.admin.PulsarAdminException) TopicName(org.apache.pulsar.common.naming.TopicName) Test(org.testng.annotations.Test)

Example 2 with MultiTopicsConsumerImpl

use of org.apache.pulsar.client.impl.MultiTopicsConsumerImpl in project pulsar by yahoo.

the class PerformanceConsumer method main.

public static void main(String[] args) throws Exception {
    final Arguments arguments = new Arguments();
    JCommander jc = new JCommander(arguments);
    jc.setProgramName("pulsar-perf consume");
    try {
        jc.parse(args);
    } catch (ParameterException e) {
        System.out.println(e.getMessage());
        jc.usage();
        PerfClientUtils.exit(-1);
    }
    if (arguments.help) {
        jc.usage();
        PerfClientUtils.exit(-1);
    }
    if (isBlank(arguments.authPluginClassName) && !isBlank(arguments.deprecatedAuthPluginClassName)) {
        arguments.authPluginClassName = arguments.deprecatedAuthPluginClassName;
    }
    if (arguments.topic != null && arguments.topic.size() != arguments.numTopics) {
        // keep compatibility with the previous version
        if (arguments.topic.size() == 1) {
            String prefixTopicName = TopicName.get(arguments.topic.get(0)).toString().trim();
            List<String> defaultTopics = new ArrayList<>();
            for (int i = 0; i < arguments.numTopics; i++) {
                defaultTopics.add(String.format("%s-%d", prefixTopicName, i));
            }
            arguments.topic = defaultTopics;
        } else {
            System.out.println("The size of topics list should be equal to --num-topics");
            jc.usage();
            PerfClientUtils.exit(-1);
        }
    }
    if (arguments.subscriptionType == SubscriptionType.Exclusive && arguments.numConsumers > 1) {
        System.out.println("Only one consumer is allowed when subscriptionType is Exclusive");
        jc.usage();
        PerfClientUtils.exit(-1);
    }
    if (arguments.subscriptions != null && arguments.subscriptions.size() != arguments.numSubscriptions) {
        // keep compatibility with the previous version
        if (arguments.subscriptions.size() == 1) {
            if (arguments.subscriberName == null) {
                arguments.subscriberName = arguments.subscriptions.get(0);
            }
            List<String> defaultSubscriptions = new ArrayList<>();
            for (int i = 0; i < arguments.numSubscriptions; i++) {
                defaultSubscriptions.add(String.format("%s-%d", arguments.subscriberName, i));
            }
            arguments.subscriptions = defaultSubscriptions;
        } else {
            System.out.println("The size of subscriptions list should be equal to --num-subscriptions");
            jc.usage();
            PerfClientUtils.exit(-1);
        }
    }
    if (arguments.confFile != null) {
        Properties prop = new Properties(System.getProperties());
        prop.load(new FileInputStream(arguments.confFile));
        if (arguments.serviceURL == null) {
            arguments.serviceURL = prop.getProperty("brokerServiceUrl");
        }
        if (arguments.serviceURL == null) {
            arguments.serviceURL = prop.getProperty("webServiceUrl");
        }
        // fallback to previous-version serviceUrl property to maintain backward-compatibility
        if (arguments.serviceURL == null) {
            arguments.serviceURL = prop.getProperty("serviceUrl", "http://localhost:8080/");
        }
        if (arguments.authPluginClassName == null) {
            arguments.authPluginClassName = prop.getProperty("authPlugin", null);
        }
        if (arguments.authParams == null) {
            arguments.authParams = prop.getProperty("authParams", null);
        }
        if (isBlank(arguments.tlsTrustCertsFilePath)) {
            arguments.tlsTrustCertsFilePath = prop.getProperty("tlsTrustCertsFilePath", "");
        }
        if (arguments.tlsAllowInsecureConnection == null) {
            arguments.tlsAllowInsecureConnection = Boolean.parseBoolean(prop.getProperty("tlsAllowInsecureConnection", ""));
        }
    }
    // Dump config variables
    PerfClientUtils.printJVMInformation(log);
    ObjectMapper m = new ObjectMapper();
    ObjectWriter w = m.writerWithDefaultPrettyPrinter();
    log.info("Starting Pulsar performance consumer with config: {}", w.writeValueAsString(arguments));
    final Recorder qRecorder = arguments.autoScaledReceiverQueueSize ? new Recorder(arguments.receiverQueueSize, 5) : null;
    final RateLimiter limiter = arguments.rate > 0 ? RateLimiter.create(arguments.rate) : null;
    long startTime = System.nanoTime();
    long testEndTime = startTime + (long) (arguments.testTime * 1e9);
    ClientBuilder clientBuilder = // 
    PulsarClient.builder().enableTransaction(arguments.isEnableTransaction).serviceUrl(// 
    arguments.serviceURL).connectionsPerBroker(// 
    arguments.maxConnections).statsInterval(arguments.statsIntervalSeconds, // 
    TimeUnit.SECONDS).ioThreads(// 
    arguments.ioThreads).listenerThreads(arguments.listenerThreads).enableBusyWait(arguments.enableBusyWait).tlsTrustCertsFilePath(arguments.tlsTrustCertsFilePath);
    if (isNotBlank(arguments.authPluginClassName)) {
        clientBuilder.authentication(arguments.authPluginClassName, arguments.authParams);
    }
    if (arguments.tlsAllowInsecureConnection != null) {
        clientBuilder.allowTlsInsecureConnection(arguments.tlsAllowInsecureConnection);
    }
    if (isNotBlank(arguments.listenerName)) {
        clientBuilder.listenerName(arguments.listenerName);
    }
    PulsarClient pulsarClient = clientBuilder.build();
    AtomicReference<Transaction> atomicReference;
    if (arguments.isEnableTransaction) {
        atomicReference = new AtomicReference<>(pulsarClient.newTransaction().withTransactionTimeout(arguments.transactionTimeout, TimeUnit.SECONDS).build().get());
    } else {
        atomicReference = new AtomicReference<>(null);
    }
    AtomicLong messageAckedCount = new AtomicLong();
    Semaphore messageReceiveLimiter = new Semaphore(arguments.numMessagesPerTransaction);
    Thread thread = Thread.currentThread();
    MessageListener<ByteBuffer> listener = (consumer, msg) -> {
        if (arguments.testTime > 0) {
            if (System.nanoTime() > testEndTime) {
                log.info("------------------- DONE -----------------------");
                PerfClientUtils.exit(0);
                thread.interrupt();
            }
        }
        if (arguments.totalNumTxn > 0) {
            if (totalEndTxnOpFailNum.sum() + totalEndTxnOpSuccessNum.sum() >= arguments.totalNumTxn) {
                log.info("------------------- DONE -----------------------");
                PerfClientUtils.exit(0);
                thread.interrupt();
            }
        }
        if (qRecorder != null) {
            qRecorder.recordValue(((ConsumerBase<?>) consumer).getTotalIncomingMessages());
        }
        messagesReceived.increment();
        bytesReceived.add(msg.size());
        totalMessagesReceived.increment();
        totalBytesReceived.add(msg.size());
        if (limiter != null) {
            limiter.acquire();
        }
        long latencyMillis = System.currentTimeMillis() - msg.getPublishTime();
        if (latencyMillis >= 0) {
            recorder.recordValue(latencyMillis);
            cumulativeRecorder.recordValue(latencyMillis);
        }
        if (arguments.isEnableTransaction) {
            try {
                messageReceiveLimiter.acquire();
            } catch (InterruptedException e) {
                log.error("Got error: ", e);
            }
            consumer.acknowledgeAsync(msg.getMessageId(), atomicReference.get()).thenRun(() -> {
                totalMessageAck.increment();
                messageAck.increment();
            }).exceptionally(throwable -> {
                log.error("Ack message {} failed with exception", msg, throwable);
                totalMessageAckFailed.increment();
                return null;
            });
        } else {
            consumer.acknowledgeAsync(msg).thenRun(() -> {
                totalMessageAck.increment();
                messageAck.increment();
            }).exceptionally(throwable -> {
                log.error("Ack message {} failed with exception", msg, throwable);
                totalMessageAckFailed.increment();
                return null;
            });
        }
        if (arguments.poolMessages) {
            msg.release();
        }
        if (arguments.isEnableTransaction && messageAckedCount.incrementAndGet() == arguments.numMessagesPerTransaction) {
            Transaction transaction = atomicReference.get();
            if (!arguments.isAbortTransaction) {
                transaction.commit().thenRun(() -> {
                    if (log.isDebugEnabled()) {
                        log.debug("Commit transaction {}", transaction.getTxnID());
                    }
                    totalEndTxnOpSuccessNum.increment();
                    numTxnOpSuccess.increment();
                }).exceptionally(exception -> {
                    log.error("Commit transaction failed with exception : ", exception);
                    totalEndTxnOpFailNum.increment();
                    return null;
                });
            } else {
                transaction.abort().thenRun(() -> {
                    if (log.isDebugEnabled()) {
                        log.debug("Abort transaction {}", transaction.getTxnID());
                    }
                    totalEndTxnOpSuccessNum.increment();
                    numTxnOpSuccess.increment();
                }).exceptionally(exception -> {
                    log.error("Abort transaction {} failed with exception", transaction.getTxnID().toString(), exception);
                    totalEndTxnOpFailNum.increment();
                    return null;
                });
            }
            while (true) {
                try {
                    Transaction newTransaction = pulsarClient.newTransaction().withTransactionTimeout(arguments.transactionTimeout, TimeUnit.SECONDS).build().get();
                    atomicReference.compareAndSet(transaction, newTransaction);
                    totalNumTxnOpenSuccess.increment();
                    messageAckedCount.set(0);
                    messageReceiveLimiter.release(arguments.numMessagesPerTransaction);
                    break;
                } catch (Exception e) {
                    log.error("Failed to new transaction with exception:", e);
                    totalNumTxnOpenFail.increment();
                }
            }
        }
    };
    List<Future<Consumer<ByteBuffer>>> futures = new ArrayList<>();
    ConsumerBuilder<ByteBuffer> consumerBuilder = // 
    pulsarClient.newConsumer(Schema.BYTEBUFFER).messageListener(// 
    listener).receiverQueueSize(// 
    arguments.receiverQueueSize).maxTotalReceiverQueueSizeAcrossPartitions(arguments.maxTotalReceiverQueueSizeAcrossPartitions).acknowledgmentGroupTime(arguments.acknowledgmentsGroupingDelayMillis, // 
    TimeUnit.MILLISECONDS).subscriptionType(arguments.subscriptionType).subscriptionInitialPosition(arguments.subscriptionInitialPosition).autoAckOldestChunkedMessageOnQueueFull(arguments.autoAckOldestChunkedMessageOnQueueFull).enableBatchIndexAcknowledgment(arguments.batchIndexAck).poolMessages(arguments.poolMessages).replicateSubscriptionState(arguments.replicatedSubscription).autoScaledReceiverQueueSizeEnabled(arguments.autoScaledReceiverQueueSize);
    if (arguments.maxPendingChunkedMessage > 0) {
        consumerBuilder.maxPendingChunkedMessage(arguments.maxPendingChunkedMessage);
    }
    if (arguments.expireTimeOfIncompleteChunkedMessageMs > 0) {
        consumerBuilder.expireTimeOfIncompleteChunkedMessage(arguments.expireTimeOfIncompleteChunkedMessageMs, TimeUnit.MILLISECONDS);
    }
    if (isNotBlank(arguments.encKeyFile)) {
        consumerBuilder.defaultCryptoKeyReader(arguments.encKeyFile);
    }
    for (int i = 0; i < arguments.numTopics; i++) {
        final TopicName topicName = TopicName.get(arguments.topic.get(i));
        log.info("Adding {} consumers per subscription on topic {}", arguments.numConsumers, topicName);
        for (int j = 0; j < arguments.numSubscriptions; j++) {
            String subscriberName = arguments.subscriptions.get(j);
            for (int k = 0; k < arguments.numConsumers; k++) {
                futures.add(consumerBuilder.clone().topic(topicName.toString()).subscriptionName(subscriberName).subscribeAsync());
            }
        }
    }
    for (Future<Consumer<ByteBuffer>> future : futures) {
        future.get();
    }
    log.info("Start receiving from {} consumers per subscription on {} topics", arguments.numConsumers, arguments.numTopics);
    long start = System.nanoTime();
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
        printAggregatedThroughput(start, arguments);
        printAggregatedStats();
    }));
    long oldTime = System.nanoTime();
    Histogram reportHistogram = null;
    Histogram qHistogram = null;
    HistogramLogWriter histogramLogWriter = null;
    if (arguments.histogramFile != null) {
        String statsFileName = arguments.histogramFile;
        log.info("Dumping latency stats to {}", statsFileName);
        PrintStream histogramLog = new PrintStream(new FileOutputStream(statsFileName), false);
        histogramLogWriter = new HistogramLogWriter(histogramLog);
        // Some log header bits
        histogramLogWriter.outputLogFormatVersion();
        histogramLogWriter.outputLegend();
    }
    while (true) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            break;
        }
        long now = System.nanoTime();
        double elapsed = (now - oldTime) / 1e9;
        long total = totalMessagesReceived.sum();
        double rate = messagesReceived.sumThenReset() / elapsed;
        double throughput = bytesReceived.sumThenReset() / elapsed * 8 / 1024 / 1024;
        double rateAck = messageAck.sumThenReset() / elapsed;
        long totalTxnOpSuccessNum = 0;
        long totalTxnOpFailNum = 0;
        double rateOpenTxn = 0;
        reportHistogram = recorder.getIntervalHistogram(reportHistogram);
        if (arguments.isEnableTransaction) {
            totalTxnOpSuccessNum = totalEndTxnOpSuccessNum.sum();
            totalTxnOpFailNum = totalEndTxnOpFailNum.sum();
            rateOpenTxn = numTxnOpSuccess.sumThenReset() / elapsed;
            log.info("--- Transaction: {} transaction end successfully --- {} transaction end failed " + "--- {}  Txn/s --- AckRate: {} msg/s", totalTxnOpSuccessNum, totalTxnOpFailNum, dec.format(rateOpenTxn), dec.format(rateAck));
        }
        log.info("Throughput received: {} msg --- {}  msg/s --- {} Mbit/s  " + "--- Latency: mean: {} ms - med: {} " + "- 95pct: {} - 99pct: {} - 99.9pct: {} - 99.99pct: {} - Max: {}", intFormat.format(total), dec.format(rate), dec.format(throughput), dec.format(reportHistogram.getMean()), reportHistogram.getValueAtPercentile(50), reportHistogram.getValueAtPercentile(95), reportHistogram.getValueAtPercentile(99), reportHistogram.getValueAtPercentile(99.9), reportHistogram.getValueAtPercentile(99.99), reportHistogram.getMaxValue());
        if (arguments.autoScaledReceiverQueueSize && log.isDebugEnabled() && qRecorder != null) {
            qHistogram = qRecorder.getIntervalHistogram(qHistogram);
            log.debug("ReceiverQueueUsage: cnt={},mean={}, min={},max={},25pct={},50pct={},75pct={}", qHistogram.getTotalCount(), dec.format(qHistogram.getMean()), qHistogram.getMinValue(), qHistogram.getMaxValue(), qHistogram.getValueAtPercentile(25), qHistogram.getValueAtPercentile(50), qHistogram.getValueAtPercentile(75));
            qHistogram.reset();
            for (Future<Consumer<ByteBuffer>> future : futures) {
                ConsumerBase<?> consumerBase = (ConsumerBase<?>) future.get();
                log.debug("[{}] CurrentReceiverQueueSize={}", consumerBase.getConsumerName(), consumerBase.getCurrentReceiverQueueSize());
                if (consumerBase instanceof MultiTopicsConsumerImpl) {
                    for (ConsumerImpl<?> consumer : ((MultiTopicsConsumerImpl<?>) consumerBase).getConsumers()) {
                        log.debug("[{}] SubConsumer.CurrentReceiverQueueSize={}", consumer.getConsumerName(), consumer.getCurrentReceiverQueueSize());
                    }
                }
            }
        }
        if (histogramLogWriter != null) {
            histogramLogWriter.outputIntervalHistogram(reportHistogram);
        }
        reportHistogram.reset();
        oldTime = now;
    }
    pulsarClient.close();
}
Also used : LongAdder(java.util.concurrent.atomic.LongAdder) Parameters(com.beust.jcommander.Parameters) ParameterException(com.beust.jcommander.ParameterException) TopicName(org.apache.pulsar.common.naming.TopicName) Parameter(com.beust.jcommander.Parameter) LoggerFactory(org.slf4j.LoggerFactory) ConsumerBuilder(org.apache.pulsar.client.api.ConsumerBuilder) HistogramLogWriter(org.HdrHistogram.HistogramLogWriter) SubscriptionInitialPosition(org.apache.pulsar.client.api.SubscriptionInitialPosition) RateLimiter(com.google.common.util.concurrent.RateLimiter) AtomicReference(java.util.concurrent.atomic.AtomicReference) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) Future(java.util.concurrent.Future) Recorder(org.HdrHistogram.Recorder) PulsarClient(org.apache.pulsar.client.api.PulsarClient) PrintStream(java.io.PrintStream) Properties(java.util.Properties) ConsumerImpl(org.apache.pulsar.client.impl.ConsumerImpl) Logger(org.slf4j.Logger) ObjectWriter(com.fasterxml.jackson.databind.ObjectWriter) Semaphore(java.util.concurrent.Semaphore) MessageListener(org.apache.pulsar.client.api.MessageListener) JCommander(com.beust.jcommander.JCommander) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) DecimalFormat(java.text.DecimalFormat) FileOutputStream(java.io.FileOutputStream) PaddingDecimalFormat(org.apache.pulsar.testclient.utils.PaddingDecimalFormat) FileInputStream(java.io.FileInputStream) SubscriptionType(org.apache.pulsar.client.api.SubscriptionType) Transaction(org.apache.pulsar.client.api.transaction.Transaction) Schema(org.apache.pulsar.client.api.Schema) TimeUnit(java.util.concurrent.TimeUnit) Histogram(org.HdrHistogram.Histogram) AtomicLong(java.util.concurrent.atomic.AtomicLong) Consumer(org.apache.pulsar.client.api.Consumer) ConsumerBase(org.apache.pulsar.client.impl.ConsumerBase) List(java.util.List) StringUtils.isNotBlank(org.apache.commons.lang3.StringUtils.isNotBlank) StringUtils.isBlank(org.apache.commons.lang3.StringUtils.isBlank) ClientBuilder(org.apache.pulsar.client.api.ClientBuilder) Collections(java.util.Collections) MultiTopicsConsumerImpl(org.apache.pulsar.client.impl.MultiTopicsConsumerImpl) Histogram(org.HdrHistogram.Histogram) ArrayList(java.util.ArrayList) Semaphore(java.util.concurrent.Semaphore) Properties(java.util.Properties) Consumer(org.apache.pulsar.client.api.Consumer) JCommander(com.beust.jcommander.JCommander) MultiTopicsConsumerImpl(org.apache.pulsar.client.impl.MultiTopicsConsumerImpl) ParameterException(com.beust.jcommander.ParameterException) PulsarClient(org.apache.pulsar.client.api.PulsarClient) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) ClientBuilder(org.apache.pulsar.client.api.ClientBuilder) HistogramLogWriter(org.HdrHistogram.HistogramLogWriter) PrintStream(java.io.PrintStream) ConsumerBase(org.apache.pulsar.client.impl.ConsumerBase) ObjectWriter(com.fasterxml.jackson.databind.ObjectWriter) Recorder(org.HdrHistogram.Recorder) ByteBuffer(java.nio.ByteBuffer) FileInputStream(java.io.FileInputStream) RateLimiter(com.google.common.util.concurrent.RateLimiter) ParameterException(com.beust.jcommander.ParameterException) TopicName(org.apache.pulsar.common.naming.TopicName) AtomicLong(java.util.concurrent.atomic.AtomicLong) Transaction(org.apache.pulsar.client.api.transaction.Transaction) FileOutputStream(java.io.FileOutputStream) Future(java.util.concurrent.Future)

Example 3 with MultiTopicsConsumerImpl

use of org.apache.pulsar.client.impl.MultiTopicsConsumerImpl in project pulsar by yahoo.

the class ContextImplTest method testGetConsumerMultiTopic.

@Test
public void testGetConsumerMultiTopic() throws PulsarClientException {
    config.setExposePulsarAdminClientEnabled(false);
    context = new ContextImpl(config, logger, client, new EnvironmentBasedSecretsProvider(), FunctionCollectorRegistry.getDefaultImplementation(), new String[0], FunctionDetails.ComponentType.FUNCTION, null, new InstanceStateManager(), pulsarAdmin, clientBuilder);
    ConsumerImpl<?> consumer1 = Mockito.mock(ConsumerImpl.class);
    when(consumer1.getTopic()).thenReturn(TopicName.get("first").toString());
    ConsumerImpl<?> consumer2 = Mockito.mock(ConsumerImpl.class);
    when(consumer2.getTopic()).thenReturn(TopicName.get("second").toString());
    List<Consumer<?>> consumersList = Lists.newArrayList(consumer1, consumer2);
    MultiTopicsConsumerImpl mtc = Mockito.mock(MultiTopicsConsumerImpl.class);
    when(mtc.getConsumers()).thenReturn(consumersList);
    context.setInputConsumers(Lists.newArrayList(mtc));
    Assert.assertNotNull(context.getConsumer("first", 0));
    Assert.assertNotNull(context.getConsumer("second", 0));
    try {
        // nknown topic
        context.getConsumer("third", 0);
        Assert.fail("Expected exception");
    } catch (PulsarClientException e) {
    // pass
    }
    // consumers updated
    ConsumerImpl<?> consumer3 = Mockito.mock(ConsumerImpl.class);
    when(consumer3.getTopic()).thenReturn(TopicName.get("third").toString());
    consumersList.add(consumer3);
    Assert.assertNotNull(context.getConsumer("third", 0));
    try {
        // unknown partition
        context.getConsumer("third", 1);
        Assert.fail("Expected exception");
    } catch (PulsarClientException e) {
    // pass
    }
}
Also used : Consumer(org.apache.pulsar.client.api.Consumer) MultiTopicsConsumerImpl(org.apache.pulsar.client.impl.MultiTopicsConsumerImpl) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) InstanceStateManager(org.apache.pulsar.functions.instance.state.InstanceStateManager) EnvironmentBasedSecretsProvider(org.apache.pulsar.functions.secretsprovider.EnvironmentBasedSecretsProvider) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Test(org.testng.annotations.Test)

Example 4 with MultiTopicsConsumerImpl

use of org.apache.pulsar.client.impl.MultiTopicsConsumerImpl in project incubator-pulsar by apache.

the class ContextImplTest method testGetConsumerMultiTopic.

@Test
public void testGetConsumerMultiTopic() throws PulsarClientException {
    config.setExposePulsarAdminClientEnabled(false);
    context = new ContextImpl(config, logger, client, new EnvironmentBasedSecretsProvider(), FunctionCollectorRegistry.getDefaultImplementation(), new String[0], FunctionDetails.ComponentType.FUNCTION, null, new InstanceStateManager(), pulsarAdmin, clientBuilder);
    ConsumerImpl<?> consumer1 = Mockito.mock(ConsumerImpl.class);
    when(consumer1.getTopic()).thenReturn(TopicName.get("first").toString());
    ConsumerImpl<?> consumer2 = Mockito.mock(ConsumerImpl.class);
    when(consumer2.getTopic()).thenReturn(TopicName.get("second").toString());
    List<Consumer<?>> consumersList = Lists.newArrayList(consumer1, consumer2);
    MultiTopicsConsumerImpl mtc = Mockito.mock(MultiTopicsConsumerImpl.class);
    when(mtc.getConsumers()).thenReturn(consumersList);
    context.setInputConsumers(Lists.newArrayList(mtc));
    Assert.assertNotNull(context.getConsumer("first", 0));
    Assert.assertNotNull(context.getConsumer("second", 0));
    try {
        // nknown topic
        context.getConsumer("third", 0);
        Assert.fail("Expected exception");
    } catch (PulsarClientException e) {
    // pass
    }
    // consumers updated
    ConsumerImpl<?> consumer3 = Mockito.mock(ConsumerImpl.class);
    when(consumer3.getTopic()).thenReturn(TopicName.get("third").toString());
    consumersList.add(consumer3);
    Assert.assertNotNull(context.getConsumer("third", 0));
    try {
        // unknown partition
        context.getConsumer("third", 1);
        Assert.fail("Expected exception");
    } catch (PulsarClientException e) {
    // pass
    }
}
Also used : Consumer(org.apache.pulsar.client.api.Consumer) MultiTopicsConsumerImpl(org.apache.pulsar.client.impl.MultiTopicsConsumerImpl) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) InstanceStateManager(org.apache.pulsar.functions.instance.state.InstanceStateManager) EnvironmentBasedSecretsProvider(org.apache.pulsar.functions.secretsprovider.EnvironmentBasedSecretsProvider) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Test(org.testng.annotations.Test)

Example 5 with MultiTopicsConsumerImpl

use of org.apache.pulsar.client.impl.MultiTopicsConsumerImpl in project incubator-pulsar by apache.

the class PerformanceConsumer method main.

public static void main(String[] args) throws Exception {
    final Arguments arguments = new Arguments();
    JCommander jc = new JCommander(arguments);
    jc.setProgramName("pulsar-perf consume");
    try {
        jc.parse(args);
    } catch (ParameterException e) {
        System.out.println(e.getMessage());
        jc.usage();
        PerfClientUtils.exit(-1);
    }
    if (arguments.help) {
        jc.usage();
        PerfClientUtils.exit(-1);
    }
    if (isBlank(arguments.authPluginClassName) && !isBlank(arguments.deprecatedAuthPluginClassName)) {
        arguments.authPluginClassName = arguments.deprecatedAuthPluginClassName;
    }
    if (arguments.topic != null && arguments.topic.size() != arguments.numTopics) {
        // keep compatibility with the previous version
        if (arguments.topic.size() == 1) {
            String prefixTopicName = TopicName.get(arguments.topic.get(0)).toString().trim();
            List<String> defaultTopics = new ArrayList<>();
            for (int i = 0; i < arguments.numTopics; i++) {
                defaultTopics.add(String.format("%s-%d", prefixTopicName, i));
            }
            arguments.topic = defaultTopics;
        } else {
            System.out.println("The size of topics list should be equal to --num-topics");
            jc.usage();
            PerfClientUtils.exit(-1);
        }
    }
    if (arguments.subscriptionType == SubscriptionType.Exclusive && arguments.numConsumers > 1) {
        System.out.println("Only one consumer is allowed when subscriptionType is Exclusive");
        jc.usage();
        PerfClientUtils.exit(-1);
    }
    if (arguments.subscriptions != null && arguments.subscriptions.size() != arguments.numSubscriptions) {
        // keep compatibility with the previous version
        if (arguments.subscriptions.size() == 1) {
            if (arguments.subscriberName == null) {
                arguments.subscriberName = arguments.subscriptions.get(0);
            }
            List<String> defaultSubscriptions = new ArrayList<>();
            for (int i = 0; i < arguments.numSubscriptions; i++) {
                defaultSubscriptions.add(String.format("%s-%d", arguments.subscriberName, i));
            }
            arguments.subscriptions = defaultSubscriptions;
        } else {
            System.out.println("The size of subscriptions list should be equal to --num-subscriptions");
            jc.usage();
            PerfClientUtils.exit(-1);
        }
    }
    if (arguments.confFile != null) {
        Properties prop = new Properties(System.getProperties());
        prop.load(new FileInputStream(arguments.confFile));
        if (arguments.serviceURL == null) {
            arguments.serviceURL = prop.getProperty("brokerServiceUrl");
        }
        if (arguments.serviceURL == null) {
            arguments.serviceURL = prop.getProperty("webServiceUrl");
        }
        // fallback to previous-version serviceUrl property to maintain backward-compatibility
        if (arguments.serviceURL == null) {
            arguments.serviceURL = prop.getProperty("serviceUrl", "http://localhost:8080/");
        }
        if (arguments.authPluginClassName == null) {
            arguments.authPluginClassName = prop.getProperty("authPlugin", null);
        }
        if (arguments.authParams == null) {
            arguments.authParams = prop.getProperty("authParams", null);
        }
        if (isBlank(arguments.tlsTrustCertsFilePath)) {
            arguments.tlsTrustCertsFilePath = prop.getProperty("tlsTrustCertsFilePath", "");
        }
        if (arguments.tlsAllowInsecureConnection == null) {
            arguments.tlsAllowInsecureConnection = Boolean.parseBoolean(prop.getProperty("tlsAllowInsecureConnection", ""));
        }
    }
    // Dump config variables
    PerfClientUtils.printJVMInformation(log);
    ObjectMapper m = new ObjectMapper();
    ObjectWriter w = m.writerWithDefaultPrettyPrinter();
    log.info("Starting Pulsar performance consumer with config: {}", w.writeValueAsString(arguments));
    final Recorder qRecorder = arguments.autoScaledReceiverQueueSize ? new Recorder(arguments.receiverQueueSize, 5) : null;
    final RateLimiter limiter = arguments.rate > 0 ? RateLimiter.create(arguments.rate) : null;
    long startTime = System.nanoTime();
    long testEndTime = startTime + (long) (arguments.testTime * 1e9);
    ClientBuilder clientBuilder = // 
    PulsarClient.builder().enableTransaction(arguments.isEnableTransaction).serviceUrl(// 
    arguments.serviceURL).connectionsPerBroker(// 
    arguments.maxConnections).statsInterval(arguments.statsIntervalSeconds, // 
    TimeUnit.SECONDS).ioThreads(// 
    arguments.ioThreads).listenerThreads(arguments.listenerThreads).enableBusyWait(arguments.enableBusyWait).tlsTrustCertsFilePath(arguments.tlsTrustCertsFilePath);
    if (isNotBlank(arguments.authPluginClassName)) {
        clientBuilder.authentication(arguments.authPluginClassName, arguments.authParams);
    }
    if (arguments.tlsAllowInsecureConnection != null) {
        clientBuilder.allowTlsInsecureConnection(arguments.tlsAllowInsecureConnection);
    }
    if (isNotBlank(arguments.listenerName)) {
        clientBuilder.listenerName(arguments.listenerName);
    }
    PulsarClient pulsarClient = clientBuilder.build();
    AtomicReference<Transaction> atomicReference;
    if (arguments.isEnableTransaction) {
        atomicReference = new AtomicReference<>(pulsarClient.newTransaction().withTransactionTimeout(arguments.transactionTimeout, TimeUnit.SECONDS).build().get());
    } else {
        atomicReference = new AtomicReference<>(null);
    }
    AtomicLong messageAckedCount = new AtomicLong();
    Semaphore messageReceiveLimiter = new Semaphore(arguments.numMessagesPerTransaction);
    Thread thread = Thread.currentThread();
    MessageListener<ByteBuffer> listener = (consumer, msg) -> {
        if (arguments.testTime > 0) {
            if (System.nanoTime() > testEndTime) {
                log.info("------------------- DONE -----------------------");
                PerfClientUtils.exit(0);
                thread.interrupt();
            }
        }
        if (arguments.totalNumTxn > 0) {
            if (totalEndTxnOpFailNum.sum() + totalEndTxnOpSuccessNum.sum() >= arguments.totalNumTxn) {
                log.info("------------------- DONE -----------------------");
                PerfClientUtils.exit(0);
                thread.interrupt();
            }
        }
        if (qRecorder != null) {
            qRecorder.recordValue(((ConsumerBase<?>) consumer).getTotalIncomingMessages());
        }
        messagesReceived.increment();
        bytesReceived.add(msg.size());
        totalMessagesReceived.increment();
        totalBytesReceived.add(msg.size());
        if (limiter != null) {
            limiter.acquire();
        }
        long latencyMillis = System.currentTimeMillis() - msg.getPublishTime();
        if (latencyMillis >= 0) {
            recorder.recordValue(latencyMillis);
            cumulativeRecorder.recordValue(latencyMillis);
        }
        if (arguments.isEnableTransaction) {
            try {
                messageReceiveLimiter.acquire();
            } catch (InterruptedException e) {
                log.error("Got error: ", e);
            }
            consumer.acknowledgeAsync(msg.getMessageId(), atomicReference.get()).thenRun(() -> {
                totalMessageAck.increment();
                messageAck.increment();
            }).exceptionally(throwable -> {
                log.error("Ack message {} failed with exception", msg, throwable);
                totalMessageAckFailed.increment();
                return null;
            });
        } else {
            consumer.acknowledgeAsync(msg).thenRun(() -> {
                totalMessageAck.increment();
                messageAck.increment();
            }).exceptionally(throwable -> {
                log.error("Ack message {} failed with exception", msg, throwable);
                totalMessageAckFailed.increment();
                return null;
            });
        }
        if (arguments.poolMessages) {
            msg.release();
        }
        if (arguments.isEnableTransaction && messageAckedCount.incrementAndGet() == arguments.numMessagesPerTransaction) {
            Transaction transaction = atomicReference.get();
            if (!arguments.isAbortTransaction) {
                transaction.commit().thenRun(() -> {
                    if (log.isDebugEnabled()) {
                        log.debug("Commit transaction {}", transaction.getTxnID());
                    }
                    totalEndTxnOpSuccessNum.increment();
                    numTxnOpSuccess.increment();
                }).exceptionally(exception -> {
                    log.error("Commit transaction failed with exception : ", exception);
                    totalEndTxnOpFailNum.increment();
                    return null;
                });
            } else {
                transaction.abort().thenRun(() -> {
                    if (log.isDebugEnabled()) {
                        log.debug("Abort transaction {}", transaction.getTxnID());
                    }
                    totalEndTxnOpSuccessNum.increment();
                    numTxnOpSuccess.increment();
                }).exceptionally(exception -> {
                    log.error("Abort transaction {} failed with exception", transaction.getTxnID().toString(), exception);
                    totalEndTxnOpFailNum.increment();
                    return null;
                });
            }
            while (true) {
                try {
                    Transaction newTransaction = pulsarClient.newTransaction().withTransactionTimeout(arguments.transactionTimeout, TimeUnit.SECONDS).build().get();
                    atomicReference.compareAndSet(transaction, newTransaction);
                    totalNumTxnOpenSuccess.increment();
                    messageAckedCount.set(0);
                    messageReceiveLimiter.release(arguments.numMessagesPerTransaction);
                    break;
                } catch (Exception e) {
                    log.error("Failed to new transaction with exception:", e);
                    totalNumTxnOpenFail.increment();
                }
            }
        }
    };
    List<Future<Consumer<ByteBuffer>>> futures = new ArrayList<>();
    ConsumerBuilder<ByteBuffer> consumerBuilder = // 
    pulsarClient.newConsumer(Schema.BYTEBUFFER).messageListener(// 
    listener).receiverQueueSize(// 
    arguments.receiverQueueSize).maxTotalReceiverQueueSizeAcrossPartitions(arguments.maxTotalReceiverQueueSizeAcrossPartitions).acknowledgmentGroupTime(arguments.acknowledgmentsGroupingDelayMillis, // 
    TimeUnit.MILLISECONDS).subscriptionType(arguments.subscriptionType).subscriptionInitialPosition(arguments.subscriptionInitialPosition).autoAckOldestChunkedMessageOnQueueFull(arguments.autoAckOldestChunkedMessageOnQueueFull).enableBatchIndexAcknowledgment(arguments.batchIndexAck).poolMessages(arguments.poolMessages).replicateSubscriptionState(arguments.replicatedSubscription).autoScaledReceiverQueueSizeEnabled(arguments.autoScaledReceiverQueueSize);
    if (arguments.maxPendingChunkedMessage > 0) {
        consumerBuilder.maxPendingChunkedMessage(arguments.maxPendingChunkedMessage);
    }
    if (arguments.expireTimeOfIncompleteChunkedMessageMs > 0) {
        consumerBuilder.expireTimeOfIncompleteChunkedMessage(arguments.expireTimeOfIncompleteChunkedMessageMs, TimeUnit.MILLISECONDS);
    }
    if (isNotBlank(arguments.encKeyFile)) {
        consumerBuilder.defaultCryptoKeyReader(arguments.encKeyFile);
    }
    for (int i = 0; i < arguments.numTopics; i++) {
        final TopicName topicName = TopicName.get(arguments.topic.get(i));
        log.info("Adding {} consumers per subscription on topic {}", arguments.numConsumers, topicName);
        for (int j = 0; j < arguments.numSubscriptions; j++) {
            String subscriberName = arguments.subscriptions.get(j);
            for (int k = 0; k < arguments.numConsumers; k++) {
                futures.add(consumerBuilder.clone().topic(topicName.toString()).subscriptionName(subscriberName).subscribeAsync());
            }
        }
    }
    for (Future<Consumer<ByteBuffer>> future : futures) {
        future.get();
    }
    log.info("Start receiving from {} consumers per subscription on {} topics", arguments.numConsumers, arguments.numTopics);
    long start = System.nanoTime();
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
        printAggregatedThroughput(start, arguments);
        printAggregatedStats();
    }));
    long oldTime = System.nanoTime();
    Histogram reportHistogram = null;
    Histogram qHistogram = null;
    HistogramLogWriter histogramLogWriter = null;
    if (arguments.histogramFile != null) {
        String statsFileName = arguments.histogramFile;
        log.info("Dumping latency stats to {}", statsFileName);
        PrintStream histogramLog = new PrintStream(new FileOutputStream(statsFileName), false);
        histogramLogWriter = new HistogramLogWriter(histogramLog);
        // Some log header bits
        histogramLogWriter.outputLogFormatVersion();
        histogramLogWriter.outputLegend();
    }
    while (true) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            break;
        }
        long now = System.nanoTime();
        double elapsed = (now - oldTime) / 1e9;
        long total = totalMessagesReceived.sum();
        double rate = messagesReceived.sumThenReset() / elapsed;
        double throughput = bytesReceived.sumThenReset() / elapsed * 8 / 1024 / 1024;
        double rateAck = messageAck.sumThenReset() / elapsed;
        long totalTxnOpSuccessNum = 0;
        long totalTxnOpFailNum = 0;
        double rateOpenTxn = 0;
        reportHistogram = recorder.getIntervalHistogram(reportHistogram);
        if (arguments.isEnableTransaction) {
            totalTxnOpSuccessNum = totalEndTxnOpSuccessNum.sum();
            totalTxnOpFailNum = totalEndTxnOpFailNum.sum();
            rateOpenTxn = numTxnOpSuccess.sumThenReset() / elapsed;
            log.info("--- Transaction: {} transaction end successfully --- {} transaction end failed " + "--- {}  Txn/s --- AckRate: {} msg/s", totalTxnOpSuccessNum, totalTxnOpFailNum, dec.format(rateOpenTxn), dec.format(rateAck));
        }
        log.info("Throughput received: {} msg --- {}  msg/s --- {} Mbit/s  " + "--- Latency: mean: {} ms - med: {} " + "- 95pct: {} - 99pct: {} - 99.9pct: {} - 99.99pct: {} - Max: {}", intFormat.format(total), dec.format(rate), dec.format(throughput), dec.format(reportHistogram.getMean()), reportHistogram.getValueAtPercentile(50), reportHistogram.getValueAtPercentile(95), reportHistogram.getValueAtPercentile(99), reportHistogram.getValueAtPercentile(99.9), reportHistogram.getValueAtPercentile(99.99), reportHistogram.getMaxValue());
        if (arguments.autoScaledReceiverQueueSize && log.isDebugEnabled() && qRecorder != null) {
            qHistogram = qRecorder.getIntervalHistogram(qHistogram);
            log.debug("ReceiverQueueUsage: cnt={},mean={}, min={},max={},25pct={},50pct={},75pct={}", qHistogram.getTotalCount(), dec.format(qHistogram.getMean()), qHistogram.getMinValue(), qHistogram.getMaxValue(), qHistogram.getValueAtPercentile(25), qHistogram.getValueAtPercentile(50), qHistogram.getValueAtPercentile(75));
            qHistogram.reset();
            for (Future<Consumer<ByteBuffer>> future : futures) {
                ConsumerBase<?> consumerBase = (ConsumerBase<?>) future.get();
                log.debug("[{}] CurrentReceiverQueueSize={}", consumerBase.getConsumerName(), consumerBase.getCurrentReceiverQueueSize());
                if (consumerBase instanceof MultiTopicsConsumerImpl) {
                    for (ConsumerImpl<?> consumer : ((MultiTopicsConsumerImpl<?>) consumerBase).getConsumers()) {
                        log.debug("[{}] SubConsumer.CurrentReceiverQueueSize={}", consumer.getConsumerName(), consumer.getCurrentReceiverQueueSize());
                    }
                }
            }
        }
        if (histogramLogWriter != null) {
            histogramLogWriter.outputIntervalHistogram(reportHistogram);
        }
        reportHistogram.reset();
        oldTime = now;
    }
    pulsarClient.close();
}
Also used : LongAdder(java.util.concurrent.atomic.LongAdder) Parameters(com.beust.jcommander.Parameters) ParameterException(com.beust.jcommander.ParameterException) TopicName(org.apache.pulsar.common.naming.TopicName) Parameter(com.beust.jcommander.Parameter) LoggerFactory(org.slf4j.LoggerFactory) ConsumerBuilder(org.apache.pulsar.client.api.ConsumerBuilder) HistogramLogWriter(org.HdrHistogram.HistogramLogWriter) SubscriptionInitialPosition(org.apache.pulsar.client.api.SubscriptionInitialPosition) RateLimiter(com.google.common.util.concurrent.RateLimiter) AtomicReference(java.util.concurrent.atomic.AtomicReference) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) Future(java.util.concurrent.Future) Recorder(org.HdrHistogram.Recorder) PulsarClient(org.apache.pulsar.client.api.PulsarClient) PrintStream(java.io.PrintStream) Properties(java.util.Properties) ConsumerImpl(org.apache.pulsar.client.impl.ConsumerImpl) Logger(org.slf4j.Logger) ObjectWriter(com.fasterxml.jackson.databind.ObjectWriter) Semaphore(java.util.concurrent.Semaphore) MessageListener(org.apache.pulsar.client.api.MessageListener) JCommander(com.beust.jcommander.JCommander) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) DecimalFormat(java.text.DecimalFormat) FileOutputStream(java.io.FileOutputStream) PaddingDecimalFormat(org.apache.pulsar.testclient.utils.PaddingDecimalFormat) FileInputStream(java.io.FileInputStream) SubscriptionType(org.apache.pulsar.client.api.SubscriptionType) Transaction(org.apache.pulsar.client.api.transaction.Transaction) Schema(org.apache.pulsar.client.api.Schema) TimeUnit(java.util.concurrent.TimeUnit) Histogram(org.HdrHistogram.Histogram) AtomicLong(java.util.concurrent.atomic.AtomicLong) Consumer(org.apache.pulsar.client.api.Consumer) ConsumerBase(org.apache.pulsar.client.impl.ConsumerBase) List(java.util.List) StringUtils.isNotBlank(org.apache.commons.lang3.StringUtils.isNotBlank) StringUtils.isBlank(org.apache.commons.lang3.StringUtils.isBlank) ClientBuilder(org.apache.pulsar.client.api.ClientBuilder) Collections(java.util.Collections) MultiTopicsConsumerImpl(org.apache.pulsar.client.impl.MultiTopicsConsumerImpl) Histogram(org.HdrHistogram.Histogram) ArrayList(java.util.ArrayList) Semaphore(java.util.concurrent.Semaphore) Properties(java.util.Properties) Consumer(org.apache.pulsar.client.api.Consumer) JCommander(com.beust.jcommander.JCommander) MultiTopicsConsumerImpl(org.apache.pulsar.client.impl.MultiTopicsConsumerImpl) ParameterException(com.beust.jcommander.ParameterException) PulsarClient(org.apache.pulsar.client.api.PulsarClient) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) ClientBuilder(org.apache.pulsar.client.api.ClientBuilder) HistogramLogWriter(org.HdrHistogram.HistogramLogWriter) PrintStream(java.io.PrintStream) ConsumerBase(org.apache.pulsar.client.impl.ConsumerBase) ObjectWriter(com.fasterxml.jackson.databind.ObjectWriter) Recorder(org.HdrHistogram.Recorder) ByteBuffer(java.nio.ByteBuffer) FileInputStream(java.io.FileInputStream) RateLimiter(com.google.common.util.concurrent.RateLimiter) ParameterException(com.beust.jcommander.ParameterException) TopicName(org.apache.pulsar.common.naming.TopicName) AtomicLong(java.util.concurrent.atomic.AtomicLong) Transaction(org.apache.pulsar.client.api.transaction.Transaction) FileOutputStream(java.io.FileOutputStream) Future(java.util.concurrent.Future)

Aggregations

MultiTopicsConsumerImpl (org.apache.pulsar.client.impl.MultiTopicsConsumerImpl)8 Test (org.testng.annotations.Test)6 Consumer (org.apache.pulsar.client.api.Consumer)5 TopicName (org.apache.pulsar.common.naming.TopicName)5 PulsarAdminException (org.apache.pulsar.client.admin.PulsarAdminException)3 PulsarClientException (org.apache.pulsar.client.api.PulsarClientException)3 JCommander (com.beust.jcommander.JCommander)2 Parameter (com.beust.jcommander.Parameter)2 ParameterException (com.beust.jcommander.ParameterException)2 Parameters (com.beust.jcommander.Parameters)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)2 ObjectWriter (com.fasterxml.jackson.databind.ObjectWriter)2 RateLimiter (com.google.common.util.concurrent.RateLimiter)2 FileInputStream (java.io.FileInputStream)2 FileOutputStream (java.io.FileOutputStream)2 PrintStream (java.io.PrintStream)2 ByteBuffer (java.nio.ByteBuffer)2 DecimalFormat (java.text.DecimalFormat)2 ArrayList (java.util.ArrayList)2 Collections (java.util.Collections)2