首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Java中限制带宽?

如何在Java中限制带宽?
EN

Stack Overflow用户
提问于 2010-10-16 12:00:54
回答 4查看 23.1K关注 0票数 11

我写了一个Java调度器,每小时使用:

代码语言:javascript
运行
复制
new SAXBuilder().build(new URL(xxx));

代码语言:javascript
运行
复制
HttpConnection.connect(new URL(xxx)); // jsoup library code

来获得一个大的XML/HTML文件。

我的服务器最大带宽限制是2Mbits。

当这段Java调度代码运行时,我使用了超过2MB的带宽。(check it out)

所以每次用户访问我的服务器都太慢了。

如何限制我的Java调度以使用较低的带宽?(例如500Kbits)

我正在使用Ubuntu服务器。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-10-16 12:15:38

没有一种优雅的方法可以做到这一点。

一种简单但不优雅的方法是编写一个Java流包装器,该包装器限制从包装的流中读取字节的速率。例如,如果您希望限制为每秒1000字节,则可以按如下方式实现int read()方法:

代码语言:javascript
运行
复制
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线程,内核空间中的内存用于缓冲接收到的网络数据包,直到应用程序读取它们。
  • 这也可能导致更多的网络流量。问题是,这种节流会扰乱数据包的顺畅流动。服务器将只缓冲相对较少数量的数据包,当超过该数量时,它必须通知客户端暂时停止。这需要额外的信令分组(ACK),并且在此过程中可能会有数据包被丢弃。最终,这些数据包将需要是retransmitted.

票数 17
EN

Stack Overflow用户

发布于 2011-06-08 05:38:10

理论:

Token Bucket Algorithm是一种限制下载带宽的方法。你应该阅读this article:它解释了这个算法的用法。

实施:

来自谷歌Guava的RateLimiter

Google Guava22.0包含了一个RateLimiter类,但它仍处于测试阶段。

来自api文档:

例如,假设我们有一个要执行的任务列表,但我们不希望每秒提交2个以上的任务:

代码语言:javascript
运行
复制
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);
    }
  }

再举一个例子,假设我们产生了一个数据流,我们想把它限制在每秒5kb。这可以通过要求每个字节一个许可证,并指定每秒5000个许可证的速率来实现:

代码语言:javascript
运行
复制
final RateLimiter rateLimiter = RateLimiter.create(5000.0); // rate = 5000 permits per second
  void submitPacket(byte[] packet) {
    rateLimiter.acquire(packet.length);
    networkService.send(packet);
  }

来自Apache Commons Lang v3的TimedSemaphore

Apache Commons Lang v3包含一个可用于实现速率限制的TimedSemaphore类。

票数 17
EN

Stack Overflow用户

发布于 2014-10-29 20:04:03

一种可能的解决方案是使用限制带宽的代理服务器。如果你想要一个完整的java解决方案,你可以使用一个简单的socket java代理服务器here,并用Thread.sleep或任何其他方式减慢从streams的读/写过程。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3947621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档