论坛首页 编程语言技术论坛

Memcached的另类用途 - Rate Limit

浏览 2676 次
精华帖 (0) :: 良好帖 (11) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-03-29  
我们通常用memcached来做缓存来提高系统性能,其实它不仅仅是一个缓存工具,我们还可以用它来做其他用途,比如下列常见的需求:
1. 避免服务器的负担太大,限制Open API的调用次数
2. 避免恶意尝试密码,限制登录错误次数

这2个需求的共同特点是要能够统计在某个时间段内,某个操作被执行了多少次,利用memcached的失效时间和它的incr指令,可以很方便地实现,直接上代码:
module RateLimit
  class OverRateLimitError < StandardError; end

  def over_limit?(key, options, &block)
    requests = Rails.cache.increment("RateLimit/#{key}")
    if requests.nil?
      Rails.cache.write("RateLimit/#{key}", 1, :expires_in => options[:per].minutes)
      requests = 1
    end
    if requests > options[:requests]
      raise OverRateLimitError.new
    else
      block.call
    end
  end

  def reset_limit(key)
    key.gsub!(/\s/, '')
    Rails.cache.delete("RateLimit/#{key}")
  end
end

Rails.cache是rails带的一个memcached封装,你也可以直接用memcached client自己来写。

使用这个代码很容易,以需求1为例子,我们可以include这个module,然后在需要统计的某个api调用(可用around_filter将这个代码简化):
      begin
        #每小时不能超过360次api调用
        over_limit?("Api/#{key}", :per => 60, :requests => 360) {
          #真正的api代码段
        }
      rescue OverRateLimitError
        render :text => "error.api.over.limit", :status => 400 and return false
      end

这里的key,你可以根据客户端ip+api名称或者授予客户端的key来生成。

你也在用memcached做缓存之外的用途吗?欢迎交流。

延伸阅读:Python的实现
   发表时间:2009-03-30  
我有个比较简单的,就是保存随机值。 把memcache当作一个全局的变量保存器.

某个项目,我不想直接把ID值暴露给用户,于是每个用户分配一个随机值,然后顺序递加,做为一个伪ID,出现在UI上,而当前的最新值,都是存在memcache中的。这样部署起来就不用考虑太多


0 请登录后投票
   发表时间:2010-03-22  
一个Rack中间件throttle:
http://datagraph.rubyforge.org/rack-throttle/

提供相同的功能和更完善的封装,支持更多的计数存储(memcached/redis/...)
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics