use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class LoadBalancingProxyClient method getConnection.
@Override
public void getConnection(ProxyTarget target, HttpServerExchange exchange, final ProxyCallback<ProxyConnection> callback, long timeout, TimeUnit timeUnit) {
final ExclusiveConnectionHolder holder = exchange.getConnection().getAttachment(exclusiveConnectionKey);
if (holder != null && holder.connection.getConnection().isOpen()) {
// Something has already caused an exclusive connection to be allocated so keep using it.
callback.completed(exchange, holder.connection);
return;
}
final Host host = selectHost(exchange);
if (host == null) {
callback.couldNotResolveBackend(exchange);
} else {
exchange.addToAttachmentList(ATTEMPTED_HOSTS, host);
if (holder != null || (exclusivityChecker != null && exclusivityChecker.isExclusivityRequired(exchange))) {
// If we have a holder, even if the connection was closed we now exclusivity was already requested so our client
// may be assuming it still exists.
host.connectionPool.connect(target, exchange, new ProxyCallback<ProxyConnection>() {
@Override
public void completed(HttpServerExchange exchange, ProxyConnection result) {
if (holder != null) {
holder.connection = result;
} else {
final ExclusiveConnectionHolder newHolder = new ExclusiveConnectionHolder();
newHolder.connection = result;
ServerConnection connection = exchange.getConnection();
connection.putAttachment(exclusiveConnectionKey, newHolder);
connection.addCloseListener(new ServerConnection.CloseListener() {
@Override
public void closed(ServerConnection connection) {
ClientConnection clientConnection = newHolder.connection.getConnection();
if (clientConnection.isOpen()) {
safeClose(clientConnection);
}
}
});
}
callback.completed(exchange, result);
}
@Override
public void queuedRequestFailed(HttpServerExchange exchange) {
callback.queuedRequestFailed(exchange);
}
@Override
public void failed(HttpServerExchange exchange) {
UndertowLogger.PROXY_REQUEST_LOGGER.proxyFailedToConnectToBackend(exchange.getRequestURI(), host.uri);
callback.failed(exchange);
}
@Override
public void couldNotResolveBackend(HttpServerExchange exchange) {
callback.couldNotResolveBackend(exchange);
}
}, timeout, timeUnit, true);
} else {
host.connectionPool.connect(target, exchange, callback, timeout, timeUnit, false);
}
}
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class ProxyConnectionPool method returnConnection.
/**
* Called when the IO thread has completed a successful request
*
* @param connectionHolder The client connection holder
*/
private void returnConnection(final ConnectionHolder connectionHolder) {
ClientStatistics stats = connectionHolder.clientConnection.getStatistics();
this.requestCount.incrementAndGet();
if (stats != null) {
//we update the stats when the connection is closed
this.read.addAndGet(stats.getRead());
this.written.addAndGet(stats.getWritten());
stats.reset();
}
HostThreadData hostData = getData();
if (closed) {
//the host has been closed
IoUtils.safeClose(connectionHolder.clientConnection);
ConnectionHolder con = hostData.availableConnections.poll();
while (con != null) {
IoUtils.safeClose(con.clientConnection);
con = hostData.availableConnections.poll();
}
redistributeQueued(hostData);
return;
}
//only do something if the connection is open. If it is closed then
//the close setter will handle creating a new connection and decrementing
//the connection count
final ClientConnection connection = connectionHolder.clientConnection;
if (connection.isOpen() && !connection.isUpgraded()) {
CallbackHolder callback = hostData.awaitingConnections.poll();
while (callback != null && callback.isCancelled()) {
callback = hostData.awaitingConnections.poll();
}
if (callback != null) {
if (callback.getTimeoutKey() != null) {
callback.getTimeoutKey().remove();
}
// Anything waiting for a connection is not expecting exclusivity.
connectionReady(connectionHolder, callback.getCallback(), callback.getExchange(), false);
} else {
final int cachedConnectionCount = hostData.availableConnections.size();
if (cachedConnectionCount >= maxCachedConnections) {
// Close the longest idle connection instead of the current one
final ConnectionHolder holder = hostData.availableConnections.poll();
if (holder != null) {
IoUtils.safeClose(holder.clientConnection);
}
}
hostData.availableConnections.add(connectionHolder);
// If the soft max and ttl are configured
if (timeToLive > 0) {
//we only start the timeout process once we have hit the core pool size
//otherwise connections could start timing out immediately once the core pool size is hit
//and if we never hit the core pool size then it does not make sense to start timers which are never
//used (as timers are expensive)
final long currentTime = System.currentTimeMillis();
connectionHolder.timeout = currentTime + timeToLive;
if (hostData.availableConnections.size() > coreCachedConnections) {
if (hostData.nextTimeout <= 0) {
hostData.timeoutKey = WorkerUtils.executeAfter(connection.getIoThread(), hostData.timeoutTask, timeToLive, TimeUnit.MILLISECONDS);
hostData.nextTimeout = connectionHolder.timeout;
}
}
}
}
} else if (connection.isOpen() && connection.isUpgraded()) {
//we treat upgraded connections as closed
//as we do not want the connection pool filled with upgraded connections
//if the connection is actually closed the close setter will handle it
connection.getCloseSetter().set(null);
handleClosedConnection(hostData, connectionHolder);
}
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class SimpleProxyClientProvider method getConnection.
@Override
public void getConnection(ProxyTarget target, HttpServerExchange exchange, ProxyCallback<ProxyConnection> callback, long timeout, TimeUnit timeUnit) {
ClientConnection existing = exchange.getConnection().getAttachment(clientAttachmentKey);
if (existing != null) {
if (existing.isOpen()) {
//this connection already has a client, re-use it
callback.completed(exchange, new ProxyConnection(existing, uri.getPath() == null ? "/" : uri.getPath()));
return;
} else {
exchange.getConnection().removeAttachment(clientAttachmentKey);
}
}
client.connect(new ConnectNotifier(callback, exchange), uri, exchange.getIoThread(), exchange.getConnection().getByteBufferPool(), OptionMap.EMPTY);
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class ModClusterProxyClient method getConnection.
public void getConnection(final ProxyTarget target, final HttpServerExchange exchange, final ProxyCallback<ProxyConnection> callback, final long timeout, final TimeUnit timeUnit) {
final ExclusiveConnectionHolder holder = exchange.getConnection().getAttachment(exclusiveConnectionKey);
if (holder != null && holder.connection.getConnection().isOpen()) {
// Something has already caused an exclusive connection to be
// allocated so keep using it.
callback.completed(exchange, holder.connection);
return;
}
if (!(target instanceof ModClusterProxyTarget)) {
callback.couldNotResolveBackend(exchange);
return;
}
// Resolve the node
final ModClusterProxyTarget proxyTarget = (ModClusterProxyTarget) target;
final Context context = proxyTarget.resolveContext(exchange);
if (context == null) {
callback.couldNotResolveBackend(exchange);
} else {
if (holder != null || (exclusivityChecker != null && exclusivityChecker.isExclusivityRequired(exchange))) {
// If we have a holder, even if the connection was closed we now
// exclusivity was already requested so our client
// may be assuming it still exists.
final ProxyCallback<ProxyConnection> wrappedCallback = new ProxyCallback<ProxyConnection>() {
@Override
public void completed(HttpServerExchange exchange, ProxyConnection result) {
if (holder != null) {
holder.connection = result;
} else {
final ExclusiveConnectionHolder newHolder = new ExclusiveConnectionHolder();
newHolder.connection = result;
ServerConnection connection = exchange.getConnection();
connection.putAttachment(exclusiveConnectionKey, newHolder);
connection.addCloseListener(new ServerConnection.CloseListener() {
@Override
public void closed(ServerConnection connection) {
ClientConnection clientConnection = newHolder.connection.getConnection();
if (clientConnection.isOpen()) {
safeClose(clientConnection);
}
}
});
}
callback.completed(exchange, result);
}
@Override
public void queuedRequestFailed(HttpServerExchange exchange) {
callback.queuedRequestFailed(exchange);
}
@Override
public void failed(HttpServerExchange exchange) {
callback.failed(exchange);
}
@Override
public void couldNotResolveBackend(HttpServerExchange exchange) {
callback.couldNotResolveBackend(exchange);
}
};
context.handleRequest(proxyTarget, exchange, wrappedCallback, timeout, timeUnit, true);
} else {
context.handleRequest(proxyTarget, exchange, callback, timeout, timeUnit, false);
}
}
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class HttpClientTestCase method testSimpleBasic.
@Test
public void testSimpleBasic() throws Exception {
//
DefaultServer.setRootHandler(SIMPLE_MESSAGE_HANDLER);
final UndertowClient client = createClient();
final List<ClientResponse> responses = new CopyOnWriteArrayList<>();
final CountDownLatch latch = new CountDownLatch(10);
final ClientConnection connection = client.connect(ADDRESS, worker, DefaultServer.getBufferPool(), OptionMap.EMPTY).get();
try {
connection.getIoThread().execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
final ClientRequest request = new ClientRequest().setMethod(Methods.GET).setPath("/");
request.getRequestHeaders().put(Headers.HOST, DefaultServer.getHostAddress());
connection.sendRequest(request, createClientCallback(responses, latch));
}
}
});
latch.await(10, TimeUnit.SECONDS);
Assert.assertEquals(10, responses.size());
for (final ClientResponse response : responses) {
Assert.assertEquals(message, response.getAttachment(RESPONSE_BODY));
}
} finally {
IoUtils.safeClose(connection);
}
}
Aggregations