Java带宽限速器、Springboot限速器

Java限速器,设计思路
1.假设下载或上传速度上限是: m(KB/s),那么发送一个固定的字节数据[假设是n字节(Bytes)]
时间花费 -> 单位:毫秒 == 1000 * n/(m*1024)
2.假设发送n字节的数据只花费了t毫秒,
那么发送线程就应该睡眠(毫秒): 1000 * n/(m*1024)- t毫秒

java实现代码

public class SpeedLimiter {

    /** 速度上限(KB/s), 0=不限速 */
    private int maxRate = 1024;
    private long getMaxRateBytes(){
        return this.maxRate * 1024;
    }
    private long getLessCountBytes() {
        long lcb = getMaxRateBytes() / 10;
        if (lcb < 10240) lcb = 10240;
        return lcb;
        //return 1024l * 20;
    }
    public SpeedLimiter(int maxRate) {
        this.setMaxRate(maxRate);
    }
    public synchronized void setMaxRate(int maxRate){
        this.maxRate = maxRate < 0 ? 0 : maxRate;
    }
    private long totalBytes = 0;
    private long tmpCountBytes = 0;
    private long lastTime = System.currentTimeMillis();
    /**
     * @author Ethan
     * @date 2022-11-18
     * @param len       send bytes
     * @description 计算线程延时
     * sendTime(Ms) = nowTime - lastTime;
     * workTime(Ms) = (totalBytes*1000)/(maxRate*1024)
     * delayTime(Ms) = workTime-sendTime
     **/
    public synchronized void delayNextBytes(int len) {
        if (maxRate <= 0) return;
        totalBytes += len;
        tmpCountBytes += len;
        //未达到指定字节数跳过...
        if (tmpCountBytes < getLessCountBytes()) {
            return;
        }
        long nowTime = System.currentTimeMillis();
        long sendTime = nowTime - lastTime;
        long workTime = (totalBytes * 1000) / getMaxRateBytes();
        long delayTime = workTime - sendTime;
        if (delayTime > 0) {
            try {
                Thread.sleep(delayTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tmpCountBytes = 0;
        }
    }
}

集成到Springboot进行下载测试

 DownloadController代码

@RestController
@RequestMapping(value = "/api/v1/download")
public class DownloadController {

    //设置一个本地文件用于下载测试, 大小约几百MB
    final String localFile = "E:/tmp/A2.tar.gz";

    /**
     * @author Ethan
     * @date 2022-11-18
     * @description 普通下载测试, 不限速!
     **/
    @GetMapping("getFile")
    public void getFile(HttpServletResponse response) {
        File file = this.getLocalFile(response, localFile);
        if (file == null || !file.exists()) {
            return;
        }
        InputStream is = null;
        OutputStream out = null;
        try {
            is = new FileInputStream(file);
            out = response.getOutputStream();
            IOUtils.copyLarge(is, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * @author Ethan
     * @date 2022-11-18
     * @description 限速下载测试, xxx KB/s
     **/
    @GetMapping("limit")
    public void limit(
            @RequestParam(value = "speed", defaultValue = "500", required = false) int speed,
            HttpServletResponse response
    ) {
        File file = this.getLocalFile(response, localFile);
        if (file == null || !file.exists()) {
            return;
        }
        BufferedInputStream bis = null;
        OutputStream out = null;

        try {
            bis = new BufferedInputStream(new FileInputStream(file));
            out = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            SpeedLimiter speedLimiter = new SpeedLimiter(speed);
            while ((length = bis.read(buffer)) != -1) {
                out.write(buffer, 0, length);
                if (speedLimiter != null) {
                    speedLimiter.delayNextBytes(length);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(bis);
            IOUtils.closeQuietly(out);
        }
    }

    private File getLocalFile(HttpServletResponse response, String fullPath){
        File file = new File(fullPath);
        if (file.exists()) {
            String fileName = file.getName();
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setHeader("Content-Type", "application/x-zip-compressed");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        } else {
            String noteMsg = "本地测试文件[" + file + "]不存在";
            System.err.println(noteMsg);
            this.setResponse(response, noteMsg);
        }
        return file;
    }
    private final static String CharacterEncoding = "UTF-8";
    private final static String MediaType = "application/json";
    private void setResponse(HttpServletResponse res, String noteMsg) {
        try {
            int httpStatus = HttpStatus.OK.value();
            res.setCharacterEncoding(CharacterEncoding);
            res.setContentType(MediaType);
            res.setStatus(httpStatus);
            res.getWriter().write(noteMsg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


启动Springboot

使用firefox浏览器分别测试
限速下载(500KB/s)   http://127.0.0.1:8080/api/v1/download/limit

限速下载(900KB/s)   http://127.0.0.1:8080/api/v1/download/limit?speed=900

经过测试,可以满足需求!

完整demo下载地址
https://download.csdn.net/download/tianbbs2008/87126141

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在OpenWrt中配置带宽限速有两种方式:使用LuCI界面和使用命令行。 使用LuCI界面进行带宽限速配置: 1. 登录OpenWrt路由的管理界面,进入“Network”菜单,点击“Firewall”子菜单; 2. 在“Traffic Rules”标签页中,点击“Add”按钮,创建一个新的限速规则; 3. 在“General Settings”选项卡中,设置限速规则的名称、描述、协议、源地址、目标地址、目标端口等信息; 4. 在“Advanced Settings”选项卡中,设置限速规则的带宽限制参数,包括最大上传速度、最大下载速度、最大连接数等; 5. 点击“Save & Apply”按钮,保存并应用新的限速规则。 使用命令行进行带宽限速配置: 1. SSH登录OpenWrt路由的终端界面; 2. 运行以下命令,创建一个新的限速规则: ``` iptables -A FORWARD -s <source_ip> -d <destination_ip> -p <protocol> --dport <destination_port> -m conntrack --ctstate NEW -j QOS ``` 其中,`<source_ip>`是源地址,`<destination_ip>`是目标地址,`<protocol>`是协议(如TCP或UDP),`<destination_port>`是目标端口; 3. 运行以下命令,设置限速规则的带宽限制参数: ``` tc qdisc add dev <interface> root handle 1: htb default 10 tc class add dev <interface> parent 1: classid 1:1 htb rate <max_upload_speed> tc class add dev <interface> parent 1:1 classid 1:10 htb rate <max_download_speed> ``` 其中,`<interface>`是网络接口名称,`<max_upload_speed>`是最大上传速度,`<max_download_speed>`是最大下载速度; 4. 运行以下命令,将限速规则应用到QoS队列中: ``` iptables -t mangle -A QOS -j MARK --set-mark 1 tc filter add dev <interface> parent 1: protocol ip prio 16 handle 1 fw flowid 1:1 ``` 5. 运行以下命令,保存并应用新的限速规则: ``` /etc/init.d/firewall restart ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱喝咖啡的程序猿

写博不易且看且珍惜,打赏最给力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值