使用okio的Throttler类实现IO限速(文件拷贝限速、文件下载限速)
背景
在开发文件流相关的应用时,为了保护磁盘使用率或者防止网络带宽被单个用户占满,需要对文件流采取限速策略,包括磁盘文件读写限速和文件下载限速。
Okio
Okio是 Square 公司开发的一个高效 I/O 库,用于简化 Java 和 Android 中的 I/O 操作。Throttler是 Okio中的一个类,主要用于限制带宽(速率限制),以防止读取或写入数据时占用过多网络或磁盘资源。
Throttler主要用于节流(throttle)。它可以配置读/写操作的最大速率(字节/秒),从而控制数据流量。例如,当你不想让某个操作占满全部带宽时,就可以使用Throttler。
本地文件读取限速代码
File sourceFile = new File("/Users/mac/Downloads/test.pdf");
File sinkFile = new File("/Users/mac/Downloads/copy.pdf");
Throttler throttler = new Throttler();
// 限速为 1024KB/s
throttler.bytesPerSecond(1024 * 1024L);
StopWatch watch = new StopWatch();
watch.start();
try (
BufferedSource source = Okio.buffer(Okio.source(sourceFile));
BufferedSink sink = Okio.buffer(Okio.sink(sinkFile))
) {
sink.writeAll(throttler.source(source));
} catch (Exception e) {
e.printStackTrace();
}
watch.stop();
System.out.println("耗时: " + watch.getTotalTimeSeconds() + " 秒");
test.pdf文件大小为5.4MB,耗时打印日志:
耗时: 5.240336792 秒
使用OkHttp做客户端下载文件限速参考代码
@GetMapping("/download")
void proxy(
@RequestHeader HttpHeaders requestHeaders,
@RequestParam String link,
HttpServletResponse response
) throws Exception {
Request downloadRequest = new Request.Builder()
.url(link) // 文件链接地址
.headers(Headers.of(headers)) // 请求头
.build();
try (Response downloadResponse = client.newCall(downloadRequest).execute();
BufferedSource source = Okio.buffer(Okio.source(downloadResponse.body().byteStream()));
BufferedSink sink = Okio.buffer(Okio.sink(response.getOutputStream()))
) {
// 重写响应头信息
response.reset();
// todo重写响应头
Throttler throttler = new Throttler();
// 下载限速为 1024KB/s
throttler.bytesPerSecond(1024 * 1024L);
sink.writeAll(throttler.source(source));
} catch (Throwable e) {
throw e;
} finally {
response.getOutputStream().flush();
response.getOutputStream().close();
}
}

浙公网安备 33010602011771号