Search in sources :

Example 11 with Consumer

use of org.apache.pulsar.broker.service.Consumer in project incubator-pulsar by apache.

the class CompactorSubscription method acknowledgeMessage.

@Override
public void acknowledgeMessage(PositionImpl position, AckType ackType, Map<String, Long> properties) {
    checkArgument(ackType == AckType.Cumulative);
    checkArgument(properties.containsKey(Compactor.COMPACTED_TOPIC_LEDGER_PROPERTY));
    long compactedLedgerId = properties.get(Compactor.COMPACTED_TOPIC_LEDGER_PROPERTY);
    if (log.isDebugEnabled()) {
        log.debug("[{}][{}] Cumulative ack on compactor subscription {}", topicName, subName, position);
    }
    CompletableFuture<Void> future = new CompletableFuture<>();
    cursor.asyncMarkDelete(position, properties, new MarkDeleteCallback() {

        @Override
        public void markDeleteComplete(Object ctx) {
            if (log.isDebugEnabled()) {
                log.debug("[{}][{}] Mark deleted messages until position on compactor subscription {}", topicName, subName, position);
            }
            future.complete(null);
        }

        @Override
        public void markDeleteFailed(ManagedLedgerException exception, Object ctx) {
            // TODO: cut consumer connection on markDeleteFailed
            if (log.isDebugEnabled()) {
                log.debug("[{}][{}] Failed to mark delete for position on compactor subscription {}", topicName, subName, ctx, exception);
            }
        }
    }, null);
    if (topic.getManagedLedger().isTerminated() && cursor.getNumberOfEntriesInBacklog() == 0) {
        // Notify all consumer that the end of topic was reached
        dispatcher.getConsumers().forEach(Consumer::reachedEndOfTopic);
    }
    // Once properties have been persisted, we can notify the compacted topic to use
    // the new ledger
    future.thenAccept((v) -> compactedTopic.newCompactedLedger(position, compactedLedgerId));
}
Also used : MarkDeleteCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback) CompletableFuture(java.util.concurrent.CompletableFuture) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) Consumer(org.apache.pulsar.broker.service.Consumer)

Example 12 with Consumer

use of org.apache.pulsar.broker.service.Consumer in project incubator-pulsar by apache.

the class PersistentDispatcherMultipleConsumers method readEntriesComplete.

@Override
public synchronized void readEntriesComplete(List<Entry> entries, Object ctx) {
    ReadType readType = (ReadType) ctx;
    int start = 0;
    int entriesToDispatch = entries.size();
    if (readType == ReadType.Normal) {
        havePendingRead = false;
    } else {
        havePendingReplayRead = false;
    }
    if (readBatchSize < MaxReadBatchSize) {
        int newReadBatchSize = Math.min(readBatchSize * 2, MaxReadBatchSize);
        if (log.isDebugEnabled()) {
            log.debug("[{}] Increasing read batch size from {} to {}", name, readBatchSize, newReadBatchSize);
        }
        readBatchSize = newReadBatchSize;
    }
    readFailureBackoff.reduceToHalf();
    if (shouldRewindBeforeReadingOrReplaying && readType == ReadType.Normal) {
        // All consumers got disconnected before the completion of the read operation
        entries.forEach(Entry::release);
        cursor.rewind();
        shouldRewindBeforeReadingOrReplaying = false;
        readMoreEntries();
        return;
    }
    if (log.isDebugEnabled()) {
        log.debug("[{}] Distributing {} messages to {} consumers", name, entries.size(), consumerList.size());
    }
    long totalMessagesSent = 0;
    long totalBytesSent = 0;
    while (entriesToDispatch > 0 && totalAvailablePermits > 0 && isAtleastOneConsumerAvailable()) {
        Consumer c = getNextConsumer();
        if (c == null) {
            // Do nothing, cursor will be rewind at reconnection
            log.info("[{}] rewind because no available consumer found from total {}", name, consumerList.size());
            entries.subList(start, entries.size()).forEach(Entry::release);
            cursor.rewind();
            return;
        }
        // round-robin dispatch batch size for this consumer
        int messagesForC = Math.min(Math.min(entriesToDispatch, c.getAvailablePermits()), MaxRoundRobinBatchSize);
        if (messagesForC > 0) {
            // remove positions first from replay list first : sendMessages recycles entries
            if (readType == ReadType.Replay) {
                entries.subList(start, start + messagesForC).forEach(entry -> {
                    messagesToReplay.remove(entry.getLedgerId(), entry.getEntryId());
                });
            }
            SendMessageInfo sentMsgInfo = c.sendMessages(entries.subList(start, start + messagesForC));
            long msgSent = sentMsgInfo.getTotalSentMessages();
            start += messagesForC;
            entriesToDispatch -= messagesForC;
            totalAvailablePermits -= msgSent;
            totalMessagesSent += sentMsgInfo.getTotalSentMessages();
            totalBytesSent += sentMsgInfo.getTotalSentMessageBytes();
        }
    }
    // acquire message-dispatch permits for already delivered messages
    if (serviceConfig.isDispatchThrottlingOnNonBacklogConsumerEnabled() || !cursor.isActive()) {
        topic.getDispatchRateLimiter().tryDispatchPermit(totalMessagesSent, totalBytesSent);
    }
    if (entriesToDispatch > 0) {
        if (log.isDebugEnabled()) {
            log.debug("[{}] No consumers found with available permits, storing {} positions for later replay", name, entries.size() - start);
        }
        entries.subList(start, entries.size()).forEach(entry -> {
            messagesToReplay.add(entry.getLedgerId(), entry.getEntryId());
            entry.release();
        });
    }
    readMoreEntries();
}
Also used : Entry(org.apache.bookkeeper.mledger.Entry) SendMessageInfo(org.apache.pulsar.broker.service.Consumer.SendMessageInfo) Consumer(org.apache.pulsar.broker.service.Consumer)

