Search in sources :

Example 6 with AsyncPool

use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.

the class Http2NettyStreamClient method doWriteRequestWithWireAttrHeaders.

@Override
protected void doWriteRequestWithWireAttrHeaders(Request request, final RequestContext requestContext, SocketAddress address, Map<String, String> wireAttrs, TimeoutTransportCallback<StreamResponse> callback, long requestTimeout) {
    final AsyncPool<Channel> pool;
    try {
        pool = getChannelPoolManagerPerRequest(request).getPoolForAddress(address);
    } catch (IllegalStateException e) {
        errorResponse(callback, e);
        return;
    }
    requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_2);
    Callback<Channel> getCallback = new ChannelPoolGetCallback(pool, request, requestContext, callback, requestTimeout);
    final Cancellable pendingGet = pool.get(getCallback);
    if (pendingGet != null) {
        callback.addTimeoutTask(pendingGet::cancel);
    }
}
Also used : Cancellable(com.linkedin.r2.util.Cancellable) Channel(io.netty.channel.Channel)

Example 7 with AsyncPool

use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.

the class HttpNettyClient method doWriteRequest.

@Override
protected void doWriteRequest(RestRequest request, RequestContext requestContext, SocketAddress address, Map<String, String> wireAttrs, final TimeoutTransportCallback<RestResponse> callback, long requestTimeout) {
    final RestRequest newRequest = new RestRequestBuilder(request).overwriteHeaders(WireAttributeHelper.toWireAttributes(wireAttrs)).build();
    requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
    final AsyncPool<Channel> pool;
    try {
        pool = getChannelPoolManagerPerRequest(request).getPoolForAddress(address);
    } catch (IllegalStateException e) {
        errorResponse(callback, e);
        return;
    }
    final Cancellable pendingGet = pool.get(new Callback<Channel>() {

        @Override
        public void onSuccess(final Channel channel) {
            // This handler ensures the channel is returned to the pool at the end of the
            // Netty pipeline.
            channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).set(pool);
            callback.addTimeoutTask(() -> {
                AsyncPool<Channel> pool1 = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndSet(null);
                if (pool1 != null) {
                    pool1.dispose(channel);
                }
            });
            TransportCallback<RestResponse> sslTimingCallback = SslHandshakeTimingHandler.getSslTimingCallback(channel, requestContext, callback);
            // This handler invokes the callback with the response once it arrives.
            channel.attr(RAPResponseHandler.CALLBACK_ATTR_KEY).set(sslTimingCallback);
            // Set the session validator requested by the user
            SslSessionValidator sslSessionValidator = (SslSessionValidator) requestContext.getLocalAttr(R2Constants.REQUESTED_SSL_SESSION_VALIDATOR);
            channel.attr(NettyChannelAttributes.SSL_SESSION_VALIDATOR).set(sslSessionValidator);
            final NettyClientState state = _state.get();
            if (state == NettyClientState.REQUESTS_STOPPING || state == NettyClientState.SHUTDOWN) {
                // In this case, we acquired a channel from the pool as request processing is halting.
                // The shutdown task might not timeout this callback, since it may already have scanned
                // all the channels for pending requests before we set the callback as the channel
                // attachment.  The TimeoutTransportCallback ensures the user callback in never
                // invoked more than once, so it is safe to invoke it unconditionally.
                errorResponse(sslTimingCallback, new TimeoutException("Operation did not complete before shutdown"));
                // The channel is usually release in two places: timeout or in the netty pipeline.
                // Since we call the callback above, the timeout associated will be never invoked. On top of that
                // we never send the request to the pipeline (due to the return statement), and nobody is releasing the channel
                // until the channel is forcefully closed by the shutdownTimeout. Therefore we have to release it here
                AsyncPool<Channel> pool = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndSet(null);
                if (pool != null) {
                    pool.put(channel);
                }
                return;
            }
            // here we want the exception in outbound operations to be passed back through pipeline so that
            // the user callback would be invoked with the exception and the channel can be put back into the pool
            channel.writeAndFlush(newRequest).addListener(new ErrorChannelFutureListener());
        }

        @Override
        public void onError(Throwable e) {
            errorResponse(callback, e);
        }
    });
    if (pendingGet != null) {
        callback.addTimeoutTask(pendingGet::cancel);
    }
}
Also used : TimeoutTransportCallback(com.linkedin.r2.transport.http.client.TimeoutTransportCallback) TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) SslSessionValidator(com.linkedin.r2.transport.http.client.common.ssl.SslSessionValidator) Cancellable(com.linkedin.r2.util.Cancellable) Channel(io.netty.channel.Channel) RestRequest(com.linkedin.r2.message.rest.RestRequest) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) NettyClientState(com.linkedin.r2.netty.common.NettyClientState) AsyncPool(com.linkedin.r2.transport.http.client.AsyncPool) TimeoutException(java.util.concurrent.TimeoutException) ErrorChannelFutureListener(com.linkedin.r2.transport.http.client.common.ErrorChannelFutureListener)

