Search in sources :

Example 1 with ReadTimeoutHandler

use of org.jboss.netty.handler.timeout.ReadTimeoutHandler in project graylog2-server by Graylog2.

the class HttpTransport method getBaseChannelHandlers.

@Override
protected LinkedHashMap<String, Callable<? extends ChannelHandler>> getBaseChannelHandlers(MessageInput input) {
    final LinkedHashMap<String, Callable<? extends ChannelHandler>> baseChannelHandlers = super.getBaseChannelHandlers(input);
    if (idleWriterTimeout > 0) {
        // Install read timeout handler to close idle connections after a timeout.
        // This avoids dangling HTTP connections when the HTTP client does not close the connection properly.
        // For details see: https://github.com/Graylog2/graylog2-server/issues/3223#issuecomment-270350500
        baseChannelHandlers.put("read-timeout-handler", () -> new ReadTimeoutHandler(timer, idleWriterTimeout, TimeUnit.SECONDS));
    }
    baseChannelHandlers.put("decoder", () -> new HttpRequestDecoder(DEFAULT_MAX_INITIAL_LINE_LENGTH, DEFAULT_MAX_HEADER_SIZE, maxChunkSize));
    baseChannelHandlers.put("aggregator", () -> new HttpChunkAggregator(maxChunkSize));
    baseChannelHandlers.put("encoder", HttpResponseEncoder::new);
    baseChannelHandlers.put("decompressor", HttpContentDecompressor::new);
    return baseChannelHandlers;
}
Also used : HttpResponseEncoder(org.jboss.netty.handler.codec.http.HttpResponseEncoder) HttpRequestDecoder(org.jboss.netty.handler.codec.http.HttpRequestDecoder) ReadTimeoutHandler(org.jboss.netty.handler.timeout.ReadTimeoutHandler) HttpChunkAggregator(org.jboss.netty.handler.codec.http.HttpChunkAggregator) SimpleChannelHandler(org.jboss.netty.channel.SimpleChannelHandler) ChannelHandler(org.jboss.netty.channel.ChannelHandler) Callable(java.util.concurrent.Callable) HttpContentDecompressor(org.jboss.netty.handler.codec.http.HttpContentDecompressor)

Example 2 with ReadTimeoutHandler

use of org.jboss.netty.handler.timeout.ReadTimeoutHandler in project camel by apache.

the class NettyProducer method process.