Example 13 with Consumer

use of org.apache.pulsar.broker.service.Consumer in project incubator-pulsar by apache.

the class PersistentDispatcherSingleActiveConsumer method readMoreEntries.

@Override
protected void readMoreEntries(Consumer consumer) {
    // so skip reading more entries if currently there is no active consumer.
    if (null == consumer) {
        return;
    }
    int availablePermits = consumer.getAvailablePermits();
    if (availablePermits > 0) {
        if (!consumer.isWritable()) {
            // If the connection is not currently writable, we issue the read request anyway, but for a single
            // message. The intent here is to keep use the request as a notification mechanism while avoiding to
            // read and dispatch a big batch of messages which will need to wait before getting written to the
            // socket.
            availablePermits = 1;
        }
        int messagesToRead = Math.min(availablePermits, readBatchSize);
        // threshold: then schedule the read after MESSAGE_RATE_BACKOFF_MS
        if (serviceConfig.isDispatchThrottlingOnNonBacklogConsumerEnabled() || !cursor.isActive()) {
            DispatchRateLimiter rateLimiter = topic.getDispatchRateLimiter();
            if (rateLimiter.isDispatchRateLimitingEnabled()) {
                if (!rateLimiter.hasMessageDispatchPermit()) {
                    if (log.isDebugEnabled()) {
                        log.debug("[{}] message-read exceeded message-rate {}/{}, schedule after a {}", name, rateLimiter.getDispatchRateOnMsg(), rateLimiter.getDispatchRateOnByte(), MESSAGE_RATE_BACKOFF_MS);
                    }
                    topic.getBrokerService().executor().schedule(() -> {
                        Consumer currentConsumer = ACTIVE_CONSUMER_UPDATER.get(this);
                        if (currentConsumer != null && !havePendingRead) {
                            readMoreEntries(currentConsumer);
                        } else {
                            if (log.isDebugEnabled()) {
                                log.info("[{}] Skipping read retry: Current Consumer {}, havePendingRead {}", topic.getName(), currentConsumer, havePendingRead);
                            }
                        }
                    }, MESSAGE_RATE_BACKOFF_MS, TimeUnit.MILLISECONDS);
                    return;
                } else {
                    // if dispatch-rate is in msg then read only msg according to available permit
                    long availablePermitsOnMsg = rateLimiter.getAvailableDispatchRateLimitOnMsg();
                    if (availablePermitsOnMsg > 0) {
                        messagesToRead = Math.min(messagesToRead, (int) availablePermitsOnMsg);
                    }
                }
            }
        }
        // Schedule read
        if (log.isDebugEnabled()) {
            log.debug("[{}-{}] Schedule read of {} messages", name, consumer, messagesToRead);
        }
        havePendingRead = true;
        if (consumer.readCompacted()) {
            topic.compactedTopic.asyncReadEntriesOrWait(cursor, messagesToRead, this, consumer);
        } else {
            cursor.asyncReadEntriesOrWait(messagesToRead, this, consumer);
        }
    } else {
        if (log.isDebugEnabled()) {
            log.debug("[{}-{}] Consumer buffer is full, pause reading", name, consumer);
        }
    }
}
Also used : Consumer(org.apache.pulsar.broker.service.Consumer) AbstractDispatcherSingleActiveConsumer(org.apache.pulsar.broker.service.AbstractDispatcherSingleActiveConsumer)

