From 2cdb04c52284037c546bf6e72a2d1779b9b0beb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=AD=90=E9=93=AD?= Date: Fri, 21 Mar 2025 15:50:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=BB=A1=E8=B6=B3=E5=8E=8B=E6=B5=8B=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 2 + internal/data/gorm_test.go | 54 ++++++++++++++++++- internal/pkg/limit/rate.go | 96 ++++++++++++++++----------------- internal/pkg/limit/rate_test.go | 9 ++++ 5 files changed, 113 insertions(+), 49 deletions(-) diff --git a/go.mod b/go.mod index 3a5f641..550aeb5 100644 --- a/go.mod +++ b/go.mod @@ -86,6 +86,7 @@ require ( golang.org/x/sys v0.30.0 // indirect golang.org/x/term v0.29.0 // indirect golang.org/x/text v0.22.0 // indirect + golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect google.golang.org/grpc v1.61.1 // indirect gopkg.in/ini.v1 v1.42.0 // indirect diff --git a/go.sum b/go.sum index 309d9c1..26e6c8d 100644 --- a/go.sum +++ b/go.sum @@ -386,6 +386,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/internal/data/gorm_test.go b/internal/data/gorm_test.go index bf5357a..a598fa7 100644 --- a/internal/data/gorm_test.go +++ b/internal/data/gorm_test.go @@ -24,6 +24,14 @@ func Test_gorm_db(t *testing.T) { MaxLifetime: durationpb.New(60), // 5分钟 IsDebug: false, } + //data := &conf.Data_Database{ + // Driver: "mysql", + // Source: "root:lansexiongdi6,@tcp(47.97.27.195:3306)/voucher?parseTime=True&loc=Local", + // MaxIdle: 2, // 空闲连接池 + // MaxOpen: 10, // 最大连接数 + // MaxLifetime: durationpb.New(60), + // IsDebug: false, + //} gormDb, cleanup := db(data) defer cleanup() @@ -78,7 +86,7 @@ func Test_db(t *testing.T) { start2 := time.Now() errCount := 0 - const concurrency = 2 + const concurrency = 1 for i := 0; i < concurrency; i++ { ctx := context.Background() @@ -102,3 +110,47 @@ func Test_db(t *testing.T) { t.Logf("\n--------------连接请求,总请求耗时: %v,总数: %d, 失败次数: %d--------------\n", time.Since(start2), concurrency, errCount) } + +func Test_orderCreate(t *testing.T) { + //maxLifetime := durationpb.New(300) // 5分钟 + //data := &conf.Data_Database{ + // Driver: "mysql", + // Source: "root:lansexiongdi6,@tcp(47.97.27.195:3306)/voucher?parseTime=True&loc=Local", + // MaxIdle: 2, // 空闲连接池 + // MaxOpen: 10, // 最大连接数 + // MaxLifetime: maxLifetime, + // IsDebug: false, + //} + //gormDb, cleanup := db(data) + //defer cleanup() + // + //now := time.Now() + // + //info := &model.Order{ + // OrderNo: req.OrderNo, + // OutBizNo: req.OutBizNo, + // ProductNo: req.ProductNo, + // BatchNo: req.BatchNo, + // Account: req.Account, + // AccountType: req.AccountType.GetValue(), + // Status: req.Status.GetValue(), + // Type: req.Type.GetValue(), + // AppID: req.AppID, + // MerchantNo: req.MerchantNo, + // Channel: req.Channel.GetValue(), + // NotifyUrl: req.NotifyUrl, + // Attach: req.Attach, + // CreateTime: &now, + // UpdateTime: &now, + //} + // + //if req.ProductNo == "001" { + // info.VoucherNo = req.OrderNo + // info.Status = vo.OrderStatusSuccess.GetValue() + //} + // + //tx := p.DB(ctx).Create(info) + //if tx.Error != nil { + // return nil, fmt.Errorf("create db fail %w", tx.Error) + //} +} diff --git a/internal/pkg/limit/rate.go b/internal/pkg/limit/rate.go index 4acc8da..7ee5efd 100644 --- a/internal/pkg/limit/rate.go +++ b/internal/pkg/limit/rate.go @@ -1,50 +1,50 @@ package limit -//import ( -// "fmt" -// "golang.org/x/time/rate" -// "sync" -// "time" -//) -// -//type RateLimiter struct { -// // RateLimiterMap 用来存储每个 key 对应的限流器 -// rateLimiters map[string]*rate.Limiter -// mu sync.Mutex -//} -// -//type Parameters struct { -// Key string // 限流器的标识 -// Burst int // 每分钟允许的最大请求数 -// Interval time.Duration // 请求数量的时间窗口内 -//} -// -//func NewRateLimiter() *RateLimiter { -// return &RateLimiter{ -// rateLimiters: make(map[string]*rate.Limiter), -// } -//} -// -//// RateLimit 创建一个函数来检查某个 ID 的请求是否频繁 -//func (r *RateLimiter) RateLimit(p *Parameters) error { -// // 锁定访问 rateLimiters,确保线程安全 -// r.mu.Lock() -// defer r.mu.Unlock() -// -// // 如果该 id 没有对应的限流器,则创建一个新的 -// if _, exists := r.rateLimiters[p.Key]; !exists { -// // 每分钟允许 1 次请求 -// r.rateLimiters[p.Key] = rate.NewLimiter(rate.Every(p.Interval), p.Burst) -// } -// -// // 获取该 id 对应的限流器 -// limiter := r.rateLimiters[p.Key] -// -// // 判断请求是否被限流 -// if !limiter.Allow() { -// return fmt.Errorf("请求频率过快,请稍后再试") -// } -// -// // 请求通过限制,可以继续执行 -// return nil -//} +import ( + "fmt" + "golang.org/x/time/rate" + "sync" + "time" +) + +type RateLimiter struct { + // RateLimiterMap 用来存储每个 key 对应的限流器 + rateLimiters map[string]*rate.Limiter + mu sync.Mutex +} + +type Parameters struct { + Key string // 限流器的标识 + Burst int // 每分钟允许的最大请求数 + Interval time.Duration // 请求数量的时间窗口内 +} + +func NewRateLimiter() *RateLimiter { + return &RateLimiter{ + rateLimiters: make(map[string]*rate.Limiter), + } +} + +// RateLimit 创建一个函数来检查某个 ID 的请求是否频繁 +func (r *RateLimiter) RateLimit(p *Parameters) error { + // 锁定访问 rateLimiters,确保线程安全 + r.mu.Lock() + defer r.mu.Unlock() + + // 如果该 id 没有对应的限流器,则创建一个新的 + if _, exists := r.rateLimiters[p.Key]; !exists { + // 每分钟允许 1 次请求 + r.rateLimiters[p.Key] = rate.NewLimiter(rate.Every(p.Interval), p.Burst) + } + + // 获取该 id 对应的限流器 + limiter := r.rateLimiters[p.Key] + + // 判断请求是否被限流 + if !limiter.Allow() { + return fmt.Errorf("请求频率过快,请稍后再试") + } + + // 请求通过限制,可以继续执行 + return nil +} diff --git a/internal/pkg/limit/rate_test.go b/internal/pkg/limit/rate_test.go index 2eda384..19ddb43 100644 --- a/internal/pkg/limit/rate_test.go +++ b/internal/pkg/limit/rate_test.go @@ -1,7 +1,9 @@ package limit import ( + "golang.org/x/time/rate" "testing" + "time" ) func TestRateLimiter(t *testing.T) { @@ -21,4 +23,11 @@ func TestRateLimiter(t *testing.T) { // } // time.Sleep(1 * time.Second) // 每 1 秒请求一次 //} + + limiter := rate.NewLimiter(rate.Every(time.Second), 100) // 每秒100个令牌,突发容量100 + if !limiter.Allow() { + // 拒绝或排队请求(需结合业务逻辑) + t.Log("限流") + return + } }