public boolean process(final Exchange exchange, AsyncCallback callback) {
    if (!isRunAllowed()) {
        if (exchange.getException() == null) {
            exchange.setException(new RejectedExecutionException());
        }
        callback.done(true);
        return true;
    }
    Object body;
    try {
        body = getRequestBody(exchange);
        if (body == null) {
            noReplyLogger.log("No payload to send for exchange: " + exchange);
            callback.done(true);
            return true;
        }
    } catch (Exception e) {
        exchange.setException(e);
        callback.done(true);
        return true;
    }
    // set the exchange encoding property
    if (getConfiguration().getCharsetName() != null) {
        exchange.setProperty(Exchange.CHARSET_NAME, IOHelper.normalizeCharset(getConfiguration().getCharsetName()));
    }
    if (LOG.isTraceEnabled()) {
        LOG.trace("Pool[active={}, idle={}]", pool.getNumActive(), pool.getNumIdle());
    }
    // get a channel from the pool
    Channel existing;
    try {
        existing = pool.borrowObject();
        if (existing != null) {
            LOG.trace("Got channel from pool {}", existing);
        }
    } catch (Exception e) {
        exchange.setException(e);
        callback.done(true);
        return true;
    }
    // we must have a channel
    if (existing == null) {
        exchange.setException(new CamelExchangeException("Cannot get channel from pool", exchange));
        callback.done(true);
        return true;
    }
    if (exchange.getIn().getHeader(NettyConstants.NETTY_REQUEST_TIMEOUT) != null) {
        long timeoutInMs = exchange.getIn().getHeader(NettyConstants.NETTY_REQUEST_TIMEOUT, Long.class);
        ChannelHandler oldHandler = existing.getPipeline().get("timeout");
        ReadTimeoutHandler newHandler = new ReadTimeoutHandler(getEndpoint().getTimer(), timeoutInMs, TimeUnit.MILLISECONDS);
        if (oldHandler == null) {
            existing.getPipeline().addBefore("handler", "timeout", newHandler);
        } else {
            existing.getPipeline().replace(oldHandler, "timeout", newHandler);
        }
    }
    // need to declare as final
    final Channel channel = existing;
    final AsyncCallback producerCallback = new NettyProducerCallback(channel, callback);
    // setup state as attachment on the channel, so we can access the state later when needed
    channel.setAttachment(new NettyCamelState(producerCallback, exchange));
    InetSocketAddress remoteAddress = null;
    if (!isTcp()) {
        // Need to specify the remoteAddress for udp connection
        remoteAddress = new InetSocketAddress(configuration.getHost(), configuration.getPort());
    }
    // write body
    NettyHelper.writeBodyAsync(LOG, channel, remoteAddress, body, exchange, new ChannelFutureListener() {

        public void operationComplete(ChannelFuture channelFuture) throws Exception {
            LOG.trace("Operation complete {}", channelFuture);
            if (!channelFuture.isSuccess()) {
                // no success then exit, (any exception has been handled by ClientChannelHandler#exceptionCaught)
                return;
            }
            // if we do not expect any reply then signal callback to continue routing
            if (!configuration.isSync()) {
                try {
                    // should channel be closed after complete?
                    Boolean close;
                    if (ExchangeHelper.isOutCapable(exchange)) {
                        close = exchange.getOut().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
                    } else {
                        close = exchange.getIn().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
                    }
                    // should we disconnect, the header can override the configuration
                    boolean disconnect = getConfiguration().isDisconnect();
                    if (close != null) {
                        disconnect = close;
                    }
                    if (disconnect) {
                        if (LOG.isTraceEnabled()) {
                            LOG.trace("Closing channel when complete at address: {}", getEndpoint().getConfiguration().getAddress());
                        }
                        NettyHelper.close(channel);
                    }
                } finally {
                    // signal callback to continue routing
                    producerCallback.done(false);
                }
            }
        }
    });
    // continue routing asynchronously
    return false;
}
Also used : ChannelFuture(org.jboss.netty.channel.ChannelFuture) SucceededChannelFuture(org.jboss.netty.channel.SucceededChannelFuture) CamelExchangeException(org.apache.camel.CamelExchangeException) InetSocketAddress(java.net.InetSocketAddress) Channel(org.jboss.netty.channel.Channel) AsyncCallback(org.apache.camel.AsyncCallback) ChannelHandler(org.jboss.netty.channel.ChannelHandler) ChannelFutureListener(org.jboss.netty.channel.ChannelFutureListener) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) CamelException(org.apache.camel.CamelException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) ConnectException(java.net.ConnectException) CamelExchangeException(org.apache.camel.CamelExchangeException) ReadTimeoutHandler(org.jboss.netty.handler.timeout.ReadTimeoutHandler)

Example 3 with ReadTimeoutHandler

use of org.jboss.netty.handler.timeout.ReadTimeoutHandler in project camel by apache.

the class DefaultClientPipelineFactory method getPipeline.

