Skip to content

Commit 083fd4c

Browse files
authored
[improve][broker] Default managedLedgerMaxReadsInFlightSizeInMB to 15% of direct memory (#25979)
1 parent 1eb08ed commit 083fd4c

6 files changed

Lines changed: 67 additions & 25 deletions

File tree

conf/broker.conf

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,13 +1473,18 @@ managedLedgerCursorMaxEntriesPerLedger=50000
14731473
# Max time before triggering a rollover on a cursor ledger
14741474
managedLedgerCursorRolloverTimeInSeconds=14400
14751475

1476-
# Maximum amount of memory used hold data read from storage (or from the cache).
1477-
# This mechanism prevents the broker to have too many concurrent
1478-
# reads from storage and fall into Out of Memory errors in case
1479-
# of multiple concurrent reads to multiple concurrent consumers.
1480-
# Set 0 in order to disable the feature.
1481-
#
1482-
managedLedgerMaxReadsInFlightSizeInMB=0
1476+
# Maximum buffer size in MB for bytes read from storage (or from the cache).
1477+
# This is the memory retained by data read from storage (or cache) until it has been
1478+
# delivered to the Consumer Netty channel. This provides backpressure for BookKeeper and
1479+
# tiered storage reads, preventing the broker from having too many concurrent reads and
1480+
# running into Out of Memory errors when there are multiple concurrent reads to multiple
1481+
# concurrent consumers.
1482+
# When left unset (empty), it defaults to the greater of dispatcherMaxReadSizeBytes and 15% of available
1483+
# JVM direct memory; dispatcherMaxReadSizeBytes is the minimum value so the limiter can never block the
1484+
# completion of a single read.
1485+
# Set to 0 to disable the feature.
1486+
# Set to a value greater than 0 to use that many MB.
1487+
managedLedgerMaxReadsInFlightSizeInMB=
14831488

14841489
# Max number of "acknowledgment holes" that are going to be persistently stored.
14851490
# When acknowledging out of order, a consumer will leave holes that are supposed

conf/standalone.conf

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,19 @@ managedLedgerCacheEvictionExtendTTLOfRecentlyAccessed=true
914914
# The default value is 2 * managedLedgerCacheEvictionTimeThresholdMillis.
915915
managedLedgerContinueCachingAddedEntriesAfterLastActiveCursorLeavesMillis=
916916

917+
# Maximum buffer size in MB for bytes read from storage (or from the cache).
918+
# This is the memory retained by data read from storage (or cache) until it has been
919+
# delivered to the Consumer Netty channel. This provides backpressure for BookKeeper and
920+
# tiered storage reads, preventing the broker from having too many concurrent reads and
921+
# running into Out of Memory errors when there are multiple concurrent reads to multiple
922+
# concurrent consumers.
923+
# When left unset (empty), it defaults to the greater of dispatcherMaxReadSizeBytes and 15% of available
924+
# JVM direct memory; dispatcherMaxReadSizeBytes is the minimum value so the limiter can never block the
925+
# completion of a single read.
926+
# Set to 0 to disable the feature.
927+
# Set to a value greater than 0 to use that many MB.
928+
managedLedgerMaxReadsInFlightSizeInMB=
929+
917930
# Configure the threshold (in number of entries) from where a cursor should be considered 'backlogged'
918931
# and thus should be set as inactive.
919932
# This has no effect when cacheEvictionByExpectedReadCount is enabled.

pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,10 +2335,17 @@ The max allowed delay for delayed delivery (in milliseconds). If the broker rece
23352335
+ "inserting in cache")
23362336
private boolean managedLedgerCacheCopyEntries = false;
23372337

