Как вы препятствуете отказу в обслуживании исчерпать пул потоков на сервере сокетов в Java? - PullRequest
4 голосов
/ 12 октября 2011

Для работы я написал специализированный HTTP-сервер, который выполняет только перенаправления 301/302 / Frame для веб-сайтов. В последнее время некоторые гнусные клиенты намеренно открывают сокеты и пишут один символ каждые 500 миллисекунд, чтобы сократить время ожидания моего сокета TCP. Затем они оставляют сокет открытым на неопределенное время и имеют несколько клиентов, делающих одно и то же в распределенном отказе в обслуживании. Это в конечном итоге исчерпывает пул потоков, который обрабатывает соединения TCP. Как бы вы написали свой код, чтобы сделать его менее восприимчивым к такого рода плохому поведению? Вот мой сокет, принимающий код:

while (true) {
    // Blocks while waiting for a new connection
    log.debug("Blocking while waiting for a new connection.") ;
    try {
        Socket server = httpServer.accept() ; 

        // After receiving a new connection, set the SO_LINGER and SO_TIMEOUT options
        server.setReuseAddress(true) ;
        server.setSoTimeout(timeout) ;
        server.setSoLinger(true, socketTimeout) ;

        // Hand off the new socket connection to a worker thread
        threadPool.execute(new Worker(cache, server, requests, geoIp)) ;
    } catch (IOException e) {
        log.error("Unable to accept socket connection.", e) ;
        continue ;
    }
}

timeout и socketTimeout в настоящее время установлены на 500 миллисекунд.

1 Ответ

3 голосов
/ 12 октября 2011

Начните закрывать розетки по истечении определенного времени.Если розетка оставалась открытой слишком долго, просто закройте ее.Вы можете сделать это двумя способами:

Вы также можете установить ограничение по времени, которое требуется клиенту для отправки вам запроса.Если они не поддерживают определенный уровень пропускной способности, закройте их.Это может быть довольно легко сделать в цикле чтения, когда ваш поток читает запрос, добавив System.currentTimeInMillis () в начале и сравнивая с тем, где вы находитесь в цикле.Если он дойдет до определенного предела, он отключится и упадет.

Альтернативная идея этой идеи - возможно, не отклонять их, а позволить вашему потоку вернуться в пул, но поместить сокет в стек для наблюдения.Пусть байты накапливаются, и после того, как они достигли определенного размера, вы можете передать их потоку в пул для обработки.Это гибридный подход, чтобы отрезать их от, может быть, они неплохие, но медленные.

Еще один способ справиться с этим - посмотреть, как долго поток работал над запросом, и если он не завершен в течениеограничение по времени закрыть основной сокет.Тогда поток получит SocketException, и он может завершить работу и очистить.

Вот некоторые другие идеи, которые в основном связаны с использованием внешнего оборудования, например брандмауэры, балансировщики нагрузки и т. Д.1012 *

...