前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Web应用程序限速方法

Web应用程序限速方法

作者头像
jeremyxu
发布2018-05-10 14:37:49
3.1K0
发布2018-05-10 14:37:49
举报
文章被收录于专栏:jeremy的技术点滴

一般来说Web应用程序的开发者不太关心网络限速的问题。所以通常写的程序逻辑基本认为用户提交上来的数据速率越快越好;用户下载文件时,下载越快越好。但现实情况是服务器的带宽不是无限的,通常我们并不希望某一个用户的极速下载导致其它用户感觉此Web应用程序不可用。这样就带来了网络速率的需求。我在实际工作中大概总结出好几种限速办法,在这里记录以备忘。

ngx_http_core_module限制下载速率

最简单是直接使用ngx_http_core_module中的limit_ratelimit_rate_after指令,如下

代码语言:javascript
复制
location /flv/ {
    alias /www/flv/;
    limit_rate_after 500k;
    limit_rate       50k;
}

limit_rate可限制响应传输至浏览器客户端的速率,limit_rate_after表示浏览器客户端下载多少后才可以执行限速(使下载小文件不受限,下载大文件才限速)。

limit_rate还有一种配合后端被代理服务器的用户,如下

代码语言:javascript
复制
location /download/ {
    proxy_pass http://127.0.0.1:8080/download/; # proxied server return "X-Accel-Limit-Rate" response header
}

后端被代理服务器可返回X-Accel-Limit-Rate响应头,nginx将根据这个响应头设置的值进行限速。这样就可以灵活控制限速的逻辑(比如有些用户下载不限速,有些用户下载限速,而且限速的数值也可根据不同用户身份而不同)

nginx-upload-module限制上传速率

代码语言:javascript
复制
location /upload {
        # 转到后台处理URL,表示Nginx接收完上传的文件后,然后交给后端处理的地址
        upload_pass @backend;

        # 临时保存路径, 可以使用散列
        # 上传模块接收到的文件临时存放的路径, 1 表示方式,该方式是需要在/tmp/nginx_upload下创建以0到9为目录名称的目录,上传时候会进行一个散列处理。
        upload_store /tmp/nginx_upload;

        # 上传文件的权限,rw表示读写 r只读
        upload_store_access user:rw group:rw all:rw;

        set $upload_field_name "file";
        # upload_resumable on;

        # 这里写入http报头,pass到后台页面后能获取这里set的报头字段
        upload_set_form_field "${upload_field_name}_name" $upload_file_name;
        upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;
        upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;

        # Upload模块自动生成的一些信息,如文件大小与文件md5值
        upload_aggregate_form_field "${upload_field_name}_md5" $upload_file_md5;
        upload_aggregate_form_field "${upload_field_name}_size" $upload_file_size;

        # 允许的字段,允许全部可以 "^.*$"
        upload_pass_form_field "^.*$";
        # upload_pass_form_field "^submit$|^description$";

        # 每秒字节速度控制,0表示不受控制,默认0, 128K
        upload_limit_rate 0;

        # 如果pass页面是以下状态码,就删除此次上传的临时文件
        upload_cleanup 400 404 499 500-505;

        # 打开开关,意思就是把前端脚本请求的参数会传给后端的脚本语言,比如:http://192.168.1.251:9000/upload/?k=23,后台可以通过POST['k']来访问。
        upload_pass_args on;
    }

    location @backend {
        proxy_pass http://127.0.0.1:8080/process_upload;
    }

upload_limit_rate即可对上传速率进行限制。

ngx_stream_proxy_module限制上传下载速率

代码语言:javascript
复制
server {
    listen 81;
    proxy_pass 127.0.0.1:8081;
    proxy_download_rate 200k;
    proxy_upload_rate 200k;
}

使用ngx_stream_proxy_module的好处时只要是tcp或udp协议且使用nginx作反向代理,都可以限速。proxy_download_rate可限制下载速率,proxy_upload_rate可限制上传速率。

Java使用Guava的RateLimiter进行限速

上面说的全是使用nginx配置的方式进行限速,当有很特殊需求时,我们也可以使用程序来限速,如Java可使用GuavaRateLimiter进行限速。

RateLimiter 从概念上来讲,速率限制器会在可配置的速率下分配许可证。如果必要的话,每个acquire() 会阻塞当前线程直到许可证可用后获取该许可证。一旦获取到许可证,不需要再释放许可证。

RateLimiter使用的是一种叫令牌桶的流控算法,RateLimiter会按照一定的频率往桶里扔令牌,线程拿到令牌才能执行,比如你希望自己的应用程序QPS不要超过1000,那么RateLimiter设置1000的速率后,就会每秒往桶里扔1000个令牌。(这个跟nginx的ngx_http_limit_req_module中用到的leaky bucket是一个意思)

RateLimiter经常用于限制对一些物理资源或者逻辑资源的访问速率。与Semaphore 相比,Semaphore 限制了并发访问的数量而不是使用速率。

RateLimiter几个关键的方法

  • static RateLimiter create(double permitsPerSecond) 根据指定的稳定吞吐率创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少查询)
  • static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) 根据指定的稳定吞吐率和预热期来创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少个请求量),在这段预热时间内,RateLimiter每秒分配的许可数会平稳地增长直到预热期结束时达到其最大速率。(只要存在足够请求数来使其饱和)
  • double acquire(int permits) 从RateLimiter获取指定许可数,该方法会被阻塞直到获取到请求
  • void setRate(double permitsPerSecond) 动态更新RateLimite的稳定速率,参数permitsPerSecond 由构造RateLimiter的工厂方法提供。
  • boolean tryAcquire(int permits) 从RateLimiter 获取许可数,如果该许可数可以在无延迟下的情况下立即获取得到的话
  • boolean tryAcquire(int permits, long timeout, TimeUnit unit) 从RateLimiter 获取指定许可数如果该许可数可以在不超过timeout的时间内获取得到的话,或者如果无法在timeout 过期之前获取得到许可数的话,那么立即返回false (无需等待)

使用示例

限制写入response的速率不超过200kB/s

代码语言:javascript
复制
RateLimiter limiter = RateLimiter.create(1024*200);
while(....){
  byte[] bytes = ...
  limiter.acquire(bytes.length);
  response.getWriter().write(bytes);
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ngx_http_core_module限制下载速率
  • nginx-upload-module限制上传速率
  • ngx_stream_proxy_module限制上传下载速率
  • Java使用Guava的RateLimiter进行限速
    • RateLimiter几个关键的方法
      • 使用示例
      相关产品与服务
      云服务器
      云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档