2338-
@FieldContext(category = CATEGORY_STORAGE_ML, doc = "Maximum buffer size for bytes read from storage."
2339-
+ " This is the memory retained by data read from storage (or cache) until it has been delivered to the"
2340-
+ " Consumer Netty channel. Use O to disable")
2341-
private long managedLedgerMaxReadsInFlightSizeInMB = 0;
2338+
@FieldContext(category = CATEGORY_STORAGE_ML, doc = "Maximum buffer size in MB for bytes read from storage"
2339+
+ " (or from the cache). This is the memory retained by data read from storage (or cache) until it has"
2340+
+ " been delivered to the Consumer Netty channel. This provides backpressure for BookKeeper and tiered"
2341+
+ " storage reads, preventing the broker from having too many concurrent reads and running into Out of"
2342+
+ " Memory errors when there are multiple concurrent reads to multiple concurrent consumers.\n"
2343+
+ "When left unset (empty), it defaults to the greater of dispatcherMaxReadSizeBytes and 15% of"
2344+
+ " available JVM direct memory; dispatcherMaxReadSizeBytes is the minimum value so the limiter"
2345+
+ " can never block the completion of a single read.\n"
2346+
+ "Set to 0 to disable the feature.\n"
2347+
+ "Set to a value greater than 0 to use that many MB.")
2348+
private Long managedLedgerMaxReadsInFlightSizeInMB = null;
23422349

23432350
@FieldContext(category = CATEGORY_STORAGE_ML, doc = "Maximum time to wait for acquiring permits for max reads in "
23442351
+ "flight when managedLedgerMaxReadsInFlightSizeInMB is set (>0) and the limit is reached.")

pulsar-broker/src/main/java/org/apache/pulsar/broker/ManagedLedgerClientFactory.java

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.pulsar.broker.storage.ManagedLedgerStorageClass;
4949
import org.apache.pulsar.common.policies.data.EnsemblePlacementPolicyConfig;
5050
import org.apache.pulsar.common.stats.CacheMetricsCollector;
51+
import org.apache.pulsar.common.util.DirectMemoryUtils;
5152
import org.apache.pulsar.metadata.api.extended.MetadataStoreExtended;
5253

