|
- class ApiLimitService < ApplicationService
- Error = Class.new(StandardError)
-
- def initialize() end
-
- def call
-
- end
-
- # 时间窗口法
- def is_action_allowed?(user_id, action_key, period, max_count)
- key = "#{user_id}:#{action_key}"
- count = $redis_cache.multi do |multi|
- multi.incr(key)
- multi.expire(key, period)
- end
- count[0] <= max_count
- end
-
- # 漏桶法
- def is_action_allowed_bucket?(user_id, action_key, capacity, rate)
- key = "#{user_id}:#{action_key}"
- # now = (("%10.3f" % Time.now.to_f).to_f * 1000).to_i
- now = Time.now.to_i
- count = $redis_cache.multi do |multi|
- multi.zadd(key, now, SecureRandom.uuid.gsub("-", ""))
- multi.zremrangebyscore(key, 0, now - capacity)
- multi.zcard(key)
- multi.expire(key, (capacity / rate + 1).to_i)
- end
- # puts "count1==#{count}"
- # puts "count2==#{count[2]}"
- count[2] <= capacity
- end
-
- def is_action_allowed_aaa?(user_id, action_key, period, maxCount)
- key = "#{user_id}:#{action_key}"
- now = (("%10.3f" % Time.now.to_f).to_f * 1000).to_i
- count = $redis_cache.multi do |multi|
- # 添加命令
- multi.zadd(key, now, SecureRandom.uuid.gsub("-", ""))
- # 清楚无用数据
- multi.zremrangebyscore(key, 0, now - period * 1000)
- # 判断规定时间内请求数量
- multi.zcard(key)
- # 重新设置过期时间
- multi.expire(key, period + 1)
- end
- # puts "count1==#{count}"
- # puts "count2==#{count[2]}"
- count[2] <= maxCount
- end
-
- def sdfsf
-
- # 每秒钟漏斗的容量
-
- capacity = 10
-
-
- # 漏斗填充速度
-
- leak_rate = 0.3
-
- # 当前漏斗中的水量
-
- current_volume = 0
-
- # 上一次漏水的时间
-
- last_leak_time = Time.now.to_i
-
- funnel_name = "tests"
-
- # $redis_cache.hset(funnel_name, "volume", capacity)
- $redis_cache.hset(funnel_name, "last_leak_time", Time.now.to_i)
-
- # 构造事务命令
-
- # result = $redis_cache.multi do |pipe|
- # # 把当前时间与上一次漏水时间的差值,作为漏斗流出水量
- #
- # pipe.hget(funnel_name, "last_leak_time")
- #
- # pipe.hset(funnel_name, "last_leak_time", Time.now.to_i)
- #
- # pipe.hget(funnel_name, "volume")
- #
- # pipe.hget(funnel_name, "capacity")
- #
- # pipe.hget(funnel_name, "leak_rate")
- # end
-
- current_volume = $redis_cache.hget(funnel_name, "volume")
- last_leak_time = $redis_cache.hget(funnel_name, "last_leak_time")
- # 先漏水
- leaked_volume = (Time.now.to_i - last_leak_time.to_i) * leak_rate.to_f
-
- current_volume = [current_volume.to_f + leaked_volume, capacity.to_f].sort.first
- puts "current_volume====#{current_volume}"
- # 判断是否可以通过请求
- if current_volume >= 1
- $redis_cache.hset(funnel_name, "volume", current_volume.to_i - 1)
- # $redis_cache.hset(funnel_name, "last_leak_time", Time.now.to_i)
- true
- else
- false
- end
-
- end
-
- def done_test3
- 100.times.each do |t|
- if t % 2== 0
- sleep(1)
- end
- puts "#{t}:res====#{sdfsf}"
- end
- end
-
- def done_test
- 100.times.each do |t|
- if t % 10== 0
- sleep(5)
- end
- puts "#{t}:res====#{is_action_allowed_bucket?("123", "test2", 10, 0.2)}"
- end
- end
-
- def done_test2
- 100.times.each do |t|
- sleep(1)
- puts "#{t}:res====#{is_action_allowed_aaa?("123", "test3", 10, 5)}"
- end
- end
-
- end
|