@Override public Client createClient(ChannelHandlerContext ctx, ClientConfig config) { ClientState clientState = new ClientState(channelConfig(ctx), config); ClientChannelInitializer clientChannelInit = new ClientChannelInitializer(clientState, () -> new ProxyBackendHandler(ctx), getTracing()); ClientConnectionManager connManager = new ClientConnectionManager(clientState, clientChannelInit); Client client = new Client(clientState, connManager); ctx.channel().closeFuture().addListener(f -> clientPool.release(client)); log.debug("creating client"); return client; }
private boolean checkClientMetaState(ChannelHandlerContext ctx, ClientConfig config, Meta meta) { boolean available = meta.available.getAndSet(false); if (available && meta.client.isReusable()) { int count = meta.usageCount.incrementAndGet(); log.debug("reusing client in pool with usage count {}", count); meta.client.prepareForReuse(() -> new ProxyBackendHandler(ctx)); return true; } else { if (!meta.client.isReusable()) { clientPool.remove(config.remote()); } return false; } }
public void release(Client client) { log.debug("recycling client {}", client); client.recycle(); ConcurrentMap<Client, Meta> pool = getPool(client.remoteAddress()); if (pool.size() < maxSizePerAddress && !pool.containsKey(client)) { log.debug("releasing client to pool {}", client); pool.put(client, new Meta(client)); } else { Meta meta = pool.get(client); if (meta != null) { log.debug("setting client available in pool {}", client); meta.available.set(true); } } }
private void writeClientRequest(ChannelHandlerContext ctx, Client client, Request request) { Optional<ChannelFuture> optionalFuture = client.write(request); optionalFuture.ifPresent( channelFuture ->
protected Optional<Client> getHandlerClient( ChannelHandlerContext ctx, InetSocketAddress address) { return Optional.ofNullable(getClientMap(ctx).get(address)) .flatMap( it -> { if (it.isReusable()) { return Optional.of(it); } else { getClientMap(ctx).remove(address); return Optional.empty(); } }); }
private Client mockClient(String host) { Client client = mock(Client.class); when(client.remoteAddress()).thenReturn(new InetSocketAddress(host, 80)); return client; }
log.debug("== Dequeue req: " + requestPayload.request + " on client: " + this); if (connectionSuccess) { this.rawWrite(requestPayload.request) .addListener( (writeResult) -> {
@Test public void testConnectinFailed() throws Exception { when(connectionManager.connectionState()).thenReturn(ClientConnectionState.CLOSED_CONNECTION); Request request1 = requestFactory("req1"); Optional<ChannelFuture> result1Future = subject.write(request1); assertFalse(result1Future.isPresent()); } }
when(closeClient.isReusable()).thenReturn(false); factory.getClientMap(ctx).put(remoteAddress, closeClient);
return Optional.of(this.rawWrite(request)); } else { log.error("Connect failed on client: " + this);
@Test public void testAlreadyConnectedWrites() throws Exception { when(connectionManager.connectionState()).thenReturn(ClientConnectionState.CONNECTED); Request request1 = requestFactory("req1"); Request request2 = requestFactory("req2"); Optional<ChannelFuture> result1Future = subject.write(request1); Optional<ChannelFuture> result2Future = subject.write(request2); Request proxiedRequest1 = channel.readOutbound(); Request proxiedRequest2 = channel.readOutbound(); assertEquals(proxiedRequest1.path(), request1.path()); assertEquals(proxiedRequest2.path(), request2.path()); assertTrue(result1Future.get().isDone() && result1Future.get().isSuccess()); assertTrue(result2Future.get().isDone() && result2Future.get().isSuccess()); }
@Before public void setUp() throws Exception { channel = new EmbeddedChannel(); MockitoAnnotations.initMocks(this); when(connectionManager.currentChannel()).thenReturn(channel); subject = new Client(null, connectionManager); }
@Test public void testInitialConnectedWrites() throws Exception { ChannelPromise connectPromise = channel.newPromise(); when(connectionManager.connectionState()).thenReturn(ClientConnectionState.NOT_CONNECTED); when(connectionManager.connect()).thenReturn(connectPromise); Request request1 = requestFactory("req1"); Optional<ChannelFuture> result1Future = subject.write(request1); verify(connectionManager).connect(); Request proxiedRequest1BeforeConnection = channel.readOutbound(); assertNull(proxiedRequest1BeforeConnection); connectPromise.setSuccess(); Request proxiedRequest1AfterConnectionComplete = channel.readOutbound(); assertEquals(proxiedRequest1AfterConnectionComplete.path(), request1.path()); assertTrue(result1Future.get().isDone() && result1Future.get().isSuccess()); }
private Client newClient(XioTracing tracing) { val channelConfig = ChannelConfiguration.clientConfig(1, "client-tracing-test-worker"); val clientConfig = ClientConfig.from(ConfigFactory.load().getConfig("xio.baseClient")); val clientState = new ClientState(channelConfig, clientConfig); ClientChannelInitializer clientChannelInit = new ClientChannelInitializer(clientState, ApplicationHandler::new, tracing); ClientConnectionManager connManager = new ClientConnectionManager(clientState, clientChannelInit); return new Client(clientState, connManager); }
@Test public void testConnectionInProcessWrites() throws Exception { ChannelPromise connectPromise = channel.newPromise(); when(connectionManager.connectionState()).thenReturn(ClientConnectionState.NOT_CONNECTED); when(connectionManager.connect()).thenReturn(connectPromise); Request request1 = requestFactory("req1"); Request request2 = requestFactory("req2"); Request request3 = requestFactory("req3"); Optional<ChannelFuture> result1Future = subject.write(request1); when(connectionManager.connectionState()).thenReturn(ClientConnectionState.CONNECTING); Optional<ChannelFuture> result2Future = subject.write(request2); Optional<ChannelFuture> result3Future = subject.write(request3); // shouldn't get anything written on the channel at all Request proxiedRequest1BeforeConnection = channel.readOutbound(); assertNull(proxiedRequest1BeforeConnection); connectPromise.setSuccess(); Request proxiedRequest1AfterConnectionComplete = channel.readOutbound(); Request proxiedRequest2AfterConnectionComplete = channel.readOutbound(); Request proxiedRequest3AfterConnectionComplete = channel.readOutbound(); assertEquals(proxiedRequest1AfterConnectionComplete.path(), request1.path()); assertEquals(proxiedRequest2AfterConnectionComplete.path(), request2.path()); assertEquals(proxiedRequest3AfterConnectionComplete.path(), request3.path()); assertTrue(result1Future.get().isDone() && result1Future.get().isSuccess()); assertTrue(result2Future.get().isDone() && result2Future.get().isSuccess()); assertTrue(result3Future.get().isDone() && result3Future.get().isSuccess()); }
@Override public Client createClient(ChannelHandlerContext ctx, ClientConfig config) { ClientState clientState = new ClientState(channelConfig(ctx), config); ClientChannelInitializer clientChannelInit = new ClientChannelInitializer( clientState, () -> new ProxyBackendHandler(ctx), getTracing()); ClientConnectionManager connManager = new ClientConnectionManager(clientState, clientChannelInit); return new Client(clientState, connManager); } };
@Test public void testOutBoundAndInboundSpan() throws Exception { TracingConfig tracingConfig = new TracingConfig( "tracingHandlerClientIntegrationTest", config().getConfig("settings.tracing")); val client = newClient(new FakeTracer(tracingConfig)); val request = DefaultSegmentedRequest.builder() .method(GET) .path("/v1/authinit") .host("127.0.0.1" + ":" + server.getPort()) .build(); client.write(request); // We wait on the local future because this signals the full roundtrip between outbound and // return trip from the Application Handler out and then back in. local.get(); assertEquals(reportedSpans.size(), 1); val responseHex = ByteBufUtil.hexDump(((SegmentedData) response).content()); byte[] bytes = Hex.decodeHex(responseHex.toCharArray()); assertEquals(expectedResponse, new String(bytes, "UTF-8")); } }