5354
@CustomLog
@@ -90,18 +91,34 @@ public void initialize(ServiceConfiguration conf, MetadataStoreExtended metadata
9091
);
9192
}
9293
managedLedgerFactoryConfig.setCopyEntriesInCache(conf.isManagedLedgerCacheCopyEntries());
93-
long managedLedgerMaxReadsInFlightSizeBytes = conf.getManagedLedgerMaxReadsInFlightSizeInMB() * 1024L * 1024L;
94-
if (managedLedgerMaxReadsInFlightSizeBytes > 0 && conf.getDispatcherMaxReadSizeBytes() > 0
95-
&& managedLedgerMaxReadsInFlightSizeBytes < conf.getDispatcherMaxReadSizeBytes()) {
96-
log.warn()
97-
.attr("managedLedgerMaxReadsInFlightSizeInMB", conf.getManagedLedgerMaxReadsInFlightSizeInMB())
98-
.attr("dispatcherMaxReadSizeBytes", conf.getDispatcherMaxReadSizeBytes())
99-
.attr("minManagedLedgerMaxReadsInFlightSizeInMB",
100-
(conf.getDispatcherMaxReadSizeBytes() / (1024L * 1024L)) + 1)
101-
.log("Invalid configuration:"
102-
+ " managedLedgerMaxReadsInFlightSizeInMB in bytes"
103-
+ " should be greater than"
104-
+ " dispatcherMaxReadSizeBytes");
94+
Long managedLedgerMaxReadsInFlightSizeInMB = conf.getManagedLedgerMaxReadsInFlightSizeInMB();
95+
// A single dispatcher read can retain up to dispatcherMaxReadSizeBytes bytes. The in-flight reads
96+
// limit must be at least this size, otherwise the limiter can block the completion of a single read.
97+
long dispatcherMaxReadSizeBytes = conf.getDispatcherMaxReadSizeBytes();
98+
final long managedLedgerMaxReadsInFlightSizeBytes;
99+
if (managedLedgerMaxReadsInFlightSizeInMB == null) {
100+
// When unset, default to 15% of the available JVM direct memory, but never below the maximum
101+
// size of a single read (dispatcherMaxReadSizeBytes) so that the limiter can never block the
102+
// completion of one read.
103+
long fractionOfDirectMemory = (long) (0.15d * DirectMemoryUtils.jvmMaxDirectMemory());
104+
managedLedgerMaxReadsInFlightSizeBytes = Math.max(fractionOfDirectMemory, dispatcherMaxReadSizeBytes);
105+
} else {
106+
// An explicit 0 disables the feature; an explicit value > 0 is used as-is.
107+
managedLedgerMaxReadsInFlightSizeBytes = managedLedgerMaxReadsInFlightSizeInMB * 1024L * 1024L;
108+
// Warn when the feature is enabled but manually configured below the size of a single read, since
109+
// the limiter would then be unable to admit one read. Disabled (0) is ignored.
110+
if (managedLedgerMaxReadsInFlightSizeBytes > 0 && dispatcherMaxReadSizeBytes > 0
111+
&& managedLedgerMaxReadsInFlightSizeBytes < dispatcherMaxReadSizeBytes) {
112+
log.warn()
113+
.attr("managedLedgerMaxReadsInFlightSizeInMB", managedLedgerMaxReadsInFlightSizeInMB)
114+
.attr("dispatcherMaxReadSizeBytes", dispatcherMaxReadSizeBytes)
115+
.attr("minManagedLedgerMaxReadsInFlightSizeInMB",
116+
(dispatcherMaxReadSizeBytes + (1024L * 1024L) - 1) / (1024L * 1024L))
117+
.log("Invalid configuration:"
118+
+ " managedLedgerMaxReadsInFlightSizeInMB in bytes should be greater than or"
119+
+ " equal to dispatcherMaxReadSizeBytes, otherwise the in-flight reads limiter"
120+
+ " can block the completion of a single read.");
121+
}
105122
}
106123
managedLedgerFactoryConfig.setManagedLedgerMaxReadsInFlightSize(managedLedgerMaxReadsInFlightSizeBytes);
107124
managedLedgerFactoryConfig.setManagedLedgerMaxReadsInFlightPermitsAcquireTimeoutMillis(

pulsar-broker/src/test/java/org/apache/pulsar/client/api/KeySharedSubscriptionBrokerCacheTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ protected void doInitConf() throws Exception {
100100
// Important: this is currently necessary to make use of cache for replay queue reads
101101
conf.setCacheEvictionByMarkDeletedPosition(true);
102102

103-
conf.setManagedLedgerMaxReadsInFlightSizeInMB(100);
103+
conf.setManagedLedgerMaxReadsInFlightSizeInMB(100L);
104104
conf.setDispatcherRetryBackoffInitialTimeInMs(0);
105105
conf.setDispatcherRetryBackoffMaxTimeInMs(0);
106106
conf.setKeySharedUnblockingIntervalMs(0);

pulsar-broker/src/test/java/org/apache/pulsar/client/api/KeySharedSubscriptionDisabledBrokerCacheTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected void setup() throws Exception {
9494
this.conf.setUnblockStuckSubscriptionEnabled(false);
9595
this.conf.setSubscriptionKeySharedUseConsistentHashing(true);
9696
conf.setManagedLedgerCacheSizeMB(0);
97-
conf.setManagedLedgerMaxReadsInFlightSizeInMB(0);
97+
conf.setManagedLedgerMaxReadsInFlightSizeInMB(0L);
9898
conf.setDispatcherRetryBackoffInitialTimeInMs(0);
9999
conf.setDispatcherRetryBackoffMaxTimeInMs(0);
100100
conf.setKeySharedUnblockingIntervalMs(0);

0 commit comments

Comments
 (0)