如何在 Java 中限制带宽?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3947621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I limit bandwidth in Java?
提问by Koerr
I wrote a Java scheduler, every hour using:
我写了一个 Java 调度程序,每小时使用:
new SAXBuilder().build(new URL(xxx));
or
或者
HttpConnection.connect(new URL(xxx)); // jsoup library code
to get a big XML/HTML file.
得到一个大的 XML/HTML 文件。
My server maximum bandwidth limit is 2Mbits.
我的服务器最大带宽限制是 2Mbits。
When this Java schedule code runs, I use over 2Mbits of bandwidth. (check it out)
当这个 Java 调度代码运行时,我使用了超过 2Mbits 的带宽。(检查出来)
So every time a user visits my server it is too slow.
所以每次用户访问我的服务器时都太慢了。
How do I limit my Java schedule to use lower bandwidth? (ex. 500Kbits)
如何限制我的 Java 计划以使用较低的带宽?(例如 500Kbits)
I am using Ubuntu server.
我正在使用 Ubuntu 服务器。
采纳答案by Stephen C
There's no elegant way to do this.
没有优雅的方法可以做到这一点。
A simple but inelegant way would be to write a Java stream wrapper that limits the rate at which bytes are read from the wrapped Stream. For instance, if you wanted to limit to 1000 bytes per second, the int read()
method could be implemented as follows:
一种简单但不优雅的方法是编写一个 Java 流包装器,它限制从包装的 Stream 中读取字节的速率。例如,如果您想限制为每秒 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;
}
It is worth noting that throttling rates like this can have negative as well as positive effects. On the negative side:
值得注意的是,像这样的节流率可能会产生消极和积极的影响。在消极方面:
It ties down resources on the server side for longer. In this case, we are talking about the Java thread that is handling the download, and memory in kernel space is used to buffer received network packets until the application reads them.
It may also lead to morenetwork traffic. The problem is that this kind of throttling will disrupt the smooth flow of packets. The server will only buffer a relatively small number of packets, and when that number is exceeded, it has to tell the client to STOP for now. This requires extra signalling packets (ACKs) and there will probably be data packets dropped in the process. Eventually, those data packets will need to be retransmitted.
它将服务器端的资源束缚得更久。在这种情况下,我们讨论的是处理下载的 Java 线程,内核空间中的内存用于缓冲接收到的网络数据包,直到应用程序读取它们。
它还可能导致更多的网络流量。问题是这种节流会破坏数据包的顺畅流动。服务器只会缓冲相对较少数量的数据包,当超过该数量时,它必须告诉客户端暂时停止。这需要额外的信令包 (ACK),并且可能会在此过程中丢弃数据包。最终,这些数据包将需要重新传输。
回答by Franck
Theory:
理论:
Token Bucket Algorithmis a way to limit a download's bandwidth. You should read this article: it explains the use of this algorithm.
令牌桶算法是一种限制下载带宽的方法。你应该阅读这篇文章:它解释了这个算法的使用。
Implementations:
实现:
RateLimiter from Google Guava
来自 Google Guava 的 RateLimiter
Google Guava 22.0 include a RateLimiterclass but it is still in beta.
Google Guava 22.0 包含一个RateLimiter类,但它仍处于测试阶段。
From api documentation:
来自 api 文档:
As an example, imagine that we have a list of tasks to execute, but we don't want to submit more than 2 per second:
例如,假设我们有一个要执行的任务列表,但我们不想每秒提交超过 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);
}
}
As another example, imagine that we produce a stream of data, and we want to cap it at 5kb per second. This could be accomplished by requiring a permit per byte, and specifying a rate of 5000 permits per second:
再举一个例子,假设我们产生了一个数据流,我们希望将其限制在每秒 5kb。这可以通过要求每字节一个许可并指定每秒 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 from Apache Commons Lang v3
来自 Apache Commons Lang v3 的 TimedSemaphore
Apache Commons Lang v3 include a TimedSemaphoreclass that can be used to implement a rate limit.
Apache Commons Lang v3 包含一个TimedSemaphore类,可用于实现速率限制。
回答by Jilles van Gurp
Take a look at this thread: http://httpcomponents.10934.n7.nabble.com/throttlling-download-traffic-td18329.html
看看这个线程:http: //httpcomponents.10934.n7.nabble.com/throttlling-download-traffic-td18329.html
Also, if you use apache httpclient you can configure it to use gzip compression and save a bit of bandwidth. Particularly with xml, you should expect a lot less bytes transferred this way.
此外,如果您使用 apache httpclient,您可以将其配置为使用 gzip 压缩并节省一些带宽。特别是对于 xml,您应该期望以这种方式传输的字节少得多。
回答by PbxMan
A possible solution would be to use a Proxy Serverthat limits bandwidth. if you want a full java solution you can use a simple socket java proxy server hereand slow down the reading/writing from streams process with Thread.sleep or any other way.
一种可能的解决方案是使用限制带宽的代理服务器。如果你想要一个完整的 java 解决方案,你可以在这里使用一个简单的 socket java 代理服务器,并用 Thread.sleep 或任何其他方式减慢流进程的读/写速度。