提交 467ffab1 编写于 作者: M Matteo Merli 提交者: 冉小龙

Efficiency improvements for delay delivery tracker (#5498)

Efficiency improvements for delay delivery tracker
上级 418362e1
...@@ -71,8 +71,12 @@ public class InMemoryDelayedDeliveryTracker implements DelayedDeliveryTracker, T ...@@ -71,8 +71,12 @@ public class InMemoryDelayedDeliveryTracker implements DelayedDeliveryTracker, T
log.debug("[{}] Add message {}:{} -- Delivery in {} ms ", dispatcher.getName(), ledgerId, entryId, log.debug("[{}] Add message {}:{} -- Delivery in {} ms ", dispatcher.getName(), ledgerId, entryId,
deliveryAt - now); deliveryAt - now);
} }
if (deliveryAt < now) { if (deliveryAt < (now + tickTimeMillis)) {
// It's already about time to deliver this message // It's already about time to deliver this message. We add the buffer of
// `tickTimeMillis` because messages can be extracted from the tracker
// slightly before the expiration time. We don't want the messages to
// go back into the delay tracker (for a brief amount of time) when we're
// trying to dispatch to the consumer.
return false; return false;
} }
...@@ -117,7 +121,7 @@ public class InMemoryDelayedDeliveryTracker implements DelayedDeliveryTracker, T ...@@ -117,7 +121,7 @@ public class InMemoryDelayedDeliveryTracker implements DelayedDeliveryTracker, T
} }
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("[{}] Get scheduled messags - found {}", dispatcher.getName(), positions.size()); log.debug("[{}] Get scheduled messages - found {}", dispatcher.getName(), positions.size());
} }
updateTimer(); updateTimer();
return positions; return positions;
...@@ -170,7 +174,7 @@ public class InMemoryDelayedDeliveryTracker implements DelayedDeliveryTracker, T ...@@ -170,7 +174,7 @@ public class InMemoryDelayedDeliveryTracker implements DelayedDeliveryTracker, T
@Override @Override
public void run(Timeout timeout) throws Exception { public void run(Timeout timeout) throws Exception {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.info("[{}] Timer triggered", dispatcher.getName()); log.debug("[{}] Timer triggered", dispatcher.getName());
} }
if (timeout.isCancelled()) { if (timeout.isCancelled()) {
return; return;
......
...@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit; ...@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import com.google.common.collect.Range; import com.google.common.collect.Range;
import org.apache.bookkeeper.mledger.AsyncCallbacks.ReadEntriesCallback; import org.apache.bookkeeper.mledger.AsyncCallbacks.ReadEntriesCallback;
import org.apache.bookkeeper.mledger.Entry; import org.apache.bookkeeper.mledger.Entry;
import org.apache.bookkeeper.mledger.ManagedCursor; import org.apache.bookkeeper.mledger.ManagedCursor;
...@@ -715,25 +716,28 @@ public class PersistentDispatcherMultipleConsumers extends AbstractDispatcherMul ...@@ -715,25 +716,28 @@ public class PersistentDispatcherMultipleConsumers extends AbstractDispatcherMul
} }
@Override @Override
public synchronized boolean trackDelayedDelivery(long ledgerId, long entryId, MessageMetadata msgMetadata) { public boolean trackDelayedDelivery(long ledgerId, long entryId, MessageMetadata msgMetadata) {
if (!isDelayedDeliveryEnabled) { if (!isDelayedDeliveryEnabled) {
// If broker has the feature disabled, always deliver messages immediately // If broker has the feature disabled, always deliver messages immediately
return false; return false;
} }
if (!delayedDeliveryTracker.isPresent()) { synchronized (this) {
// Initialize the tracker the first time we need to use it if (!delayedDeliveryTracker.isPresent()) {
delayedDeliveryTracker = Optional.of(topic.getBrokerService().getDelayedDeliveryTrackerFactory().newTracker(this)); // Initialize the tracker the first time we need to use it
} delayedDeliveryTracker = Optional
.of(topic.getBrokerService().getDelayedDeliveryTrackerFactory().newTracker(this));
}
return delayedDeliveryTracker.get().addMessage(ledgerId, entryId, msgMetadata.getDeliverAtTime()); return delayedDeliveryTracker.get().addMessage(ledgerId, entryId, msgMetadata.getDeliverAtTime());
}
} }
private synchronized Set<PositionImpl> getMessagesToReplayNow(int maxMessagesToRead) { private synchronized Set<PositionImpl> getMessagesToReplayNow(int maxMessagesToRead) {
if (!messagesToRedeliver.isEmpty()) { if (!messagesToRedeliver.isEmpty()) {
return messagesToRedeliver.items(maxMessagesToRead, return messagesToRedeliver.items(maxMessagesToRead,
(ledgerId, entryId) -> new PositionImpl(ledgerId, entryId)); (ledgerId, entryId) -> new PositionImpl(ledgerId, entryId));
} else if (delayedDeliveryTracker.isPresent()) { } else if (delayedDeliveryTracker.isPresent() && delayedDeliveryTracker.get().hasMessageAvailable()) {
return delayedDeliveryTracker.get().getScheduledMessages(maxMessagesToRead); return delayedDeliveryTracker.get().getScheduledMessages(maxMessagesToRead);
} else { } else {
return Collections.emptySet(); return Collections.emptySet();
...@@ -741,11 +745,7 @@ public class PersistentDispatcherMultipleConsumers extends AbstractDispatcherMul ...@@ -741,11 +745,7 @@ public class PersistentDispatcherMultipleConsumers extends AbstractDispatcherMul
} }
public synchronized long getNumberOfDelayedMessages() { public synchronized long getNumberOfDelayedMessages() {
if (delayedDeliveryTracker.isPresent()) { return delayedDeliveryTracker.map(DelayedDeliveryTracker::getNumberOfDelayedMessages).orElse(0L);
return delayedDeliveryTracker.get().getNumberOfDelayedMessages();
} else {
return 0;
}
} }
@Override @Override
......
...@@ -156,4 +156,32 @@ public class InMemoryDeliveryTrackerTest { ...@@ -156,4 +156,32 @@ public class InMemoryDeliveryTrackerTest {
task.run(mock(Timeout.class)); task.run(mock(Timeout.class));
verify(dispatcher).readMoreEntries(); verify(dispatcher).readMoreEntries();
} }
/**
* Adding a message that is about to expire within the tick time should lead
* to a rejection from the tracker.
*/
@Test
public void testAddWithinTickTime() throws Exception {
PersistentDispatcherMultipleConsumers dispatcher = mock(PersistentDispatcherMultipleConsumers.class);
Timer timer = mock(Timer.class);
AtomicLong clockTime = new AtomicLong();
Clock clock = mock(Clock.class);
when(clock.millis()).then(x -> clockTime.get());
@Cleanup
InMemoryDelayedDeliveryTracker tracker = new InMemoryDelayedDeliveryTracker(dispatcher, timer, 100, clock);
clockTime.set(0);
assertFalse(tracker.addMessage(1, 1, 10));
assertFalse(tracker.addMessage(2, 2, 99));
assertTrue(tracker.addMessage(3, 3, 100));
assertTrue(tracker.addMessage(4, 4, 200));
assertEquals(tracker.getNumberOfDelayedMessages(), 2);
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册