Commit b204f919 by wang

修改锁相关代码

parent 339584ee
......@@ -2,16 +2,16 @@
[default_redis_read]
host = 192.168.1.235:6379
password = icDb29mLy2s
max_idle = 1000
max_idle = 50
max_active = 5000
idle_timeout = 20
[default_redis_write]
host = 192.168.1.235:6379
password = icDb29mLy2s
max_idle = 1000
max_idle = 50
max_active = 5000
idle_timeout = 20
;存放redis所有键
[redis_all]
\ No newline at end of file
[redis_all]
package main
import (
"fmt"
"github.com/guonaihong/gout"
"github.com/ichunt2019/log"
"sync"
"time"
)
type Glimit struct {
n int
c chan struct{}
}
// initialization Glimit struct
func New(n int) *Glimit {
return &Glimit{
n: n,
c: make(chan struct{}, n),
}
}
// Run f in a new goroutine but with limit.
func (g *Glimit) Run(f func(n int),n int) {
g.c <- struct{}{}
//fmt.Println(n)
go func(n int) {
f(n)
<-g.c
}(n)
}
var wg2 = sync.WaitGroup{}
var log=NewLog()
/**
测试结果1 1000个请求,并发50 完成时间 36.1955874s
*/
func main() {
//main2()
//return
start:=time.Now()
number := 2001
g := New(200)
for i := 0; i < number; i++ {
wg2.Add(1)
s:=1000+i
//log.Info("d")
goFunc := func(n int) {
log.Info("d")
// 做一些业务逻辑处理
value:=fmt.Sprintf("%d",n)
SkuHandle(value)
wg2.Done()
}
g.Run(goFunc,s)
}
wg2.Wait()
//log.SyncWait()
end:=time.Now()
fmt.Println(end.Sub(start))
}
func main2() {
var log=NewLog()
for i := 0; i < 500; i++ {
fmt.Println(i)
log.Info("d")
fmt.Println(i,"end")
}
log.SyncWait()
}
func testHandle(value string) {
println(value)
}
func SkuHandle(value string) {
//url:="192.168.1.237:8005/saveSpu"
//gout.POST(config.Get("sku_server.api_domain").String()+"/synchronization")/*.Debug(true)*/.SetForm(gout.H{"goods_id": ids}).BindBody(&resStr).Do()
resStr:=""
url:="http://localhost:60006/GetSkuListPrice"
err:=gout.GET(url).SetForm(gout.H{"token": "AbopJDAbopdu800820mcspcq==","goods_id":"1160558405670174605,1160558403263797403,10048"}).BindBody(&resStr).Do()
if(err!=nil){
panic("调用sku server saveSpu接口报错"+err.Error())
}
fmt.Println(resStr)
}
func NewLog() logger.LogInterface{
logConfig := make(map[string]string)
logConfig["log_path"] = "logs/testSpu"
logConfig["log_chan_size"] = "100"
logConfig["open_sync"] = "1"
log,err:= logger.InitLogger("file", logConfig)
if err != nil {
panic(err.Error())
}
log.Init()
return log
}
\ No newline at end of file
......@@ -61,6 +61,8 @@ func whiteIp() {
"192.168.2.72",
"::1",
"192.168.2.241",
"192.168.1.1",
"192.168.2.129",
}
fmt.Println("白名单配置:"+redisKey)
......@@ -93,13 +95,13 @@ func businessInterfaceList() {
"totalMaxNum":10000,
},
jdToken+"_"+GetSkuListFull: map[string]interface{}{
"dayMaxNum":11,
"minMaxNum":5,
"dayMaxNum":1,
"minMaxNum":1,
"totalMaxNum":10000,
},
jdToken+"_"+GetSkuListPrice: map[string]interface{}{
"dayMaxNum":11,
"minMaxNum":5,
"dayMaxNum":6100,
"minMaxNum":2000,
"totalMaxNum":10000,
},
/*baiduToken+"_"+getSkuListByClass: map[string]interface{}{
......
......@@ -50,9 +50,4 @@ func (this *business) GetInterfaceConfig(interfaceName string) (configOne *inter
}
func UsedMinNum() {
}
func UsedDayNum() {
}
......@@ -84,5 +84,5 @@ func (this *Dao)incrRedisFlowNum(key string) (num int,err error){
common.PrintStdout().Printf("INCR redis "+key+"错误")
return 0,e.NewApiError("service err",FLOWERR1)
}
return num,err
return num,nil
}
......@@ -2,7 +2,9 @@ package open
import (
"golang_open_platform/pkg/common"
"golang_open_platform/pkg/e"
"golang_open_platform/pkg/gredis"
"sync"
"time"
)
......@@ -10,7 +12,7 @@ const (
INCRTYPEMIN = iota //分
INCRTYPEDAY //天
)
var lock sync.Mutex
type flowmeter struct {
dao *Dao
flowLimitType int //INCRTYPEMIN 分限制 INCRTYPEDAY 天限制
......@@ -22,7 +24,7 @@ func NewFlow(token string,interfaceName string) *flowmeter{
return &flowmeter{dao:&Dao{},token:token,interfaceName:interfaceName}
}
//获取redis key 和过期时间
//获取 对应的计数redis key 和过期时间
func (this *flowmeter) getFlowKeyAndEx() (key string,expireTime int64){
key="flowUse_"+this.token+"_"+this.interfaceName
switch this.flowLimitType {
......@@ -43,41 +45,100 @@ func (this *flowmeter) getFlowKeyAndEx() (key string,expireTime int64){
}
//设置流量限制类型 INCRTYPEMIN 分限制 INCRTYPEDAY 天限制
func (this *flowmeter) SetFlowKey(flowLimitType int) {
func (this *flowmeter) setFlowKey(flowLimitType int) {
this.flowLimitType=flowLimitType
}
//获取 已使用的流量数
func (this *flowmeter) GetNum()(int,error){
func (this *flowmeter) getNum()(int,error){
key,expireTime:=this.getFlowKeyAndEx()
this.addOnlyLock(key)//加锁
//获取计数 (读 redis key)
num,err:=this.dao.getRedisFlowNum(key)
//common.PrintStdout().Printf("读取 计数key:%s,num 为: %d",key,num)
if(err!=nil){
this.delOnlyLock(key)//解锁
return 0,err
}
if(num==0){//计数不存在(redis没有此key),就新建一个带有超时的key
err:=this.dao.setRedisFlowEx(key,expireTime)
//common.PrintStdout().Printf("计数key:%s,不存在,创建超时%d 的key",key,expireTime)
if(err!=nil){
this.delOnlyLock(key)//解锁
return 0,err
}
}
this.delOnlyLock(key)
return num,nil
}
/**
比较
*/
func (this *flowmeter) compare(maxNum int64) (error,bool){
num,err:=this.getNum()
if(err!=nil){
return err,false
}
if(int64(num)>=maxNum){
common.PrintStdout().Printf("最大流量为: %d < %d",int(maxNum),num)
return nil,false
}
return nil,true
}
/**
验证
*/
func (this *flowmeter) checkout(business *business) error{
interfaceConfig,err:=business.GetInterfaceConfig(this.interfaceName)//商家接口配置,包含一小时最大流量,一天最大流量
key,_:=this.getFlowKeyAndEx()
defer this.delOnlyLock(key)
this.addOnlyLock(key)//加锁
//lock.Lock()
//defer lock.Unlock()
//验证天流量限制
this.setFlowKey(INCRTYPEDAY)
err,isPass:=this.compare(interfaceConfig.dayMaxNum)
if(err!=nil){
return err
}
if(err!=nil){
return err
}
if(isPass==false){
return e.NewApiError("触发天级流控",FLOWERR4)
}
//分钟流量验证
this.setFlowKey(INCRTYPEMIN)
err,isPass=this.compare(interfaceConfig.minMaxNum)
if(err!=nil){
return err
}
if(isPass==false){
return e.NewApiError("触发分钟级流控",FLOWERR4)
}
//增加分钟计数
err=this.incr()
if(err!=nil){
return nil
}
//增加天计数
this.setFlowKey(INCRTYPEDAY)
err=this.incr()
if(err!=nil){
return err
}
return nil
}
//自增
func (this *flowmeter)incr() (err error) {
key,_:=this.getFlowKeyAndEx()
_,err=this.dao.incrRedisFlowNum(key)
if(err!=nil){
return err
}
//common.PrintStdout().Printf("加1后的值是 %d",num)
return nil
......@@ -92,7 +153,7 @@ func (this *flowmeter)addOnlyLock(key string){
//common.PrintStdout().Printf("加锁 key:%s",name)
for{
s, err:= redisWriteConn.Do("SET", name, "1", "EX", "2","NX")//锁两秒没主动删就自动关闭(防止某个流程卡死,没执行到删除锁)
s, err:= redisWriteConn.Do("SET", name, "1", "EX", "10000000","NX")//锁两秒没主动删就自动关闭(防止某个流程卡死,没执行到删除锁)
if(err!=nil){
common.PrintStdout().Printf("读取redis 锁 key:%d 报错",key)
}
......
......@@ -74,34 +74,10 @@ func (this *openValidate) permissionValidate(interfaceName string) error{
//请求次数限制
func (this *openValidate) requestsNumValidate(token string,interfaceName string) error{
interfaceConfig,err:=this.business.GetInterfaceConfig(interfaceName)//商家接口配置,包含一小时最大流量,一天最大流量
flow:=NewFlow(token,interfaceName)//流控对象
//一天最大流量验证
flow.SetFlowKey(INCRTYPEDAY)
num,err:=flow.GetNum()
err:=NewFlow(token,interfaceName).checkout(this.business)
if(err!=nil){
return err
}
if(num>=int(interfaceConfig.dayMaxNum)){
common.PrintStdout().Printf("一天最大流量为: %d > %d",int(interfaceConfig.dayMaxNum),num)
return e.NewApiError("触发天级流控",FLOWERR4)
}
//一分钟最大流量验证
flow.SetFlowKey(INCRTYPEMIN)
num,err=flow.GetNum()//获取分钟使用流量
if(err!=nil){
return err
}
if(num>=int(interfaceConfig.minMaxNum)){
common.PrintStdout().Printf("一分钟最大流量为: %d >%d",int(interfaceConfig.minMaxNum),num)
return e.NewApiError("触发分钟级流控",FLOWERR3)
}else{
flow.incr()//验证成功,自增1
flow.SetFlowKey(INCRTYPEDAY)
flow.incr()//同时天也自增1
}
return nil
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment