1 Star 0 Fork 0

golang库 / api限流

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
index.go 5.50 KB
一键复制 编辑 原始数据 按行查看 历史
李旭 提交于 2024-01-23 15:08 . 过期时间保底
package lxlimit
import (
"encoding/json"
"fmt"
"gitee.com/lxgow/lxconv"
"github.com/astaxie/beego/logs"
redigo "github.com/garyburd/redigo/redis"
"hash/fnv"
"strconv"
"strings"
)
// api限流
// 创建时间:2023/11/24 11:23
// 创建人:lixu
type LimitConfig struct {
Redis MapRedisConfig `json:"redis"`
Func MFuncConfig `json:"func"`
}
type MFuncItem struct {
Name string `json:"name"`
Times int `json:"times"` // 每几秒
Nums int `json:"nums"` // 限制多少次
}
type MFuncConfig struct {
FunName string `json:"fun_name"`
Open bool `json:"open"`
Ip MFuncItem `json:"ip"`
Kernel MFuncItem `json:"kernel"`
BodyBy []byte `json:"bodyBy"`
Url string `json:"url"`
Params map[string]string `json:"params"`
DelGameIDS []string `json:"delGameIDS"` // 删除某个游戏
Member MFuncItem `json:"member"`
}
type LimitVar struct {
RedisConfig MapRedisConfig
RedisPool *redigo.Pool
FuncConfig MFuncConfig
}
var LXLIMITCL LimitVar
// InitDefault 初始化
func InitDefault(cfg LimitConfig) (err error) {
err = initRedis(cfg.Redis)
if err != nil {
logs.Error("InitDefault", "initRedis error::", err)
return
}
LXLIMITCL.FuncConfig = cfg.Func
return
}
// CheckLimit 检查是否超 出限制
func CheckLimit(cfg MFuncConfig) (gameid, tp string) {
var (
times = 0
postdata map[string]interface{}
)
postdata = make(map[string]interface{})
if len(cfg.BodyBy) > 0 {
_ = json.Unmarshal([]byte(cfg.BodyBy), &postdata)
if postdata["gameid"] != nil {
gameid = lxconv.ToString(postdata["gameid"])
}
}
if !LXLIMITCL.FuncConfig.Open || cfg.FunName == "" {
return
}
if len(cfg.DelGameIDS) > 0 {
if cfg.Url != "" {
for _, gameid := range cfg.DelGameIDS {
if strings.Contains(cfg.Url, gameid) {
tp = "gameid"
break
}
}
if tp != "" {
return
}
}
if postdata["gameid"] != nil {
pgameid := lxconv.ToString(postdata["gameid"])
for _, gid := range cfg.DelGameIDS {
if pgameid == gid {
tp = "gameid"
break
}
}
if tp != "" {
return
}
}
}
if cfg.Ip.Name != "" {
if cfg.Ip.Times == 0 {
cfg.Ip.Times = LXLIMITCL.FuncConfig.Ip.Times
}
if cfg.Ip.Nums == 0 {
cfg.Ip.Nums = LXLIMITCL.FuncConfig.Ip.Nums
}
}
if cfg.Kernel.Name != "" {
if cfg.Kernel.Times == 0 {
cfg.Kernel.Times = LXLIMITCL.FuncConfig.Kernel.Times
}
if cfg.Kernel.Nums == 0 {
cfg.Kernel.Nums = LXLIMITCL.FuncConfig.Kernel.Nums
}
}
if cfg.Member.Times == 0 {
cfg.Member.Times = LXLIMITCL.FuncConfig.Member.Times
}
if cfg.Member.Nums == 0 {
cfg.Member.Nums = LXLIMITCL.FuncConfig.Member.Nums
}
_rds := LXredis{}
ipif := (cfg.Ip.Times > 0 && cfg.Ip.Name != "")
if ipif {
_rds.Name = "ip::" + cfg.Ip.Name
_rds.Name += getRedisKey(cfg.FunName, cfg.Ip.Name)
// ip
if isx, _ := _rds.IsExist(); isx {
gstr, _ := _rds.GET()
if gstr != "" {
times, _ = strconv.Atoi(gstr)
if times >= cfg.Ip.Nums {
tp = "ip"
return
}
}
_rds.INCR()
//logs.Error("ip:::11::", lxconv.JsonEncode(cfg.Ip))
} else {
//logs.Error("ip:::22::", lxconv.JsonEncode(cfg.Ip))
_rds.Val = "1"
_rds.setTime(cfg.Ip.Times)
}
ex, _ := _rds.TTL()
if ex < 0 {
_rds.EXPIRE(cfg.Ip.Times)
}
}
if ipif && cfg.Kernel.Times > 0 && cfg.Kernel.Name != "" {
_rds.Name = "kernel::" + cfg.Ip.Name
_rds.Name += getRedisKey(cfg.FunName, cfg.Ip.Name, cfg.Kernel.Name)
// ip
if isx, _ := _rds.IsExist(); isx {
gstr, _ := _rds.GET()
if gstr != "" {
times, _ = strconv.Atoi(gstr)
if times >= cfg.Kernel.Nums {
tp = "kernel"
return
}
}
_rds.INCR()
//logs.Error("Kernel:::11::", lxconv.JsonEncode(cfg.Kernel))
} else {
_rds.Val = "1"
_rds.setTime(cfg.Kernel.Times)
//logs.Error("Kernel:::22::", lxconv.JsonEncode(cfg.Kernel))
}
ex, _ := _rds.TTL()
if ex < 0 {
_rds.EXPIRE(cfg.Kernel.Times)
}
}
var uid string
if cfg.Member.Name != "" {
if strings.Contains(cfg.Member.Name, "{gameid}") && postdata["gameid"] != nil {
gameid = lxconv.InterfaceToStr(postdata["gameid"])
cfg.Member.Name = strings.Replace(cfg.Member.Name, "{gameid}", gameid, -1)
}
if strings.Contains(cfg.Member.Name, "{uid}") && postdata["uid"] != nil {
uid = lxconv.InterfaceToStr(postdata["uid"])
cfg.Member.Name = strings.Replace(cfg.Member.Name, "{uid}", uid, -1)
}
}
if cfg.Member.Times > 0 && cfg.Member.Name != "" {
_rds.Name = "member::" + cfg.Member.Name
_rds.Name += getRedisKey(cfg.FunName)
// ip
if isx, _ := _rds.IsExist(); isx {
gstr, _ := _rds.GET()
if gstr != "" {
times, _ = strconv.Atoi(gstr)
if times >= cfg.Member.Nums {
tp = "member"
return
}
}
_rds.INCR()
//logs.Error("Member:::11::", lxconv.JsonEncode(cfg.Member))
} else {
_rds.Val = "1"
_rds.setTime(cfg.Member.Times)
//logs.Error("Member:::22::", lxconv.JsonEncode(cfg.Member))
}
ex, _ := _rds.TTL()
if ex < 0 {
_rds.EXPIRE(cfg.Member.Times)
}
}
return
}
func hashMod(key string, modulus int) int {
// 使用FNV哈希算法计算哈希值
hash := fnv.New32a()
hash.Write([]byte(key))
hashValue := hash.Sum32()
// 对哈希值取模得到结果
result := int(hashValue % uint32(modulus))
return result
}
func getRedisKey(ccs ...interface{}) (k string) {
var pms string
for _, cc := range ccs {
pms += lxconv.InterfaceToStr(cc)
}
mds := hashMod(pms, 100000)
k = "::" + lxconv.EncryMD5(pms)
k += fmt.Sprintf("%d", mds)
return
}
Go
1
https://gitee.com/lxgow/lxlimit.git
git@gitee.com:lxgow/lxlimit.git
lxgow
lxlimit
api限流
7635ac62b21d

搜索帮助