首页 > 解决方案 > 本地主机上的 Spring Boot 下载速度测试非常慢

问题描述

我使用 Spring Boot 应用程序和 NodeJS 应用程序编写了一个非常基本的速度测试。我的 NodeJS 最高可达 2.2Gbps,而我的 Spring Boot 应用最高可达 550 Mbps。我在 Spring Boot 中尝试了两种不同的实现,它们都产生相对相同的速度。

实施 1:(最高 550 Mbps)

private long downloadDuration = 10000;
private int downloadChunkSize = 1024 * 1024;

@GetMapping("/test")
public void downloadTest(HttpServletResponse response) throws IOException {
    OutputStream os = response.getOutputStream();
    final byte[] bytes = getRandomChunk();
    long endOn = System.currentTimeMillis() + downloadDuration;

    while (System.currentTimeMillis() <= endOn) {
        os.write(bytes, 0, downloadChunkSize);
    }

    os.close();
}

实施 2(高达 500 Mbps)

@GetMapping("/test2")
public StreamingResponseBody downloadTest2() {

    final byte[] bytes = getRandomChunk();
    final long endOn = System.currentTimeMillis() + downloadDuration;

    return new StreamingResponseBody() {
        @Override
        public void writeTo(OutputStream out) throws IOException {
            while (System.currentTimeMillis() <= endOn) {
                out.write(bytes);
            }
        }
    };
}

使用 NodeJS an XHRRequest,我可以轻松达到 2.2 Gpbs。

知道我做错了什么吗?

供参考:

private byte[] getRandomChunk() {
    final byte[] bytes = new byte[1024 * 1024];
    ThreadLocalRandom.current().nextBytes(bytes);
    return bytes;
}

和 NodeJS 代码:

const requestHandler = (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');

    const startTime = new Date();
    const endOn = new Date(startTime.getTime() + 10000);
    const chunkSize = 1024 * 1024;

    const chunk = 'a'.repeat(chunkSize);

    const sendNext = () => {
        response.write(chunk, undefined, () => {
            if (new Date() <= endOn) {
                sendNext();
            } else {
                response.end();
            }
        });
    };

    sendNext();
};

const testServer = http.createServer(requestHandler);

这是前端速度测试的最小工作示例:

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>

<div id="speed" style="font-size: 41px;">0 Mbps</div>

<script type="text/javascript">
    const url = 'http://localhost:3001';

    const nThreads = 4;
    const method = 'GET';

    const speedLabel = document.getElementById('speed');

    let totalDownloaded = 0;
    let mainStart;
    let totalElapsed = 0;

    function download(i) {

        let downloaded = 0;

        const dl = new XMLHttpRequest();

        dl.onload = function (e) {
            console.log('[%d] Done', i);
            dl.abort(); // Done, Empty RAM
        };

        dl.onprogress = function (e) {
            const previousDownloaded = downloaded;
            downloaded = e.loaded;

            // Update global variables
            totalDownloaded += downloaded - previousDownloaded;
            totalElapsed = (performance.now() - mainStart) / 1000;
            totalSpeed = 8 * (totalDownloaded / 1000000) / totalElapsed;

            // Update UI
            speedLabel.innerHTML = (totalSpeed) + ' Mbps';
        };

        dl.open(method, url + '?threadId=' + i + '&nocache=' + Math.round(Math.random() * 1000000000));
        dl.send();
    }

    window.onload = function () {
        mainStart = performance.now();
        for (let i = 0; i < nThreads; i++) {
            download(i);
        }
    };
</script>
</body>
</html>

标签: javaspringspring-boot

解决方案


推荐阅读