Skip to content

Commit 37dc8a2

Browse files
authored
Ensure metrics are unregistered when inactive connection pool is disposed (#2932)
Fixes #2930
1 parent 960ed0c commit 37dc8a2

2 files changed

Lines changed: 73 additions & 7 deletions

File tree

reactor-netty-core/src/main/java/reactor/netty/resources/PooledConnectionProvider.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,19 @@ final void disposeInactivePoolsInBackground() {
355355
if (log.isDebugEnabled()) {
356356
log.debug("ConnectionProvider[name={}]: Disposing inactive pool for [{}]", name, e.getKey().holder);
357357
}
358-
e.getValue().dispose();
358+
SocketAddress address = e.getKey().holder;
359+
String id = e.getKey().hashCode() + "";
360+
PoolFactory<T> poolFactory = poolFactory(address);
361+
e.getValue().disposeLater().then(
362+
Mono.<Void>fromRunnable(() -> {
363+
if (poolFactory.registrar != null) {
364+
poolFactory.registrar.get().deRegisterMetrics(name, id, address);
365+
}
366+
else if (Metrics.isInstrumentationAvailable()) {
367+
deRegisterDefaultMetrics(id, address);
368+
}
369+
})
370+
).subscribe();
359371
}
360372
});
361373
}

reactor-netty-http/src/test/java/reactor/netty/resources/DefaultPooledConnectionProviderTest.java

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020-2022 VMware, Inc. or its affiliates, All Rights Reserved.
2+
* Copyright (c) 2020-2023 VMware, Inc. or its affiliates, All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -73,6 +73,7 @@
7373
import java.util.concurrent.ConcurrentMap;
7474
import java.util.concurrent.CountDownLatch;
7575
import java.util.concurrent.TimeUnit;
76+
import java.util.concurrent.atomic.AtomicBoolean;
7677
import java.util.concurrent.atomic.AtomicInteger;
7778
import java.util.concurrent.atomic.AtomicReference;
7879
import java.util.function.Function;
@@ -649,7 +650,7 @@ void testMinConnections() throws Exception {
649650

650651
@ParameterizedTest
651652
@MethodSource("disposeInactivePoolsInBackgroundCombinations")
652-
void testDisposeInactivePoolsInBackground(boolean enableEvictInBackground, boolean isHttp2) throws Exception {
653+
void testDisposeInactivePoolsInBackground(boolean enableEvictInBackground, boolean isHttp2, boolean isBuiltInMetrics) throws Exception {
653654
disposableServer =
654655
createServer()
655656
.wiretap(false)
@@ -668,6 +669,19 @@ void testDisposeInactivePoolsInBackground(boolean enableEvictInBackground, boole
668669
builder.evictInBackground(Duration.ofMillis(50));
669670
}
670671

672+
MeterRegistrarImpl meterRegistrar;
673+
String metricsName = "";
674+
if (isBuiltInMetrics) {
675+
meterRegistrar = null;
676+
builder.metrics(true);
677+
678+
metricsName = isHttp2 ? "http2.testDisposeInactivePoolsInBackground" : "testDisposeInactivePoolsInBackground";
679+
}
680+
else {
681+
meterRegistrar = new MeterRegistrarImpl();
682+
builder.metrics(true, () -> meterRegistrar);
683+
}
684+
671685
CountDownLatch latch = new CountDownLatch(10);
672686
DefaultPooledConnectionProvider provider = (DefaultPooledConnectionProvider) builder.build();
673687
HttpClient client =
@@ -694,6 +708,12 @@ void testDisposeInactivePoolsInBackground(boolean enableEvictInBackground, boole
694708
.verify(Duration.ofSeconds(5));
695709

696710
assertThat(provider.channelPools.size()).isEqualTo(1);
711+
if (meterRegistrar != null) {
712+
assertThat(meterRegistrar.registered.get()).isTrue();
713+
}
714+
else {
715+
assertThat(getGaugeValue(CONNECTION_PROVIDER_PREFIX + ACTIVE_CONNECTIONS, NAME, metricsName)).isNotEqualTo(-1);
716+
}
697717

698718
if (enableEvictInBackground) {
699719
assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();
@@ -706,6 +726,17 @@ void testDisposeInactivePoolsInBackground(boolean enableEvictInBackground, boole
706726
.isEqualTo(enableEvictInBackground ? 0 : 1));
707727

708728
assertThat(provider.isDisposed()).isEqualTo(enableEvictInBackground);
729+
if (meterRegistrar != null) {
730+
assertThat(meterRegistrar.deRegistered.get()).isEqualTo(enableEvictInBackground);
731+
}
732+
else {
733+
if (enableEvictInBackground) {
734+
assertThat(getGaugeValue(CONNECTION_PROVIDER_PREFIX + ACTIVE_CONNECTIONS, NAME, metricsName)).isEqualTo(-1);
735+
}
736+
else {
737+
assertThat(getGaugeValue(CONNECTION_PROVIDER_PREFIX + ACTIVE_CONNECTIONS, NAME, metricsName)).isNotEqualTo(-1);
738+
}
739+
}
709740
}
710741
finally {
711742
if (!enableEvictInBackground) {
@@ -717,10 +748,15 @@ void testDisposeInactivePoolsInBackground(boolean enableEvictInBackground, boole
717748

718749
static Stream<Arguments> disposeInactivePoolsInBackgroundCombinations() {
719750
return Stream.of(
720-
Arguments.of(false, false),
721-
Arguments.of(false, true),
722-
Arguments.of(true, false),
723-
Arguments.of(true, true)
751+
// enableEvictInBackground, isHttp2, isBuiltInMetrics
752+
Arguments.of(false, false, false),
753+
Arguments.of(false, false, true),
754+
Arguments.of(false, true, false),
755+
Arguments.of(false, true, true),
756+
Arguments.of(true, false, false),
757+
Arguments.of(true, false, true),
758+
Arguments.of(true, true, false),
759+
Arguments.of(true, true, true)
724760
);
725761
}
726762

@@ -830,4 +866,22 @@ void testHttp2PoolAndGoAway() {
830866
.block(Duration.ofSeconds(5));
831867
}
832868
}
869+
870+
static final class MeterRegistrarImpl implements ConnectionProvider.MeterRegistrar {
871+
AtomicBoolean registered = new AtomicBoolean();
872+
AtomicBoolean deRegistered = new AtomicBoolean();
873+
874+
MeterRegistrarImpl() {
875+
}
876+
877+
@Override
878+
public void registerMetrics(String poolName, String id, SocketAddress remoteAddress, ConnectionPoolMetrics metrics) {
879+
registered.compareAndSet(false, true);
880+
}
881+
882+
@Override
883+
public void deRegisterMetrics(String poolName, String id, SocketAddress remoteAddress) {
884+
deRegistered.compareAndSet(false, true);
885+
}
886+
}
833887
}

0 commit comments

Comments
 (0)