ソースを参照

feat(game-shield): 重构 IP 生成逻辑

- 移除 GenerateIpService 接口和实现
- 新增 GameShieldSdkIp 相关的 model、repository 和 service
- 更新 GameShieldService,集成新的 IP 生成逻辑
- 添加处理 SDK IP 的新 handler
fusu 3 ヶ月 前
コミット
12139c3475

+ 3 - 0
cmd/server/wire/wire.go

@@ -36,6 +36,7 @@ var repositorySet = wire.NewSet(
 	repository.NewTcpLimitRepository,
 	repository.NewUdpLimitRepository,
 	repository.NewGameShieldBackendRepository,
+	repository.NewGameShieldSdkIpRepository,
 )
 
 var serviceSet = wire.NewSet(
@@ -56,6 +57,7 @@ var serviceSet = wire.NewSet(
 	service.NewTcpLimitService,
 	service.NewUdpLimitService,
 	service.NewGameShieldBackendService,
+	service.NewGameShieldSdkIpService,
 )
 
 var handlerSet = wire.NewSet(
@@ -71,6 +73,7 @@ var handlerSet = wire.NewSet(
 	handler.NewTcpLimitHandler,
 	handler.NewUdpLimitHandler,
 	handler.NewGameShieldBackendHandler,
+	handler.NewGameShieldSdkIpHandler,
 )
 
 var jobSet = wire.NewSet(

+ 6 - 4
cmd/server/wire/wire_gen.go

@@ -47,7 +47,9 @@ func NewWire(viperViper *viper.Viper, logger *log.Logger) (*app.App, func(), err
 	duedateService := service.NewDuedateService(serviceService, gameShieldRepository)
 	formatterService := service.NewFormatterService(serviceService, gameShieldPublicIpService)
 	requiredService := service.NewRequiredService(serviceService, crawlerService, viperViper)
-	gameShieldService := service.NewGameShieldService(serviceService, gameShieldRepository, crawlerService, gameShieldPublicIpService, duedateService, formatterService, parserService, requiredService, viperViper)
+	gameShieldSdkIpRepository := repository.NewGameShieldSdkIpRepository(repositoryRepository)
+	gameShieldSdkIpService := service.NewGameShieldSdkIpService(serviceService, gameShieldSdkIpRepository)
+	gameShieldService := service.NewGameShieldService(serviceService, gameShieldRepository, crawlerService, gameShieldPublicIpService, duedateService, formatterService, parserService, requiredService, viperViper, gameShieldSdkIpService)
 	gameShieldHandler := handler.NewGameShieldHandler(handlerHandler, gameShieldService, crawlerService)
 	gameShieldBackendRepository := repository.NewGameShieldBackendRepository(repositoryRepository)
 	gameShieldBackendService := service.NewGameShieldBackendService(serviceService, gameShieldBackendRepository, gameShieldRepository, crawlerService, gameShieldPublicIpService, duedateService, formatterService, parserService, requiredService, viperViper)
@@ -81,11 +83,11 @@ func NewWire(viperViper *viper.Viper, logger *log.Logger) (*app.App, func(), err
 
 // wire.go:
 
-var repositorySet = wire.NewSet(repository.NewDB, repository.NewRepository, repository.NewTransaction, repository.NewUserRepository, repository.NewGameShieldRepository, repository.NewGameShieldPublicIpRepository, repository.NewWebForwardingRepository, repository.NewTcpforwardingRepository, repository.NewUdpForWardingRepository, repository.NewGameShieldUserIpRepository, repository.NewWebLimitRepository, repository.NewTcpLimitRepository, repository.NewUdpLimitRepository, repository.NewGameShieldBackendRepository)
+var repositorySet = wire.NewSet(repository.NewDB, repository.NewRepository, repository.NewTransaction, repository.NewUserRepository, repository.NewGameShieldRepository, repository.NewGameShieldPublicIpRepository, repository.NewWebForwardingRepository, repository.NewTcpforwardingRepository, repository.NewUdpForWardingRepository, repository.NewGameShieldUserIpRepository, repository.NewWebLimitRepository, repository.NewTcpLimitRepository, repository.NewUdpLimitRepository, repository.NewGameShieldBackendRepository, repository.NewGameShieldSdkIpRepository)
 
-var serviceSet = wire.NewSet(service.NewService, service.NewUserService, service.NewGameShieldService, service.NewCrawlerService, service.NewGameShieldPublicIpService, service.NewDuedateService, service.NewFormatterService, service.NewParserService, service.NewRequiredService, service.NewWebForwardingService, service.NewTcpforwardingService, service.NewUdpForWardingService, service.NewGameShieldUserIpService, service.NewWebLimitService, service.NewTcpLimitService, service.NewUdpLimitService, service.NewGameShieldBackendService)
+var serviceSet = wire.NewSet(service.NewService, service.NewUserService, service.NewGameShieldService, service.NewCrawlerService, service.NewGameShieldPublicIpService, service.NewDuedateService, service.NewFormatterService, service.NewParserService, service.NewRequiredService, service.NewWebForwardingService, service.NewTcpforwardingService, service.NewUdpForWardingService, service.NewGameShieldUserIpService, service.NewWebLimitService, service.NewTcpLimitService, service.NewUdpLimitService, service.NewGameShieldBackendService, service.NewGameShieldSdkIpService)
 
-var handlerSet = wire.NewSet(handler.NewHandler, handler.NewUserHandler, handler.NewGameShieldHandler, handler.NewGameShieldPublicIpHandler, handler.NewWebForwardingHandler, handler.NewTcpforwardingHandler, handler.NewUdpForWardingHandler, handler.NewGameShieldUserIpHandler, handler.NewWebLimitHandler, handler.NewTcpLimitHandler, handler.NewUdpLimitHandler, handler.NewGameShieldBackendHandler)
+var handlerSet = wire.NewSet(handler.NewHandler, handler.NewUserHandler, handler.NewGameShieldHandler, handler.NewGameShieldPublicIpHandler, handler.NewWebForwardingHandler, handler.NewTcpforwardingHandler, handler.NewUdpForWardingHandler, handler.NewGameShieldUserIpHandler, handler.NewWebLimitHandler, handler.NewTcpLimitHandler, handler.NewUdpLimitHandler, handler.NewGameShieldBackendHandler, handler.NewGameShieldSdkIpHandler)
 
 var jobSet = wire.NewSet(job.NewJob, job.NewUserJob)
 

+ 0 - 1
go.sum

@@ -234,7 +234,6 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
 github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
 github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
 github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=

+ 25 - 0
internal/handler/gameshieldsdkip.go

@@ -0,0 +1,25 @@
+package handler
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/go-nunu/nunu-layout-advanced/internal/service"
+)
+
+type GameShieldSdkIpHandler struct {
+	*Handler
+	gameShieldSdkIpService service.GameShieldSdkIpService
+}
+
+func NewGameShieldSdkIpHandler(
+	handler *Handler,
+	gameShieldSdkIpService service.GameShieldSdkIpService,
+) *GameShieldSdkIpHandler {
+	return &GameShieldSdkIpHandler{
+		Handler:                handler,
+		gameShieldSdkIpService: gameShieldSdkIpService,
+	}
+}
+
+func (h *GameShieldSdkIpHandler) GetGameShieldSdkIp(ctx *gin.Context) {
+
+}

+ 0 - 2
internal/model/gameshield.go

@@ -6,13 +6,11 @@ type GameShield struct {
 	Id             int `gorm:"primarykey"`
 	AppName        string
 	GatewayGroupId int
-	Backend        string
 	RuleId         int
 	Key            string
 	AddTime        time.Time
 	Uid            int
 	HostId         string
-	AppIp          string
 	Checked        int
 	DunName        string
 }

+ 15 - 0
internal/model/gameshieldsdkip.go

@@ -0,0 +1,15 @@
+package model
+
+import "time"
+
+type GameShieldSdkIp struct {
+	Id        int    `gorm:"primarykey"`
+	Uid       int    `gorm:"not null"`
+	HostId    int    `gorm:"not null"`
+	SdkIp     string `gorm:"not null unique"`
+	CreatedAt time.Time
+}
+
+func (m *GameShieldSdkIp) TableName() string {
+	return "shd_game_shield_sdk_ip"
+}

+ 0 - 10
internal/repository/gameshield.go

@@ -13,7 +13,6 @@ type GameShieldRepository interface {
 	DeleteGameShield(ctx context.Context, ruleId int) error
 	GetGameShieldIsBuy(ctx context.Context, uid int64) (int64, error)
 	GetGameShieldNextduedate(ctx context.Context, uid int64, productID string) (string, error)
-	GetGameShieldExistingIps(ctx context.Context, ip string) ([]string, error)
 	GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error)
 	GetGameShieldIdByDunName(ctx context.Context, id int64) (string, error)
 	GetGameShieldRuleIdByAppName(ctx context.Context, appName string) (int, error)
@@ -97,15 +96,6 @@ func (r *gameShieldRepository) GetGameShieldNextduedate(ctx context.Context, uid
 
 	return nextDueDate, nil
 }
-func (r *gameShieldRepository) GetGameShieldExistingIps(ctx context.Context, ip string) ([]string, error) {
-	var res []string
-	if err := r.DB(ctx).Model(&model.GameShield{}).
-		Where("app_ip LIKE ?", ip+"%").
-		Pluck("app_ip", &res).Error; err != nil {
-		return nil, err
-	}
-	return res, nil
-}
 
 func (r *gameShieldRepository) GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error) {
 	var res string

+ 81 - 0
internal/repository/gameshieldsdkip.go

@@ -0,0 +1,81 @@
+package repository
+
+import (
+	"context"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+)
+
+type GameShieldSdkIpRepository interface {
+	GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error)
+	AddGameShieldSdkIp(ctx context.Context, req *model.GameShieldSdkIp) error
+	UpdateGameShieldSdkIp(ctx context.Context, gameShieldSdkIp *model.GameShieldSdkIp) error
+	DeleteGameShieldSdkIp(ctx context.Context, id int64) error
+	GetGameShieldSdkIpByHostId(ctx context.Context, hostId int) (*model.GameShieldSdkIp, error)
+	GetGameShieldSdkIpNewByHostId(ctx context.Context, hostId int) (string, error)
+	GetGameShieldSdkIpCountByHostId(ctx context.Context, hostId int) (int64, error)
+}
+
+func NewGameShieldSdkIpRepository(
+	repository *Repository,
+) GameShieldSdkIpRepository {
+	return &gameShieldSdkIpRepository{
+		Repository: repository,
+	}
+}
+
+type gameShieldSdkIpRepository struct {
+	*Repository
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error) {
+	var res model.GameShieldSdkIp
+	if err := r.DB(ctx).Where("id = ?", id).First(&res).Error; err != nil {
+		return nil, err
+	}
+	return &res, nil
+}
+
+func (r *gameShieldSdkIpRepository) AddGameShieldSdkIp(ctx context.Context, req *model.GameShieldSdkIp) error {
+	if err := r.DB(ctx).Create(req).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *gameShieldSdkIpRepository) UpdateGameShieldSdkIp(ctx context.Context, gameShieldSdkIp *model.GameShieldSdkIp) error {
+	if err := r.DB(ctx).Updates(gameShieldSdkIp).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *gameShieldSdkIpRepository) DeleteGameShieldSdkIp(ctx context.Context, id int64) error {
+	if err := r.DB(ctx).Where("id = ?", id).Delete(&model.GameShieldSdkIp{}).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIpByHostId(ctx context.Context, hostId int) (*model.GameShieldSdkIp, error) {
+	var res model.GameShieldSdkIp
+	if err := r.DB(ctx).Where("host_id = ?", hostId).Select(&model.GameShieldSdkIp{}).Error; err != nil {
+		return nil, err
+	}
+	return &res, nil
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIpNewByHostId(ctx context.Context, hostId int) (string, error) {
+	var res model.GameShieldSdkIp
+	if err := r.DB(ctx).Where("host_id = ?", hostId).Order("id DESC").First(&model.GameShieldSdkIp{}).Error; err != nil {
+		return "", err
+	}
+	return res.SdkIp, nil
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIpCountByHostId(ctx context.Context, hostId int) (int64, error) {
+	var res int64
+	if err := r.DB(ctx).Model(&model.GameShieldSdkIp{}).Where("host_id = ?", hostId).Count(&res).Error; err != nil {
+		return 0, err
+	}
+	return res, nil
+}

+ 15 - 0
internal/service/gameshield.go

@@ -28,6 +28,7 @@ func NewGameShieldService(
 	parser ParserService,
 	required RequiredService,
 	conf *viper.Viper,
+	gameShieldSdkIp GameShieldSdkIpService,
 ) GameShieldService {
 	return &gameShieldService{
 		Service:                   service,
@@ -39,6 +40,7 @@ func NewGameShieldService(
 		parser:                    parser,
 		required:                  required,
 		Url:                       conf.GetString("crawler.Url"),
+		gameShieldSdkIp:           gameShieldSdkIp,
 	}
 }
 
@@ -53,6 +55,7 @@ type gameShieldService struct {
 	Url                       string
 	parser                    ParserService
 	required                  RequiredService
+	gameShieldSdkIp           GameShieldSdkIpService
 }
 
 func (service *gameShieldService) SubmitGameShield(ctx context.Context, req *v1.GameShieldSubmitRequest) (string, error) {
@@ -63,6 +66,17 @@ func (service *gameShieldService) SubmitGameShield(ctx context.Context, req *v1.
 	if nameCount > 0 {
 		return "", fmt.Errorf("应用名称已存在")
 	}
+
+	hostIdInt, err := strconv.Atoi(req.HostId)
+	if err != nil {
+		return "", fmt.Errorf("转换hostId失败: %v", err)
+	}
+
+	// 调用IP生成服务
+	if err := service.gameShieldSdkIp.GenerateMultipleLoopbackIps(ctx, req.Uid, hostIdInt); err != nil {
+		return "", fmt.Errorf("生成IP地址失败: %w", err)
+	}
+
 	dunName := strconv.Itoa(req.Uid) + "_" + strconv.FormatInt(time.Now().Unix(), 10) + "_hostId" + req.HostId
 	formData := map[string]interface{}{
 		"app_name":         dunName,
@@ -98,6 +112,7 @@ func (service *gameShieldService) SubmitGameShield(ctx context.Context, req *v1.
 	}); err != nil {
 		return "", err
 	}
+
 	return "", nil
 }
 

+ 147 - 0
internal/service/gameshieldsdkip.go

@@ -0,0 +1,147 @@
+package service
+
+import (
+	"context"
+	"fmt"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
+	"strconv"
+	"strings"
+)
+
+type GameShieldSdkIpService interface {
+	GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error)
+	GenerateMultipleLoopbackIps(ctx context.Context, uid int, hostId int, count ...int) error
+}
+
+func NewGameShieldSdkIpService(
+	service *Service,
+	gameShieldSdkIpRepository repository.GameShieldSdkIpRepository,
+) GameShieldSdkIpService {
+	return &gameShieldSdkIpService{
+		Service:                   service,
+		gameShieldSdkIpRepository: gameShieldSdkIpRepository,
+	}
+}
+
+type gameShieldSdkIpService struct {
+	*Service
+	gameShieldSdkIpRepository repository.GameShieldSdkIpRepository
+}
+
+func (s *gameShieldSdkIpService) GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error) {
+	return s.gameShieldSdkIpRepository.GetGameShieldSdkIp(ctx, id)
+}
+
+// GenerateMultipleLoopbackIps 生成多个唯一127.0.0.0/8范围IP地址
+// count 指定需要生成的IP地址数量,默认为10
+// 返回生成的唯一IP地址数组和可能的错误
+// GenerateMultipleLoopbackIps 生成并保存多个唯一127.0.0.0/8范围IP地址到数据库
+// uid 用户ID
+// hostId 实例ID
+// count 指定需要生成的IP地址数量,默认为10
+// 返回生成并保存的唯一IP地址数组和可能的错误
+func (s *gameShieldSdkIpService) GenerateMultipleLoopbackIps(ctx context.Context, uid int, hostId int, count ...int) error {
+	requiredCount := 10
+	if len(count) > 0 && count[0] > 0 {
+		requiredCount = count[0]
+	}
+	haveCount, err := s.gameShieldSdkIpRepository.GetGameShieldSdkIpCountByHostId(ctx, hostId)
+	if err != nil {
+		return err
+	}
+	if int(haveCount) >= requiredCount {
+		return nil
+	}
+	// 从数据库获取最新的一条IP记录
+	latestIp, err := s.gameShieldSdkIpRepository.GetGameShieldSdkIpNewByHostId(ctx, hostId)
+	if err != nil {
+		// 如果没有记录,默认从127.0.0.2开始(避免使用127.0.0.1)
+		latestIp = "127.0.0.1"
+	}
+
+	// 解析IP成四个段
+	ipParts := strings.Split(latestIp, ".")
+	if len(ipParts) != 4 {
+		return fmt.Errorf("无效的IP格式: %s", latestIp)
+	}
+
+	// 将IP段转换为整数
+	a, err1 := strconv.Atoi(ipParts[0])
+	b, err2 := strconv.Atoi(ipParts[1])
+	c, err3 := strconv.Atoi(ipParts[2])
+	d, err4 := strconv.Atoi(ipParts[3])
+
+	if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
+		return fmt.Errorf("IP段转换失败: %s", latestIp)
+	}
+
+	// 确保第一段是127(保持在回环地址范围内)
+	if a != 127 {
+		a = 127
+		b, c, d = 0, 0, 1 // 重置为127.0.0.1
+	}
+
+	// 从最新IP的下一个地址开始
+	d++
+	if d > 255 {
+		d = 0
+		c++
+		if c > 255 {
+			c = 0
+			b++
+			if b > 255 {
+				return fmt.Errorf("IP地址池已耗尽")
+			}
+		}
+	}
+
+	// 收集生成的唯一IP
+	result := make([]string, 0, requiredCount)
+	attempts := 0
+	maxAttempts := 10000 // 防止无限循环
+
+	for len(result) < requiredCount && attempts < maxAttempts {
+		currentIp := fmt.Sprintf("127.%d.%d.%d", b, c, d)
+
+		// 尝试将IP保存到数据库
+		err := s.gameShieldSdkIpRepository.AddGameShieldSdkIp(ctx, &model.GameShieldSdkIp{
+			HostId: hostId,
+			Uid:    uid,
+			SdkIp:  currentIp,
+		})
+		if err == nil {
+			// 保存成功,添加到结果列表
+			result = append(result, currentIp)
+		} else {
+			// 如果是因为IP已存在导致的错误,我们忽略并继续
+			// 其他错误则返回
+			if !strings.Contains(err.Error(), "unique_sdk_ip") {
+				return fmt.Errorf("保存IP到数据库失败: %w", err)
+			}
+			// IP已存在,继续尝试下一个
+		}
+
+		// 递增IP地址
+		d++
+		if d > 255 {
+			d = 0
+			c++
+			if c > 255 {
+				c = 0
+				b++
+				if b > 255 {
+					break
+				}
+			}
+		}
+
+		attempts++
+	}
+
+	if len(result) < requiredCount {
+		return fmt.Errorf("无法生成足够的唯一IP地址,地址池可能已耗尽,仅生成了%d个", len(result))
+	}
+
+	return nil
+}

+ 0 - 219
internal/service/generateip.go

@@ -1,219 +0,0 @@
-package service
-
-import (
-	"context"
-	"fmt"
-	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
-	"github.com/sourcegraph/conc/pool"
-	"math/rand"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-)
-
-type GenerateIpService interface {
-	GenerateMultipleLoopbackIps(ctx context.Context, count ...int) ([]string, error)
-}
-
-func NewGenerateIpService(
-	service *Service,
-	gameShieldRepository repository.GameShieldRepository,
-) GenerateIpService {
-	return &generateIpService{
-		Service:              service,
-		gameShieldRepository: gameShieldRepository,
-	}
-}
-
-type generateIpService struct {
-	*Service
-	gameShieldRepository repository.GameShieldRepository
-}
-
-// GenerateMultipleLoopbackIps 生成多个唯一127.0.0.0/8范围IP地址
-// count 指定需要生成的IP地址数量,默认为10
-// 返回生成的唯一IP地址数组和可能的错误
-func (s *generateIpService) GenerateMultipleLoopbackIps(ctx context.Context, count ...int) ([]string, error) {
-	requiredCount := 10
-	if len(count) > 0 && count[0] > 0 {
-		requiredCount = count[0]
-	}
-
-	maxAttempts := 1000 // 最大尝试次数
-	attempts := 0
-
-	// 使用互斥锁保护结果集
-	var mu sync.Mutex
-	collected := make([]string, 0, requiredCount)
-	checkedSegments := make(map[string]struct{}, maxAttempts)
-
-	// 使用一个固定的随机源以提高性能
-	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
-
-	for len(collected) < requiredCount && attempts < maxAttempts {
-		// 随机生成多个x/z段组合,批量处理
-		candidates := make([]struct{ x, z int }, 0, 5)
-		for i := 0; i < 5 && len(candidates) < 5; i++ {
-			x := rnd.Intn(256)
-			z := rnd.Intn(256)
-			segmentKey := fmt.Sprintf("%d-%d", x, z)
-
-			// 跳过已检查过的段
-			mu.Lock()
-			_, exists := checkedSegments[segmentKey]
-			if !exists {
-				checkedSegments[segmentKey] = struct{}{}
-				mu.Unlock()
-				candidates = append(candidates, struct{ x, z int }{x, z})
-			} else {
-				mu.Unlock()
-			}
-		}
-
-		// 使用conc/pool包并发处理候选IP段
-		// 创建一个工作池,限制并发数为4,并收集错误
-		p := pool.New().WithMaxGoroutines(4).WithErrors()
-
-		// 存储结果
-		var results [][]string
-
-		// 对每个候选项并发处理
-		for _, candidate := range candidates {
-			// 创建副本避免闭包捕获循环变量
-			candidate := candidate
-
-			p.Go(func() error {
-				if ctx.Err() != nil {
-					return ctx.Err()
-				}
-
-				x, z := candidate.x, candidate.z
-				prefix := fmt.Sprintf("127.%d.%d.", x, z)
-
-				// 查询数据库中该前缀已存在的IP
-				existingIps, err := s.gameShieldRepository.GetGameShieldExistingIps(ctx, prefix)
-				if err != nil {
-					// 返回错误以便收集
-					return fmt.Errorf("获取IP %s 前缀已存在的记录失败: %w", prefix, err)
-				}
-
-				// 使用map标记已存在的第四段
-				existingFourth := make(map[int]bool, len(existingIps))
-				for _, ip := range existingIps {
-					parts := strings.Split(ip, ".")
-					if len(parts) == 4 {
-						fourth, err := strconv.Atoi(parts[3])
-						if err == nil {
-							// 排除127.0.0.1的情况
-							if x == 0 && z == 0 && fourth == 1 {
-								continue
-							}
-							existingFourth[fourth] = true
-						}
-					}
-				}
-
-				// 快速估算可用数量
-				availableCount := 256 - len(existingFourth)
-				// 排除127.0.0.1的特殊情况
-				if x == 0 && z == 0 && !existingFourth[1] {
-					availableCount--
-				}
-
-				// 如果可用数量太少,可以跳过
-				if availableCount <= 0 {
-					return nil
-				}
-
-				// 预分配足够大的切片避免多次扩容
-				available := make([]string, 0, availableCount)
-
-				// 如果可用数量很多,可以只收集部分,避免不必要的工作
-				collectLimit := min(availableCount, requiredCount*2)
-				collectCount := 0
-
-				// 随机选择起始点,避免每次都从0开始
-				startPoint := rnd.Intn(256)
-				for i := 0; i < 256 && collectCount < collectLimit; i++ {
-					fourth := (startPoint + i) % 256
-
-					if existingFourth[fourth] {
-						continue
-					}
-
-					// 确保不生成127.0.0.1
-					if x == 0 && z == 0 && fourth == 1 {
-						continue
-					}
-
-					available = append(available, fmt.Sprintf("127.%d.%d.%d", x, z, fourth))
-					collectCount++
-				}
-
-				// 随机打乱结果
-				for i := len(available) - 1; i > 0; i-- {
-					j := rnd.Intn(i + 1)
-					available[i], available[j] = available[j], available[i]
-				}
-
-				// 将结果添加到结果集
-				mu.Lock()
-				results = append(results, available)
-				mu.Unlock()
-
-				return nil
-			})
-		}
-
-		// 等待所有goroutine完成并检查错误
-		if err := p.Wait(); err != nil {
-			// 这里可以选择记录错误但继续尝试,或者直接返回错误
-			// 我们选择只有当收集的IP不足时才返回错误
-			if len(collected) < requiredCount {
-				// 如果已经是最后一次尝试且收集的IP不足,返回错误
-				if attempts >= maxAttempts-1 {
-					return nil, fmt.Errorf("生成IP地址失败: %w", err)
-				}
-				// 否则继续尝试下一批候选IP段
-			}
-		}
-
-		// 收集结果
-		for _, ips := range results {
-			mu.Lock()
-			for _, ip := range ips {
-				if len(collected) >= requiredCount {
-					break
-				}
-				collected = append(collected, ip)
-			}
-			mu.Unlock()
-		}
-
-		attempts++
-
-		// 如果已经收集足够的IP,跳出循环
-		mu.Lock()
-		hasEnough := len(collected) >= requiredCount
-		mu.Unlock()
-		if hasEnough {
-			break
-		}
-	}
-
-	mu.Lock()
-	defer mu.Unlock()
-
-	if len(collected) < requiredCount {
-		return nil, fmt.Errorf("无法生成足够的唯一IP地址,地址池可能已耗尽,仅生成了%d个", len(collected))
-	}
-
-	// 最终随机排序
-	for i := len(collected) - 1; i > 0; i-- {
-		j := rand.Intn(i + 1)
-		collected[i], collected[j] = collected[j], collected[i]
-	}
-
-	return collected[:requiredCount], nil
-}