public ChannelPipeline getPipeline() throws Exception {
    // create a new pipeline
    ChannelPipeline channelPipeline = Channels.pipeline();
    SslHandler sslHandler = configureClientSSLOnDemand();
    if (sslHandler != null) {
        // must close on SSL exception
        sslHandler.setCloseOnSSLException(true);
        LOG.debug("Client SSL handler configured and added to the ChannelPipeline: {}", sslHandler);
        addToPipeline("ssl", channelPipeline, sslHandler);
    }
    List<ChannelHandler> decoders = producer.getConfiguration().getDecoders();
    for (int x = 0; x < decoders.size(); x++) {
        ChannelHandler decoder = decoders.get(x);
        if (decoder instanceof ChannelHandlerFactory) {
            // use the factory to create a new instance of the channel as it may not be shareable
            decoder = ((ChannelHandlerFactory) decoder).newChannelHandler();
        }
        addToPipeline("decoder-" + x, channelPipeline, decoder);
    }
    List<ChannelHandler> encoders = producer.getConfiguration().getEncoders();
    for (int x = 0; x < encoders.size(); x++) {
        ChannelHandler encoder = encoders.get(x);
        if (encoder instanceof ChannelHandlerFactory) {
            // use the factory to create a new instance of the channel as it may not be shareable
            encoder = ((ChannelHandlerFactory) encoder).newChannelHandler();
        }
        addToPipeline("encoder-" + x, channelPipeline, encoder);
    }
    // do we use request timeout?
    if (producer.getConfiguration().getRequestTimeout() > 0) {
        if (LOG.isTraceEnabled()) {
            LOG.trace("Using request timeout {} millis", producer.getConfiguration().getRequestTimeout());
        }
        ChannelHandler timeout = new ReadTimeoutHandler(producer.getEndpoint().getTimer(), producer.getConfiguration().getRequestTimeout(), TimeUnit.MILLISECONDS);
        addToPipeline("timeout", channelPipeline, timeout);
    }
    // our handler must be added last
    addToPipeline("handler", channelPipeline, new ClientChannelHandler(producer));
    LOG.trace("Created ChannelPipeline: {}", channelPipeline);
    return channelPipeline;
}
Also used : ReadTimeoutHandler(org.jboss.netty.handler.timeout.ReadTimeoutHandler) ClientChannelHandler(org.apache.camel.component.netty.handlers.ClientChannelHandler) ChannelHandler(org.jboss.netty.channel.ChannelHandler) ChannelPipeline(org.jboss.netty.channel.ChannelPipeline) SslHandler(org.jboss.netty.handler.ssl.SslHandler) ClientChannelHandler(org.apache.camel.component.netty.handlers.ClientChannelHandler)

Example 4 with ReadTimeoutHandler

use of org.jboss.netty.handler.timeout.ReadTimeoutHandler in project druid by druid-io.

the class NettyHttpClient method go.

