ruby-on-rails 对每个用户的Rails函数调用进行速率限制

yi0zb3m4  于 2023-05-02  发布在  Ruby
关注(0)|答案(2)|浏览(92)

有人知道我该怎么做吗?很难在网上找到信息。我发现最好的是curbit it gem,但我只能想到如何实现应用程序。

nzkunb0c

nzkunb0c1#

可通过以下方式处理:1)网络服务器2)机架应用程序。一切都取决于你需要什么。我们use内置nginx功能来限制API请求:

 limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
     limit_req zone=one burst=2;

另一个解决方案是rack-throttle
这是Rack中间件,它为Rack应用程序的传入HTTP请求提供速率限制逻辑。您可以在任何基于Rack的Ruby Web框架中使用Rack::Throttle,包括Ruby on Rails 3。0和Sinatra

wfypjpf4

wfypjpf42#

下面是一个如何使用Redis和时间戳实现它的例子。你应该在user中包含这个模块。rb,然后调用user.allowed_to?(:reveal_email)

# Lets you limit the number of actions a user can take per time period
# Keeps an integer timestamp with some buffer in the past and each action increments the timestamp
# If the counter exceeds Time.now the action is disallowed and the user must wait for some time to pass.

module UserRateLimiting

  class RateLimit < Struct.new(:max, :per)
    def minimum
      Time.now.to_i - (step_size * max)
    end

    def step_size
      seconds = case per
                when :month  then 18144000 # 60 * 60 * 24 * 30
                when :week   then 604800   # 60 * 60 * 24 * 7
                when :day    then 86400    # 60 * 60 * 24
                when :hour   then 3600     # 60 * 60
                when :minute then 60
                else raise 'invalid per param (day, hour, etc)'
                end
                seconds / max
    end
  end

  LIMITS = {
    :reveal_email => RateLimit.new(200, :day)
    # add new rate limits here...
  }

  def allowed_to? action
    inc_counter(action) < Time.now.to_i
  end

  private

  def inc_counter action
    rl = LIMITS[action]
    raise "couldn't find that action" if rl.nil?
    val = REDIS_COUNTERS.incrby redis_key(action), rl.step_size
    if val < rl.minimum
      val = REDIS_COUNTERS.set redis_key(action), rl.minimum
    end
    val.to_i
  end

  def redis_key action
    "rate_limit_#{action}_for_user_#{self.id}"
  end
end

相关问题