use of reactor.pool.InstrumentedPool in project reactor-netty by reactor.
the class DefaultPooledConnectionProviderTest method testIssue673_TimeoutException.
@Test
void testIssue673_TimeoutException() throws InterruptedException {
DisposableServer server = TcpServer.create().port(0).handle((in, out) -> out.sendString(Mono.just("test").delayElement(Duration.ofMillis(100)))).wiretap(true).bindNow();
DefaultPooledConnectionProvider provider = (DefaultPooledConnectionProvider) ConnectionProvider.builder("testIssue673_TimeoutException").maxConnections(1).pendingAcquireMaxCount(4).pendingAcquireTimeout(Duration.ofMillis(10)).build();
CountDownLatch latch = new CountDownLatch(2);
try {
AtomicReference<InstrumentedPool<PooledConnection>> pool = new AtomicReference<>();
List<? extends Signal<? extends Connection>> list = Flux.range(0, 5).flatMapDelayError(i -> TcpClient.create(provider).port(server.port()).doOnConnected(conn -> {
ConcurrentMap<PooledConnectionProvider.PoolKey, InstrumentedPool<PooledConnection>> pools = provider.channelPools;
pool.set(pools.get(pools.keySet().toArray()[0]));
}).doOnDisconnected(conn -> latch.countDown()).handle((in, out) -> in.receive().then()).wiretap(true).connect().materialize(), 256, 32).collectList().doFinally(fin -> latch.countDown()).block(Duration.ofSeconds(30));
assertThat(latch.await(30, TimeUnit.SECONDS)).as("latch 30s").isTrue();
assertThat(list).isNotNull().hasSize(5);
int onNext = 0;
int onError = 0;
String msg = "Pool#acquire(Duration) has been pending for more than the configured timeout of 10ms";
for (int i = 0; i < 5; i++) {
Signal<? extends Connection> signal = list.get(i);
if (signal.isOnNext()) {
onNext++;
} else if (signal.getThrowable() instanceof TimeoutException && msg.equals(signal.getThrowable().getMessage())) {
onError++;
}
}
assertThat(onNext).isEqualTo(1);
assertThat(onError).isEqualTo(4);
assertThat(pool.get().metrics().acquiredSize()).as("currently acquired").isEqualTo(0);
assertThat(pool.get().metrics().idleSize()).as("currently idle").isEqualTo(0);
} finally {
server.disposeNow();
provider.dispose();
}
}
use of reactor.pool.InstrumentedPool in project reactor-netty by reactor.
the class PooledConnectionProvider method acquire.
@Override
public final Mono<? extends Connection> acquire(TransportConfig config, ConnectionObserver connectionObserver, @Nullable Supplier<? extends SocketAddress> remote, @Nullable AddressResolverGroup<?> resolverGroup) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(connectionObserver, "connectionObserver");
Objects.requireNonNull(remote, "remoteAddress");
Objects.requireNonNull(resolverGroup, "resolverGroup");
return Mono.create(sink -> {
SocketAddress remoteAddress = Objects.requireNonNull(remote.get(), "Remote Address supplier returned null");
PoolKey holder = new PoolKey(remoteAddress, config.channelHash());
PoolFactory<T> poolFactory = poolFactory(remoteAddress);
InstrumentedPool<T> pool = MapUtils.computeIfAbsent(channelPools, holder, poolKey -> {
if (log.isDebugEnabled()) {
log.debug("Creating a new [{}] client pool [{}] for [{}]", name, poolFactory, remoteAddress);
}
InstrumentedPool<T> newPool = createPool(config, poolFactory, remoteAddress, resolverGroup);
if (poolFactory.metricsEnabled || config.metricsRecorder() != null) {
// registrar is null when metrics are enabled on HttpClient level or
// with the `metrics(boolean metricsEnabled)` method on ConnectionProvider
String id = poolKey.hashCode() + "";
if (poolFactory.registrar != null) {
poolFactory.registrar.get().registerMetrics(name, id, remoteAddress, new DelegatingConnectionPoolMetrics(newPool.metrics()));
} else if (Metrics.isInstrumentationAvailable()) {
// work directly with the pool otherwise a weak reference is needed to ConnectionPoolMetrics
// we don't want to keep another map with weak references
registerDefaultMetrics(id, remoteAddress, newPool.metrics());
}
}
return newPool;
});
EventLoop eventLoop = config.loopResources().onClient(config.isPreferNative()).next();
pool.acquire(Duration.ofMillis(poolFactory.pendingAcquireTimeout)).contextWrite(ctx -> ctx.put(CONTEXT_CALLER_EVENTLOOP, eventLoop)).subscribe(createDisposableAcquire(config, connectionObserver, poolFactory.pendingAcquireTimeout, pool, sink));
});
}
use of reactor.pool.InstrumentedPool in project reactor-netty by reactor.
the class DefaultPooledConnectionProviderTest method testIssue951_MaxPendingAcquire.
@Test
void testIssue951_MaxPendingAcquire() throws InterruptedException {
DisposableServer server = TcpServer.create().port(0).handle((in, out) -> out.sendString(Mono.just("test").delayElement(Duration.ofMillis(100)))).wiretap(true).bindNow();
DefaultPooledConnectionProvider provider = (DefaultPooledConnectionProvider) ConnectionProvider.builder("testIssue951_MaxPendingAcquire").maxConnections(1).pendingAcquireTimeout(Duration.ofMillis(30)).pendingAcquireMaxCount(1).build();
CountDownLatch latch = new CountDownLatch(2);
try {
AtomicReference<InstrumentedPool<PooledConnection>> pool = new AtomicReference<>();
List<? extends Signal<? extends Connection>> list = Flux.range(0, 3).flatMapDelayError(i -> TcpClient.create(provider).port(server.port()).doOnConnected(conn -> {
ConcurrentMap<PooledConnectionProvider.PoolKey, InstrumentedPool<PooledConnection>> pools = provider.channelPools;
pool.set(pools.get(pools.keySet().toArray()[0]));
}).doOnDisconnected(conn -> latch.countDown()).handle((in, out) -> in.receive().then()).wiretap(true).connect().materialize(), 256, 32).collectList().doFinally(fin -> latch.countDown()).block(Duration.ofSeconds(30));
assertThat(latch.await(30, TimeUnit.SECONDS)).as("latch 30s").isTrue();
assertThat(list).isNotNull().hasSize(3);
int onNext = 0;
int onErrorTimeout = 0;
int onErrorPendingAcquire = 0;
String msg1 = "Pool#acquire(Duration) has been pending for more than the configured timeout of 30ms";
String msg2 = "Pending acquire queue has reached its maximum size of 1";
for (int i = 0; i < 3; i++) {
Signal<? extends Connection> signal = list.get(i);
if (signal.isOnNext()) {
onNext++;
} else if (signal.getThrowable() instanceof TimeoutException && msg1.equals(signal.getThrowable().getMessage())) {
onErrorTimeout++;
} else if (signal.getThrowable() instanceof PoolAcquirePendingLimitException && msg2.equals(signal.getThrowable().getMessage())) {
onErrorPendingAcquire++;
}
}
assertThat(onNext).isEqualTo(1);
assertThat(onErrorTimeout).isEqualTo(1);
assertThat(onErrorPendingAcquire).isEqualTo(1);
assertThat(pool.get().metrics().acquiredSize()).as("currently acquired").isEqualTo(0);
assertThat(pool.get().metrics().idleSize()).as("currently idle").isEqualTo(0);
} finally {
server.disposeNow();
provider.dispose();
}
}
use of reactor.pool.InstrumentedPool in project reactor-netty by reactor.
the class DefaultPooledConnectionProviderTest method doTestIssue1790.
private void doTestIssue1790(boolean fifoPool) {
DefaultPooledConnectionProvider provider;
if (fifoPool) {
provider = (DefaultPooledConnectionProvider) ConnectionProvider.builder("testIssue1790").maxConnections(1).fifo().build();
} else {
provider = (DefaultPooledConnectionProvider) ConnectionProvider.builder("testIssue1790").maxConnections(1).lifo().build();
}
DisposableServer disposableServer = TcpServer.create().port(0).wiretap(true).bindNow();
Connection connection = null;
try {
connection = TcpClient.create(provider).port(disposableServer.port()).wiretap(true).connectNow();
assertThat(provider.channelPools).hasSize(1);
@SuppressWarnings({ "unchecked", "rawtypes" }) InstrumentedPool<DefaultPooledConnectionProvider.PooledConnection> channelPool = provider.channelPools.values().toArray(new InstrumentedPool[0])[0];
assertThat(channelPool.metrics()).withFailMessage("Reactor-netty relies on Reactor-pool instrumented pool.metrics()" + " to be the pool instance itself, got <%s> and <%s>", channelPool.metrics(), channelPool).isSameAs(channelPool);
} finally {
if (connection != null) {
connection.disposeNow();
}
disposableServer.disposeNow();
provider.disposeLater().block(Duration.ofSeconds(5));
}
}
Aggregations