api限流
This commit is contained in:
parent
b838921f74
commit
0ffb5f892d
|
@ -0,0 +1,137 @@
|
|||
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
|
Loading…
Reference in New Issue