Netty клиент генерирует много состояний сокета TIME_WAIT - PullRequest
0 голосов
/ 17 декабря 2018

Я написал код клиента netty для отправки некоторых обработанных данных нескольким клиентам.После 3-4 часов работы я исчерпал все розетки и больше никаких подключений невозможно.Также, когда я проверяю состояния сокетов в ОС, большое количество сокетов находится в состоянии TIME_WAIT.

public class NettyClient {

private static LogHelper logger = new LogHelper(NettyClient.class);

private static EventLoopGroup workerGroup = new NioEventLoopGroup();

private static Bootstrap nettyClient = new Bootstrap()
        .group(workerGroup)
        .channel(NioSocketChannel.class)
        .option(ChannelOption.SO_KEEPALIVE, true)
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);

private URL url;
private RequestVo Req;
private ChannelFuture chFuture;
private Object ReportData;
private JAXBContext jbContext;
private static final int CHANNEL_READ_TIMEOUT = 5;


public NettyClient() {
    // TODO Auto-generated constructor stub
}

public NettyClient(RequestVo Req, JAXBContext jbCtx,Object data) {
    this.Req = Req;
    this.ReportData = data;
    this.jbContext = jbCtx;
}

public void sendRequest() {

    logger.debug("In sendRequest()");
    //ChannelFuture chFuture = null;
    try {
        this.url = new URL(Req.getPushAddress());
        //add handlers
        nettyClient.handler(new ChannelInitializer<SocketChannel>() {

            @Override
            public void initChannel(SocketChannel ch) {
                ch.pipeline()
                  .addLast("timeout",
                    new ReadTimeoutHandler(CHANNEL_READ_TIMEOUT, TimeUnit.SECONDS));

                ch.pipeline()
                  .addLast("codec", new HttpClientCodec());

                ch.pipeline()
                  .addLast("inbound",
                     new NettyClientInBoundHandler(Req, jbContext, ReportData));
            }
        });

        //make a connection to the Client
        int port = url.getPort() == -1? url.getDefaultPort():url.getPort();
        chFuture = nettyClient.connect(url.getHost(), port);
        chFuture.addListener(new NettyClientConnectionListener(this.Req.getRequestId()));
    } catch (Exception e) {
        logger.error("Exception: Failed to connect to Client ", e);
    } finally {

    }
}
}

Вот методы из класса ChannelInBoundHandler

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
{
    Map<String, String> props = new HashMap<String, String>();

    if(msg instanceof HttpResponse) {
        logger.debug("channelRead()");
        HttpResponse httpRes = (HttpResponse) msg;
        HttpResponseStatus httpStatus = httpRes.status();
        props.put(REQUEST_ID, this.Request.getRequestId());
        props.put(CLIENT_RESPONSE_CODE, String.valueOf(httpStatus.code()));
        JmsService.getInstance(DESTINATION).sendTextMessage(props, "");
        logger.debug("channelRead() HttpResponse Code: " + httpStatus.code());
        ctx.close();
    }
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
    Map<String, String> props = new HashMap<String, String>();

    logger.error("exceptionCaught()", cause);
    if(cause instanceof ReadTimeoutException) {
        //If read-timeout, send back the response
        props.put(REQUEST_ID, this.Request.getRequestId());
        props.put(CLIENT_RESPONSE_CODE,
                  String.valueOf(HttpResponseStatus.REQUEST_TIMEOUT.code()));
        JmsService.getInstance(DESTINATION).sendTextMessage(props, "");
        ctx.close();
    }
    else {
        logger.error("Exception: ", cause);
    }
}

Любая идея, что не такв коде очень помог бы мне.Спасибо

1 Ответ

0 голосов
/ 24 апреля 2019

Я не знаком с netty , но я думаю, что могу объяснить часть вашей проблемы и, надеюсь, помочь вам в этом:

Когда вы используете порт изатем закройте его, порт не будет автоматически доступен для использования другими процессами сразу.Вместо этого он перейдет в состояние TIME_WAIT на определенный период времени.Я полагаю, что для Windows это будет 240 секунд (четыре минуты).

Я полагаю, что ваш код медленно использует все доступные порты в вашей системе, поскольку выход портов из состояния TIME_WAIT происходит слишком медленно.

Это не такМне совершенно ясно, откуда берутся реальные номера портов (возможно, они автоматически генерируются url.getDefaultPort()?), но, возможно, вы можете найти какой-нибудь способ их повторного использования?Если вы можете сохранить одно или несколько открытых соединений и каким-либо образом использовать их, то вы можете уменьшить частоту запросов на новые порты настолько, чтобы закрытые порты выходили из своего состояния TIME_WAIT.

...