Hi All,
We are using the last version of the Java Couchbase SDK (2.2.5 a the time of writing) and it seems that we are facing a memory leak with on direct memory allocated by Netty.
As mentionned in the documentation Env config doc we have disabled buffer pooling with the system property com.couchbase.bufferPoolingEnabled=false
because we suspected the SDK to be the origin of the memory leak.
And it worked. The memory leak was gone. The documentation says to open a ticket, if this his happenning. I create this topic instead, to be sure I am using the SDK as I should.
Here is how we create the DefaultCouchbaseEnvironment
:
DefaultCouchbaseEnvironment.Builder envBuilder = DefaultCouchbaseEnvironment
.builder()
.retryStrategy(FailFastRetryStrategy.INSTANCE)
.connectTimeout(config.getConnectionTimeoutInMs())
.maxRequestLifetime(maxRequestLifetimeInMs)
.queryTimeout(maxRequestLifetimeInMs)
.viewTimeout(maxRequestLifetimeInMs)
.managementTimeout(maxRequestLifetimeInMs)
.reconnectDelay(Delay.linear(TimeUnit.SECONDS, TimeUnit.HOURS.toSeconds(12), 10, 10))
.bootstrapCarrierEnabled(false)
.bootstrapHttpEnabled(true);
envBuilder.socketConnectTimeout(config.getSocketTimeoutInMs());
envBuilder.runtimeMetricsCollectorConfig(DefaultMetricsCollectorConfig.disabled())
.networkLatencyMetricsCollectorConfig(
DefaultLatencyMetricsCollectorConfig.builder()
.targetUnit(TimeUnit.MILLISECONDS)
.emitFrequency(30)
.emitFrequencyUnit(TimeUnit.SECONDS)
.targetPercentiles(TARGET_PERCENTILES)
.build())
.defaultMetricsLoggingConsumer(true, CouchbaseLogLevel.INFO);
DefaultCouchbaseEnvironment environment = envBuilder.build();
Here is how we open buckets :
List<Transcoder<? extends Document, ?>> transcoders = new ArrayList<>(2);
LegacyTranscoder legacyTranscoder = new LegacyTranscoder(compressionMinSize);
BinaryTranscoder binaryTranscoder = new BinaryTranscoder();
transcoders.add(legacyTranscoder);
transcoders.add(binaryTranscoder);
Bucket bucket = cluster.openBucket(bucketName, bucketPassword, transcoders);
Here is how we are accessing the bucket :
// reading
return bucket.async()
.get(id, LegacyDocument.class)
.timeout(readTimeoutInMs, TimeUnit.MILLISECONDS)
.onErrorResumeNext(throwable -> {
Throwable cause = throwable.getCause();
boolean exceptionForReplica = throwable instanceof TimeoutException || throwable instanceof TemporaryFailureException || cause instanceof TimeoutException || cause instanceof TemporaryFailureException;
if (exceptionForReplica) {
return bucket
.async()
.getFromReplica(id, ReplicaMode.FIRST, LegacyDocument.class)
.timeout(readReplicaTimeoutInMs, TimeUnit.MILLISECONDS);
}
return Observable.error(throwable);
});
// upsert
LegacyDocument document = LegacyDocument.create(
key,
expiry,
value);
return bucket.async()
.upsert(document)
.timeout(writeTimeoutInMs, TimeUnit.MILLISECONDS)
.map((Func1<LegacyDocument, Void>) legacyDocument -> null);
// delete
return bucket.async()
.remove(key, LegacyDocument.class)
.map((Func1<LegacyDocument, Void>) document -> null);
Thanks for your help