Example 8 with AsyncPool

use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.

the class TestChannelPoolManager method test.

@Test
public void test() {
    ChannelPoolFactory factory = new ChannelPoolFactory() {

        @Override
        public AsyncPool<Channel> getPool(SocketAddress address) {
            return new FakePool<>();
        }
    };
    ChannelPoolManager m = new ChannelPoolManagerImpl(factory, null, null);
    final int NUM = 100;
    List<SocketAddress> addresses = new ArrayList<>(NUM);
    for (int i = 0; i < NUM; i++) {
        addresses.add(new InetSocketAddress(i));
    }
    List<AsyncPool<Channel>> pools = new ArrayList<>(NUM);
    for (int i = 0; i < NUM; i++) {
        pools.add(m.getPoolForAddress(addresses.get(i)));
    }
    for (int i = 0; i < NUM; i++) {
        Assert.assertEquals(m.getPoolForAddress(addresses.get(i)), pools.get(i));
    }
}
Also used : ChannelPoolFactory(com.linkedin.r2.transport.http.client.common.ChannelPoolFactory) InetSocketAddress(java.net.InetSocketAddress) Channel(io.netty.channel.Channel) ChannelPoolManager(com.linkedin.r2.transport.http.client.common.ChannelPoolManager) ArrayList(java.util.ArrayList) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) ChannelPoolManagerImpl(com.linkedin.r2.transport.http.client.common.ChannelPoolManagerImpl) Test(org.testng.annotations.Test)

Example 9 with AsyncPool

use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.

the class HttpNettyStreamClient method doWriteRequestWithWireAttrHeaders.

@Override
protected void doWriteRequestWithWireAttrHeaders(Request request, RequestContext requestContext, SocketAddress address, Map<String, String> wireAttrs, TimeoutTransportCallback<StreamResponse> callback, long requestTimeout) {
    final AsyncPool<Channel> pool;
    try {
        pool = getChannelPoolManagerPerRequest(request).getPoolForAddress(address);
    } catch (IllegalStateException e) {
        errorResponse(callback, e);
        return;
    }
    requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
    Callback<Channel> getCallback = new ChannelPoolGetCallback(pool, request, requestContext, callback, requestTimeout);
    final Cancellable pendingGet = pool.get(getCallback);
    if (pendingGet != null) {
        callback.addTimeoutTask(pendingGet::cancel);
    }
}
Also used : Cancellable(com.linkedin.r2.util.Cancellable) Channel(io.netty.channel.Channel)

Example 10 with AsyncPool

use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.

the class HttpNettyClient method writeRequest.