@Override
public <Intermediate, Final> ListenableFuture<Final> go(final Request request, final HttpResponseHandler<Intermediate, Final> handler, final Duration requestReadTimeout) {
    final HttpMethod method = request.getMethod();
    final URL url = request.getUrl();
    final Multimap<String, String> headers = request.getHeaders();
    final String requestDesc = method + " " + url;
    if (log.isDebugEnabled()) {
        log.debug("[%s] starting", requestDesc);
    }
    // Block while acquiring a channel from the pool, then complete the request asynchronously.
    final Channel channel;
    final String hostKey = getPoolKey(url);
    final ResourceContainer<ChannelFuture> channelResourceContainer = pool.take(hostKey);
    final ChannelFuture channelFuture = channelResourceContainer.get().awaitUninterruptibly();
    if (!channelFuture.isSuccess()) {
        // Some other poor sap will have to deal with it...
        channelResourceContainer.returnResource();
        return Futures.immediateFailedFuture(new ChannelException("Faulty channel in resource pool", channelFuture.getCause()));
    } else {
        channel = channelFuture.getChannel();
        // In case we get a channel that never had its readability turned back on.
        channel.setReadable(true);
    }
    final String urlFile = StringUtils.nullToEmptyNonDruidDataString(url.getFile());
    final HttpRequest httpRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, method, urlFile.isEmpty() ? "/" : urlFile);
    if (!headers.containsKey(HttpHeaders.Names.HOST)) {
        httpRequest.headers().add(HttpHeaders.Names.HOST, getHost(url));
    }
    // If Accept-Encoding is set in the Request, use that. Otherwise use the default from "compressionCodec".
    if (!headers.containsKey(HttpHeaders.Names.ACCEPT_ENCODING)) {
        httpRequest.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, compressionCodec.getEncodingString());
    }
    for (Map.Entry<String, Collection<String>> entry : headers.asMap().entrySet()) {
        String key = entry.getKey();
        for (String obj : entry.getValue()) {
            httpRequest.headers().add(key, obj);
        }
    }
    if (request.hasContent()) {
        httpRequest.setContent(request.getContent());
    }
    final long readTimeout = getReadTimeout(requestReadTimeout);
    final SettableFuture<Final> retVal = SettableFuture.create();
    if (readTimeout > 0) {
        channel.getPipeline().addLast(READ_TIMEOUT_HANDLER_NAME, new ReadTimeoutHandler(timer, readTimeout, TimeUnit.MILLISECONDS));
    }
    channel.getPipeline().addLast(LAST_HANDLER_NAME, new SimpleChannelUpstreamHandler() {

        private volatile ClientResponse<Intermediate> response = null;

        // Chunk number most recently assigned.
        private long currentChunkNum = 0;

        // Suspend and resume watermarks (respectively: last chunk number that triggered a suspend, and that was
        // provided to the TrafficCop's resume method). Synchronized access since they are not always accessed
        // from an I/O thread. (TrafficCops can be called from any thread.)
        private final Object watermarkLock = new Object();

        private long suspendWatermark = -1;

        private long resumeWatermark = -1;

        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
            if (log.isDebugEnabled()) {
                log.debug("[%s] messageReceived: %s", requestDesc, e.getMessage());
            }
            try {
                Object msg = e.getMessage();
                if (msg instanceof HttpResponse) {
                    HttpResponse httpResponse = (HttpResponse) msg;
                    if (log.isDebugEnabled()) {
                        log.debug("[%s] Got response: %s", requestDesc, httpResponse.getStatus());
                    }
                    HttpResponseHandler.TrafficCop trafficCop = resumeChunkNum -> {
                        synchronized (watermarkLock) {
                            resumeWatermark = Math.max(resumeWatermark, resumeChunkNum);
                            if (suspendWatermark >= 0 && resumeWatermark >= suspendWatermark) {
                                suspendWatermark = -1;
                                channel.setReadable(true);
                                long backPressureDuration = System.nanoTime() - backPressureStartTimeNs;
                                log.debug("[%s] Resumed reads from channel (chunkNum = %,d).", requestDesc, resumeChunkNum);
                                return backPressureDuration;
                            }
                        }
                        // If we didn't resume, don't know if backpressure was happening
                        return 0;
                    };
                    response = handler.handleResponse(httpResponse, trafficCop);
                    if (response.isFinished()) {
                        retVal.set((Final) response.getObj());
                    }
                    assert currentChunkNum == 0;
                    possiblySuspendReads(response);
                    if (!httpResponse.isChunked()) {
                        finishRequest();
                    }
                } else if (msg instanceof HttpChunk) {
                    HttpChunk httpChunk = (HttpChunk) msg;
                    if (log.isDebugEnabled()) {
                        log.debug("[%s] Got chunk: %sB, last=%s", requestDesc, httpChunk.getContent().readableBytes(), httpChunk.isLast());
                    }
                    if (httpChunk.isLast()) {
                        finishRequest();
                    } else {
                        response = handler.handleChunk(response, httpChunk, ++currentChunkNum);
                        if (response.isFinished() && !retVal.isDone()) {
                            retVal.set((Final) response.getObj());
                        }
                        possiblySuspendReads(response);
                    }
                } else {
                    throw new ISE("Unknown message type[%s]", msg.getClass());
                }
            } catch (Exception ex) {
                log.warn(ex, "[%s] Exception thrown while processing message, closing channel.", requestDesc);
                if (!retVal.isDone()) {
                    retVal.set(null);
                }
                channel.close();
                channelResourceContainer.returnResource();
                throw ex;
            }
        }

        private void possiblySuspendReads(ClientResponse<?> response) {
            if (!response.isContinueReading()) {
                synchronized (watermarkLock) {
                    suspendWatermark = Math.max(suspendWatermark, currentChunkNum);
                    if (suspendWatermark > resumeWatermark) {
                        channel.setReadable(false);
                        backPressureStartTimeNs = System.nanoTime();
                        log.debug("[%s] Suspended reads from channel (chunkNum = %,d).", requestDesc, currentChunkNum);
                    }
                }
            }
        }

        private void finishRequest() {
            ClientResponse<Final> finalResponse = handler.done(response);
            if (!finalResponse.isFinished() || !finalResponse.isContinueReading()) {
                throw new ISE("[%s] Didn't get a completed ClientResponse Object from [%s] (finished = %s, continueReading = %s)", requestDesc, handler.getClass(), finalResponse.isFinished(), finalResponse.isContinueReading());
            }
            if (!retVal.isDone()) {
                retVal.set(finalResponse.getObj());
            }
            removeHandlers();
            channel.setReadable(true);
            channelResourceContainer.returnResource();
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext context, ExceptionEvent event) {
            if (log.isDebugEnabled()) {
                final Throwable cause = event.getCause();
                if (cause == null) {
                    log.debug("[%s] Caught exception", requestDesc);
                } else {
                    log.debug(cause, "[%s] Caught exception", requestDesc);
                }
            }
            retVal.setException(event.getCause());
            // response is non-null if we received initial chunk and then exception occurs
            if (response != null) {
                handler.exceptionCaught(response, event.getCause());
            }
            try {
                if (channel.isOpen()) {
                    channel.close();
                }
            } catch (Exception e) {
                log.warn(e, "Error while closing channel");
            } finally {
                channelResourceContainer.returnResource();
            }
        }

        @Override
        public void channelDisconnected(ChannelHandlerContext context, ChannelStateEvent event) {
            if (log.isDebugEnabled()) {
                log.debug("[%s] Channel disconnected", requestDesc);
            }
            // response is non-null if we received initial chunk and then exception occurs
            if (response != null) {
                handler.exceptionCaught(response, new ChannelException("Channel disconnected"));
            }
            channel.close();
            channelResourceContainer.returnResource();
            if (!retVal.isDone()) {
                log.warn("[%s] Channel disconnected before response complete", requestDesc);
                retVal.setException(new ChannelException("Channel disconnected"));
            }
        }

        private void removeHandlers() {
            if (readTimeout > 0) {
                channel.getPipeline().remove(READ_TIMEOUT_HANDLER_NAME);
            }
            channel.getPipeline().remove(LAST_HANDLER_NAME);
        }
    });
    channel.write(httpRequest).addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) {
            if (!future.isSuccess()) {
                channel.close();
                channelResourceContainer.returnResource();
                if (!retVal.isDone()) {
                    retVal.setException(new ChannelException(StringUtils.format("[%s] Failed to write request to channel", requestDesc), future.getCause()));
                }
            }
        }
    });
    return retVal;
}
Also used : ClientResponse(org.apache.druid.java.util.http.client.response.ClientResponse) ExceptionEvent(org.jboss.netty.channel.ExceptionEvent) MessageEvent(org.jboss.netty.channel.MessageEvent) ChannelHandlerContext(org.jboss.netty.channel.ChannelHandlerContext) URL(java.net.URL) ChannelStateEvent(org.jboss.netty.channel.ChannelStateEvent) DefaultHttpRequest(org.jboss.netty.handler.codec.http.DefaultHttpRequest) ISE(org.apache.druid.java.util.common.ISE) ChannelException(org.jboss.netty.channel.ChannelException) ChannelFuture(org.jboss.netty.channel.ChannelFuture) HttpRequest(org.jboss.netty.handler.codec.http.HttpRequest) DefaultHttpRequest(org.jboss.netty.handler.codec.http.DefaultHttpRequest) Channel(org.jboss.netty.channel.Channel) HttpResponse(org.jboss.netty.handler.codec.http.HttpResponse) SimpleChannelUpstreamHandler(org.jboss.netty.channel.SimpleChannelUpstreamHandler) ChannelFutureListener(org.jboss.netty.channel.ChannelFutureListener) ChannelException(org.jboss.netty.channel.ChannelException) Collection(java.util.Collection) ReadTimeoutHandler(org.jboss.netty.handler.timeout.ReadTimeoutHandler) Map(java.util.Map) HttpMethod(org.jboss.netty.handler.codec.http.HttpMethod) HttpChunk(org.jboss.netty.handler.codec.http.HttpChunk)