Example 14 with Consumer

use of org.apache.pulsar.broker.service.Consumer in project incubator-pulsar by apache.

the class PersistentDispatcherSingleActiveConsumer method readEntriesComplete.

@Override
public synchronized void readEntriesComplete(final List<Entry> entries, Object obj) {
    Consumer readConsumer = (Consumer) obj;
    if (log.isDebugEnabled()) {
        log.debug("[{}-{}] Got messages: {}", name, readConsumer, entries.size());
    }
    havePendingRead = false;
    if (readBatchSize < MaxReadBatchSize) {
        int newReadBatchSize = Math.min(readBatchSize * 2, MaxReadBatchSize);
        if (log.isDebugEnabled()) {
            log.debug("[{}-{}] Increasing read batch size from {} to {}", name, readConsumer, readBatchSize, newReadBatchSize);
        }
        readBatchSize = newReadBatchSize;
    }
    readFailureBackoff.reduceToHalf();
    Consumer currentConsumer = ACTIVE_CONSUMER_UPDATER.get(this);
    if (currentConsumer == null || readConsumer != currentConsumer) {
        // re-issue the read request for the new consumer
        if (log.isDebugEnabled()) {
            log.debug("[{}] rewind because no available consumer found", name);
        }
        entries.forEach(Entry::release);
        cursor.rewind();
        if (currentConsumer != null) {
            readMoreEntries(currentConsumer);
        }
    } else {
        SendMessageInfo sentMsgInfo = currentConsumer.sendMessages(entries);
        final long totalMessagesSent = sentMsgInfo.getTotalSentMessages();
        final long totalBytesSent = sentMsgInfo.getTotalSentMessageBytes();
        sentMsgInfo.getChannelPromse().addListener(future -> {
            if (future.isSuccess()) {
                // acquire message-dispatch permits for already delivered messages
                if (serviceConfig.isDispatchThrottlingOnNonBacklogConsumerEnabled() || !cursor.isActive()) {
                    topic.getDispatchRateLimiter().tryDispatchPermit(totalMessagesSent, totalBytesSent);
                }
                // Schedule a new read batch operation only after the previous batch has been written to the socket
                synchronized (PersistentDispatcherSingleActiveConsumer.this) {
                    Consumer newConsumer = ACTIVE_CONSUMER_UPDATER.get(this);
                    if (newConsumer != null && !havePendingRead) {
                        readMoreEntries(newConsumer);
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("[{}-{}] Ignoring write future complete. consumerAvailable={} havePendingRead={}", name, newConsumer, newConsumer != null, havePendingRead);
                        }
                    }
                }
            }
        });
    }
}
Also used : Entry(org.apache.bookkeeper.mledger.Entry) SendMessageInfo(org.apache.pulsar.broker.service.Consumer.SendMessageInfo) Consumer(org.apache.pulsar.broker.service.Consumer) AbstractDispatcherSingleActiveConsumer(org.apache.pulsar.broker.service.AbstractDispatcherSingleActiveConsumer)

Example 15 with Consumer

use of org.apache.pulsar.broker.service.Consumer in project incubator-pulsar by apache.

