Как я могу ограничить пропускную способность в Java? - PullRequest
9 голосов
/ 16 октября 2010

Я написал планировщик Java, каждый час используя:

new SAXBuilder().build(new URL(xxx));

или

HttpConnection.connect(new URL(xxx)); // jsoup library code

, чтобы получить большой файл XML / HTML.

Максимальная пропускная способность моего сервера составляет 2 Мбит.

Когда запускается этот код расписания Java, я использую более 2 Мбит пропускной способности. ( проверить это )

Так что каждый раз, когда пользователь посещает мой сервер, это происходит слишком медленно.

Как ограничить расписание Java для использования более низкой пропускной способности? (например, 500 Кбит / с)

Я использую сервер Ubuntu.

Ответы [ 4 ]

15 голосов
/ 08 июня 2011

Теория:

Алгоритм выделения токенов - это способ ограничения пропускной способности загрузки.Вам следует прочитать эту статью : здесь объясняется использование этого алгоритма.

Реализации:

RateLimiter от Google Guava

Google Guava 22.0 включает RateLimiter класс, но он все еще находится в бета-версии.

Из документации API:

В качестве примера представим, что у нас есть список задач для выполнения, но мыне хотим передавать больше 2 в секунду:

final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
  void submitTasks(List<Runnable> tasks, Executor executor) {
    for (Runnable task : tasks) {
      rateLimiter.acquire(); // may wait
      executor.execute(task);
    }
  }

В качестве другого примера представьте, что мы создаем поток данных и хотим ограничить его скоростью 5 КБ в секунду,Это может быть достигнуто путем запроса разрешения на байт и указания скорости 5000 разрешений в секунду:

final RateLimiter rateLimiter = RateLimiter.create(5000.0); // rate = 5000 permits per second
  void submitPacket(byte[] packet) {
    rateLimiter.acquire(packet.length);
    networkService.send(packet);
  }

TimedSemaphore от Apache Commons Lang v3

Apache Commons Lang v3 include TimedSemaphore класс, который можно использовать для реализации ограничения скорости.

15 голосов
/ 16 октября 2010

Нет элегантного способа сделать это.

Простой, но не элегантный способ - написать оболочку потока Java, которая ограничивает скорость чтения байтов из упакованного потока. Например, если вы хотите ограничить до 1000 байтов в секунду, метод int read() может быть реализован следующим образом:

Stream in;
long timestamp = System.currentTimeInMillis();
int counter = 0;
int INTERVAL = 1000; // one second
int LIMIT = 1000; // bytes per INTERVAL

...

/**
 * Read one byte with rate limiting
 */
@Override
public int read() {
    if (counter > LIMIT) {
        long now = System.currentTimeInMillis();
        if (timestamp + INTERVAL >= now) {
            Thread.sleep(timestamp + INTERVAL - now);  
        }
        timestamp = now;
        counter = 0;
    }
    int res = in.read();
    if (res >= 0) {
        counter++;
    }
    return res;
}

Стоит отметить, что такие темпы регулирования могут иметь как отрицательные, так и положительные эффекты. С отрицательной стороны:

  • Связывает ресурсы на стороне сервера дольше. В данном случае речь идет о потоке Java, который обрабатывает загрузку, а память в пространстве ядра используется для буферизации принятых сетевых пакетов до тех пор, пока приложение их не прочитает.

  • Это также может привести к большему сетевому трафику. Проблема состоит в том, что этот вид регулирования нарушит бесперебойную передачу пакетов. Сервер будет буферизовать только относительно небольшое количество пакетов, и когда это число будет превышено, он должен пока сказать клиенту STOP. Это требует дополнительных сигнальных пакетов (ACK) и, вероятно, в процессе будут отброшены пакеты данных. В конечном итоге эти пакеты данных необходимо будет повторно передать.

3 голосов
/ 29 октября 2014

Возможным решением будет использование Proxy Server , который ограничивает пропускную способность.если вам нужно полное решение Java, вы можете использовать простой сокет java прокси-сервер здесь и замедлять процесс чтения / записи из потоков с помощью Thread.sleep или любым другим способом.

0 голосов
/ 17 мая 2013

Взгляните на этот поток: http://httpcomponents.10934.n7.nabble.com/throttlling-download-traffic-td18329.html

Также, если вы используете apache httpclient, вы можете настроить его на использование сжатия gzip и сэкономить немного пропускной способности.В частности, для xml вы должны ожидать, что таким образом будет передано намного меньше байтов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...