Example 5 with ReadTimeoutHandler

use of org.jboss.netty.handler.timeout.ReadTimeoutHandler in project camel by apache.

the class HttpClientPipelineFactory method getPipeline.

@Override
public ChannelPipeline getPipeline() throws Exception {
    ChannelPipeline pipeline = Channels.pipeline();
    SslHandler sslHandler = configureClientSSLOnDemand();
    if (sslHandler != null) {
        // must close on SSL exception
        sslHandler.setCloseOnSSLException(true);
        LOG.debug("Client SSL handler configured and added as an interceptor against the ChannelPipeline: {}", sslHandler);
        pipeline.addLast("ssl", sslHandler);
    }
    pipeline.addLast("http", new HttpClientCodec());
    List<ChannelHandler> decoders = producer.getConfiguration().getDecoders();
    for (int x = 0; x < decoders.size(); x++) {
        ChannelHandler decoder = decoders.get(x);
        if (decoder instanceof ChannelHandlerFactory) {
            // use the factory to create a new instance of the channel as it may not be shareable
            decoder = ((ChannelHandlerFactory) decoder).newChannelHandler();
        }
        pipeline.addLast("decoder-" + x, decoder);
    }
    List<ChannelHandler> encoders = producer.getConfiguration().getEncoders();
    for (int x = 0; x < encoders.size(); x++) {
        ChannelHandler encoder = encoders.get(x);
        if (encoder instanceof ChannelHandlerFactory) {
            // use the factory to create a new instance of the channel as it may not be shareable
            encoder = ((ChannelHandlerFactory) encoder).newChannelHandler();
        }
        pipeline.addLast("encoder-" + x, encoder);
    }
    if (producer.getConfiguration().getRequestTimeout() > 0) {
        if (LOG.isTraceEnabled()) {
            LOG.trace("Using request timeout {} millis", producer.getConfiguration().getRequestTimeout());
        }
        ChannelHandler timeout = new ReadTimeoutHandler(producer.getEndpoint().getTimer(), producer.getConfiguration().getRequestTimeout(), TimeUnit.MILLISECONDS);
        pipeline.addLast("timeout", timeout);
    }
    // handler to route Camel messages
    pipeline.addLast("handler", new HttpClientChannelHandler(producer));
    return pipeline;
}
Also used : HttpClientChannelHandler(org.apache.camel.component.netty.http.handlers.HttpClientChannelHandler) ChannelHandlerFactory(org.apache.camel.component.netty.ChannelHandlerFactory) ReadTimeoutHandler(org.jboss.netty.handler.timeout.ReadTimeoutHandler) HttpClientChannelHandler(org.apache.camel.component.netty.http.handlers.HttpClientChannelHandler) ChannelHandler(org.jboss.netty.channel.ChannelHandler) HttpClientCodec(org.jboss.netty.handler.codec.http.HttpClientCodec) ChannelPipeline(org.jboss.netty.channel.ChannelPipeline) SslHandler(org.jboss.netty.handler.ssl.SslHandler)

