Search in sources :

Example 6 with ClientConnection

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);
        }
    }
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) ServerConnection(io.undertow.server.ServerConnection) ClientConnection(io.undertow.client.ClientConnection)

Example 7 with ClientConnection

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);
    }
}
Also used : ClientStatistics(io.undertow.client.ClientStatistics) ClientConnection(io.undertow.client.ClientConnection)

Example 8 with ClientConnection

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);
}
Also used : ClientConnection(io.undertow.client.ClientConnection)

Example 9 with ClientConnection

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);
        }
    }
}
Also used : ProxyCallback(io.undertow.server.handlers.proxy.ProxyCallback) HttpServerExchange(io.undertow.server.HttpServerExchange) ProxyConnection(io.undertow.server.handlers.proxy.ProxyConnection) ServerConnection(io.undertow.server.ServerConnection) ClientConnection(io.undertow.client.ClientConnection)

Example 10 with ClientConnection

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);
    }
}
Also used : ClientResponse(io.undertow.client.ClientResponse) UndertowClient(io.undertow.client.UndertowClient) ClientConnection(io.undertow.client.ClientConnection) CountDownLatch(java.util.concurrent.CountDownLatch) ClientRequest(io.undertow.client.ClientRequest) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Test(org.junit.Test)

Aggregations

ClientConnection (io.undertow.client.ClientConnection)12 ClientRequest (io.undertow.client.ClientRequest)7 UndertowClient (io.undertow.client.UndertowClient)5 IOException (java.io.IOException)5 ClientResponse (io.undertow.client.ClientResponse)4 HttpString (io.undertow.util.HttpString)4 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 Test (org.junit.Test)4 URI (java.net.URI)3 ClientCallback (io.undertow.client.ClientCallback)2 UndertowXnioSsl (io.undertow.protocols.ssl.UndertowXnioSsl)2 HttpServerExchange (io.undertow.server.HttpServerExchange)2 ServerConnection (io.undertow.server.ServerConnection)2 URISyntaxException (java.net.URISyntaxException)2 HttpHeaders (org.springframework.http.HttpHeaders)2 SockJsTransportFailureException (org.springframework.web.socket.sockjs.SockJsTransportFailureException)2 ClientExchange (io.undertow.client.ClientExchange)1 ClientStatistics (io.undertow.client.ClientStatistics)1 Http2ClientConnection (io.undertow.client.http2.Http2ClientConnection)1