the class PersistentDispatcherSingleActiveConsumer method readEntriesFailed.

@Override
public synchronized void readEntriesFailed(ManagedLedgerException exception, Object ctx) {
    havePendingRead = false;
    Consumer c = (Consumer) ctx;
    long waitTimeMillis = readFailureBackoff.next();
    if (exception instanceof NoMoreEntriesToReadException) {
        if (cursor.getNumberOfEntriesInBacklog() == 0) {
            // Topic has been terminated and there are no more entries to read
            // Notify the consumer only if all the messages were already acknowledged
            consumers.forEach(Consumer::reachedEndOfTopic);
        }
    } else if (!(exception instanceof TooManyRequestsException)) {
        log.error("[{}-{}] Error reading entries at {} : {} - Retrying to read in {} seconds", name, c, cursor.getReadPosition(), exception.getMessage(), waitTimeMillis / 1000.0);
    } else {
        if (log.isDebugEnabled()) {
            log.debug("[{}-{}] Got throttled by bookies while reading at {} : {} - Retrying to read in {} seconds", name, c, cursor.getReadPosition(), exception.getMessage(), waitTimeMillis / 1000.0);
        }
    }
    checkNotNull(c);
    // Reduce read batch size to avoid flooding bookies with retries
    readBatchSize = 1;
    topic.getBrokerService().executor().schedule(() -> {
        synchronized (PersistentDispatcherSingleActiveConsumer.this) {
            Consumer currentConsumer = ACTIVE_CONSUMER_UPDATER.get(this);
            // we should retry the read if we have an active consumer and there is no pending read
            if (currentConsumer != null && !havePendingRead) {
                if (log.isDebugEnabled()) {
                    log.debug("[{}-{}] Retrying read operation", name, c);
                }
                readMoreEntries(currentConsumer);
            } else {
                log.info("[{}-{}] Skipping read retry: Current Consumer {}, havePendingRead {}", name, c, currentConsumer, havePendingRead);
            }
        }
    }, waitTimeMillis, TimeUnit.MILLISECONDS);
}
Also used : NoMoreEntriesToReadException(org.apache.bookkeeper.mledger.ManagedLedgerException.NoMoreEntriesToReadException) TooManyRequestsException(org.apache.bookkeeper.mledger.ManagedLedgerException.TooManyRequestsException) Consumer(org.apache.pulsar.broker.service.Consumer) AbstractDispatcherSingleActiveConsumer(org.apache.pulsar.broker.service.AbstractDispatcherSingleActiveConsumer)

Aggregations

Consumer (org.apache.pulsar.broker.service.Consumer)20 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)6 ConsumerBusyException (org.apache.pulsar.broker.service.BrokerServiceException.ConsumerBusyException)6 AbstractDispatcherSingleActiveConsumer (org.apache.pulsar.broker.service.AbstractDispatcherSingleActiveConsumer)5 BrokerServiceException (org.apache.pulsar.broker.service.BrokerServiceException)5 NamingException (org.apache.pulsar.broker.service.BrokerServiceException.NamingException)5 NotAllowedException (org.apache.pulsar.broker.service.BrokerServiceException.NotAllowedException)5 SubscriptionBusyException (org.apache.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException)5 TopicFencedException (org.apache.pulsar.broker.service.BrokerServiceException.TopicFencedException)5 UnsupportedVersionException (org.apache.pulsar.broker.service.BrokerServiceException.UnsupportedVersionException)5 CompletableFuture (java.util.concurrent.CompletableFuture)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 CyclicBarrier (java.util.concurrent.CyclicBarrier)4 Entry (org.apache.bookkeeper.mledger.Entry)4 ProducerBusyException (org.apache.pulsar.broker.service.BrokerServiceException.ProducerBusyException)4 ServerMetadataException (org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException)4 TopicBusyException (org.apache.pulsar.broker.service.BrokerServiceException.TopicBusyException)4 PersistentSubscription (org.apache.pulsar.broker.service.persistent.PersistentSubscription)4 PersistentTopic (org.apache.pulsar.broker.service.persistent.PersistentTopic)4 PulsarApi (org.apache.pulsar.common.api.proto.PulsarApi)4