private void writeRequest(RestRequest request, RequestContext requestContext, Map<String, String> wireAttrs, final TimeoutTransportCallback<RestResponse> callback) {
    State state = _state.get();
    if (state != State.RUNNING) {
        errorResponse(callback, new IllegalStateException("Client is " + state));
        return;
    }
    URI uri = request.getURI();
    String scheme = uri.getScheme();
    if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
        errorResponse(callback, new IllegalArgumentException("Unknown scheme: " + scheme + " (only http/https is supported)"));
        return;
    }
    String host = uri.getHost();
    int port = uri.getPort();
    if (port == -1) {
        port = "http".equalsIgnoreCase(scheme) ? HTTP_DEFAULT_PORT : HTTPS_DEFAULT_PORT;
    }
    final RestRequest newRequest = new RestRequestBuilder(request).overwriteHeaders(WireAttributeHelper.toWireAttributes(wireAttrs)).build();
    final SocketAddress address;
    try {
        // TODO investigate DNS resolution and timing
        InetAddress inetAddress = InetAddress.getByName(host);
        address = new InetSocketAddress(inetAddress, port);
        requestContext.putLocalAttr(R2Constants.REMOTE_SERVER_ADDR, inetAddress.getHostAddress());
    } catch (UnknownHostException e) {
        errorResponse(callback, e);
        return;
    }
    requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
    final AsyncPool<Channel> pool;
    try {
        pool = _channelPoolManager.getPoolForAddress(address);
    } catch (IllegalStateException e) {
        errorResponse(callback, e);
        return;
    }
    final Cancellable pendingGet = pool.get(new Callback<Channel>() {

        @Override
        public void onSuccess(final Channel channel) {
            // This handler ensures the channel is returned to the pool at the end of the
            // Netty pipeline.
            channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).set(pool);
            callback.addTimeoutTask(new Runnable() {

                @Override
                public void run() {
                    AsyncPool<Channel> pool = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndRemove();
                    if (pool != null) {
                        pool.dispose(channel);
                    }
                }
            });
            // This handler invokes the callback with the response once it arrives.
            channel.attr(RAPResponseHandler.CALLBACK_ATTR_KEY).set(callback);
            final State state = _state.get();
            if (state == State.REQUESTS_STOPPING || state == State.SHUTDOWN) {
                // In this case, we acquired a channel from the pool as request processing is halting.
                // The shutdown task might not timeout this callback, since it may already have scanned
                // all the channels for pending requests before we set the callback as the channel
                // attachment.  The TimeoutTransportCallback ensures the user callback in never
                // invoked more than once, so it is safe to invoke it unconditionally.
                errorResponse(callback, new TimeoutException("Operation did not complete before shutdown"));
                return;
            }
            // here we want the exception in outbound operations to be passed back through pipeline so that
            // the user callback would be invoked with the exception and the channel can be put back into the pool
            channel.writeAndFlush(newRequest).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
        }

        @Override
        public void onError(Throwable e) {
            errorResponse(callback, e);
        }
    });
    if (pendingGet != null) {
        callback.addTimeoutTask(new Runnable() {

            @Override
            public void run() {
                pendingGet.cancel();
            }
        });
    }
}
Also used : UnknownHostException(java.net.UnknownHostException) InetSocketAddress(java.net.InetSocketAddress) Cancellable(com.linkedin.r2.util.Cancellable) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) Channel(io.netty.channel.Channel) URI(java.net.URI) RestRequest(com.linkedin.r2.message.rest.RestRequest) TimeoutRunnable(com.linkedin.r2.util.TimeoutRunnable) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) InetAddress(java.net.InetAddress) TimeoutException(java.util.concurrent.TimeoutException)

Aggregations

Channel (io.netty.channel.Channel)12 TimeoutException (java.util.concurrent.TimeoutException)10 Test (org.testng.annotations.Test)10 Cancellable (com.linkedin.r2.util.Cancellable)9 FutureCallback (com.linkedin.common.callback.FutureCallback)7 AsyncPoolImpl (com.linkedin.r2.transport.http.client.AsyncPoolImpl)7 ExecutionException (java.util.concurrent.ExecutionException)7 ObjectCreationTimeoutException (com.linkedin.r2.transport.http.client.ObjectCreationTimeoutException)6 PoolStats (com.linkedin.r2.transport.http.client.PoolStats)6 ArrayList (java.util.ArrayList)6 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)6 None (com.linkedin.common.util.None)5 LongTracking (com.linkedin.common.stats.LongTracking)4 RestRequest (com.linkedin.r2.message.rest.RestRequest)4 InetSocketAddress (java.net.InetSocketAddress)4 SocketAddress (java.net.SocketAddress)4 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)3 RestResponse (com.linkedin.r2.message.rest.RestResponse)3 ExponentialBackOffRateLimiter (com.linkedin.r2.transport.http.client.ExponentialBackOffRateLimiter)3 NioSocketChannel (io.netty.channel.socket.nio.NioSocketChannel)3