Aggregations

ReadTimeoutHandler (org.jboss.netty.handler.timeout.ReadTimeoutHandler)6 ChannelHandler (org.jboss.netty.channel.ChannelHandler)4 ChannelPipeline (org.jboss.netty.channel.ChannelPipeline)3 Channel (org.jboss.netty.channel.Channel)2 ChannelFuture (org.jboss.netty.channel.ChannelFuture)2 ChannelFutureListener (org.jboss.netty.channel.ChannelFutureListener)2 SslHandler (org.jboss.netty.handler.ssl.SslHandler)2 ConnectException (java.net.ConnectException)1 InetSocketAddress (java.net.InetSocketAddress)1 URL (java.net.URL)1 Collection (java.util.Collection)1 Map (java.util.Map)1 Callable (java.util.concurrent.Callable)1 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)1 AsyncCallback (org.apache.camel.AsyncCallback)1 CamelException (org.apache.camel.CamelException)1 CamelExchangeException (org.apache.camel.CamelExchangeException)1 ChannelHandlerFactory (org.apache.camel.component.netty.ChannelHandlerFactory)1 ClientChannelHandler (org.apache.camel.component.netty.handlers.ClientChannelHandler)1 HttpClientChannelHandler (org.apache.camel.component.netty.http.handlers.HttpClientChannelHandler)1