914-17:00修改
This commit is contained in:
6
go.mod
6
go.mod
@@ -12,6 +12,8 @@ require (
|
|||||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
|
github.com/sirupsen/logrus v1.9.3
|
||||||
|
go.uber.org/ratelimit v0.3.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gorm.io/driver/mysql v1.6.0
|
gorm.io/driver/mysql v1.6.0
|
||||||
gorm.io/gorm v1.31.0
|
gorm.io/gorm v1.31.0
|
||||||
@@ -20,7 +22,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/RoaringBitmap/roaring/v2 v2.10.0 // indirect
|
github.com/RoaringBitmap/roaring/v2 v2.10.0 // indirect
|
||||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.0 // indirect
|
github.com/bits-and-blooms/bitset v1.24.0 // indirect
|
||||||
github.com/blevesearch/bleve_index_api v1.2.9 // indirect
|
github.com/blevesearch/bleve_index_api v1.2.9 // indirect
|
||||||
github.com/blevesearch/geo v0.2.4 // indirect
|
github.com/blevesearch/geo v0.2.4 // indirect
|
||||||
@@ -77,7 +79,6 @@ require (
|
|||||||
github.com/philhofer/fwd v1.2.0 // indirect
|
github.com/philhofer/fwd v1.2.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/rs/xid v1.6.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
|
||||||
github.com/tidwall/gjson v1.18.0 // indirect
|
github.com/tidwall/gjson v1.18.0 // indirect
|
||||||
github.com/tidwall/match v1.2.0 // indirect
|
github.com/tidwall/match v1.2.0 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
@@ -86,7 +87,6 @@ require (
|
|||||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||||
go.etcd.io/bbolt v1.4.3 // indirect
|
go.etcd.io/bbolt v1.4.3 // indirect
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/ratelimit v0.3.1 // indirect
|
|
||||||
golang.org/x/arch v0.21.0 // indirect
|
golang.org/x/arch v0.21.0 // indirect
|
||||||
golang.org/x/crypto v0.42.0 // indirect
|
golang.org/x/crypto v0.42.0 // indirect
|
||||||
golang.org/x/lint v0.0.0-20241112194109-818c5a804067 // indirect
|
golang.org/x/lint v0.0.0-20241112194109-818c5a804067 // indirect
|
||||||
|
|||||||
171
kills/kill.go
171
kills/kill.go
@@ -1,14 +1,15 @@
|
|||||||
package kills
|
package kills
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
"toutoukan/init/databaseInit"
|
"toutoukan/init/redisInit"
|
||||||
|
"toutoukan/utill/scripts"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -40,103 +41,103 @@ func (Goods) TableName() string {
|
|||||||
func (Order) TableName() string {
|
func (Order) TableName() string {
|
||||||
return "oders_list"
|
return "oders_list"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成25位随机订单编号(string类型)
|
|
||||||
func GenerateOrderID() string {
|
func GenerateOrderID() string {
|
||||||
// 1. 取当前时间戳(精确到毫秒,8位数字)
|
timestamp := time.Now().Format("20060102150405")
|
||||||
timestamp := time.Now().Format("20060102150405") // 年月日时分秒(14位)
|
|
||||||
|
|
||||||
// 2. 生成随机字符串(11位,补足25位)
|
randomBytes := make([]byte, 8)
|
||||||
randomBytes := make([]byte, 8) // 8字节随机数经base64编码后约11字符
|
|
||||||
_, err := rand.Read(randomBytes)
|
_, err := rand.Read(randomBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// 出错时降级为伪随机数
|
|
||||||
return fmt.Sprintf("ORD%s%011d", timestamp, time.Now().UnixNano()%100000000000)
|
return fmt.Sprintf("ORD%s%011d", timestamp, time.Now().UnixNano()%100000000000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 拼接前缀+时间戳+随机字符串(确保25位)
|
randomStr := base64.URLEncoding.EncodeToString(randomBytes)[:11]
|
||||||
randomStr := base64.URLEncoding.EncodeToString(randomBytes)[:11] // 截取前11位
|
|
||||||
return fmt.Sprintf("ORD%s%s", timestamp, randomStr)
|
return fmt.Sprintf("ORD%s%s", timestamp, randomStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Userkill(c *gin.Context) {
|
func Userkill(c *gin.Context) {
|
||||||
// 直接使用全局初始化好的 UserDB 连接池
|
|
||||||
db := databaseInit.UserDB
|
result, err := redisInit.RedisClient.Eval(context.Background(), scripts.Luascript_forkill, []string{"stock:10000", "mayiming"}, 1, GenerateOrderID()).Int()
|
||||||
if db == nil {
|
if err != nil {
|
||||||
log.Printf("%sUserDB 未初始化,请先调用 InitUserDB()%s\n", colorRed, colorReset)
|
log.Printf("Redis 脚本执行错误: %v", err)
|
||||||
c.JSON(500, gin.H{"error": "系统数据库未初始化"})
|
c.JSON(500, gin.H{"error": "库存操作失败", "detail": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Printf("%s用户请求处理完成%s\n", colorBlue, colorReset)
|
if result == 1 {
|
||||||
|
c.JSON(200, gin.H{"result": "库存扣减成功"})
|
||||||
// 定义要查询的商品ID
|
} else {
|
||||||
var targetGID uint = 1
|
c.JSON(200, gin.H{"result": "库存不足,扣减失败"})
|
||||||
var goods Goods
|
|
||||||
|
|
||||||
tx := db.Begin()
|
|
||||||
if tx.Error != nil {
|
|
||||||
log.Printf("%s开启事务失败: %v%s\n", colorRed, tx.Error, colorReset)
|
|
||||||
c.JSON(500, gin.H{"body": "事务开启失败"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result := tx.Set("gorm:query_option", "FOR UPDATE").Where("gid = ?", targetGID).First(&goods)
|
|
||||||
if result.Error != nil {
|
|
||||||
tx.Rollback() // 失败回滚事务
|
|
||||||
log.Printf("%s查询商品失败: %v%s\n", colorRed, result.Error, colorReset)
|
|
||||||
c.JSON(404, gin.H{"error": "商品不存在"})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 检查库存是否充足
|
|
||||||
if goods.Stock <= 0 {
|
|
||||||
tx.Rollback()
|
|
||||||
log.Printf("%s商品库存不足%s\n", colorYellow, colorReset)
|
|
||||||
c.JSON(400, gin.H{"error": "商品库存不足"})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 生成订单
|
//func Userkill(c *gin.Context) {
|
||||||
order := Order{
|
// // 直接使用全局初始化好的 UserDB 连接池
|
||||||
OrderId: GenerateOrderID(),
|
// db := databaseInit.UserDB
|
||||||
TradeTime: time.Now(),
|
// if db == nil {
|
||||||
}
|
// log.Printf("%sUserDB 未初始化,请先调用 InitUserDB()%s\n", colorRed, colorReset)
|
||||||
if err := tx.Create(&order).Error; err != nil {
|
// c.JSON(500, gin.H{"error": "系统数据库未初始化"})
|
||||||
tx.Rollback()
|
// return
|
||||||
log.Printf("%s创建订单失败: %v%s\n", colorRed, err, colorReset)
|
// }
|
||||||
c.JSON(500, gin.H{"error": "创建订单失败"})
|
// fmt.Printf("%s用户请求处理完成%s\n", colorBlue, colorReset)
|
||||||
return
|
//
|
||||||
}
|
// // 定义要查询的商品ID
|
||||||
|
// var targetGID uint = 1
|
||||||
updateResult := tx.Model(&Goods{}).
|
// var goods Goods
|
||||||
Where("gid = ? AND stock > 0", targetGID).
|
//
|
||||||
Update("stock", gorm.Expr("stock - 1"))
|
// tx := db.Begin()
|
||||||
if updateResult.Error != nil {
|
// if tx.Error != nil {
|
||||||
tx.Rollback()
|
// log.Printf("%s开启事务失败: %v%s\n", colorRed, tx.Error, colorReset)
|
||||||
log.Printf("%s扣减库存失败: %v%s\n", colorRed, updateResult.Error, colorReset)
|
// c.JSON(500, gin.H{"body": "事务开启失败"})
|
||||||
c.JSON(500, gin.H{"error": "库存更新失败"})
|
// return
|
||||||
return
|
// }
|
||||||
}
|
// result := tx.Set("gorm:query_option", "FOR UPDATE").Where("gid = ?", targetGID).First(&goods)
|
||||||
|
// if result.Error != nil {
|
||||||
// 5. 检查库存是否实际被扣减(防止并发下库存已被其他事务耗尽)
|
// tx.Rollback() // 失败回滚事务
|
||||||
if updateResult.RowsAffected == 0 {
|
// log.Printf("%s查询商品失败: %v%s\n", colorRed, result.Error, colorReset)
|
||||||
tx.Rollback()
|
// c.JSON(404, gin.H{"error": "商品不存在"})
|
||||||
log.Printf("%s库存扣减失败:并发冲突,库存已不足%s\n", colorRed, colorReset)
|
// return
|
||||||
c.JSON(400, gin.H{"error": "商品库存不足"})
|
// }
|
||||||
return
|
//
|
||||||
}
|
// // 2. 检查库存是否充足
|
||||||
|
// if goods.Stock <= 0 {
|
||||||
// 5. 提交事务
|
// tx.Rollback()
|
||||||
if err := tx.Commit().Error; err != nil {
|
// log.Printf("%s商品库存不足%s\n", colorYellow, colorReset)
|
||||||
tx.Rollback()
|
// c.JSON(400, gin.H{"error": "商品库存不足"})
|
||||||
log.Printf("%s提交事务失败: %v%s\n", colorRed, err, colorReset)
|
// return
|
||||||
c.JSON(500, gin.H{"error": "系统错误"})
|
// }
|
||||||
return
|
//
|
||||||
}
|
// // 3. 生成订单
|
||||||
|
// userorder := Order{
|
||||||
log.Printf("%s订单创建成功,订单ID: %s,剩余库存: %d%s\n", colorGreen, order.OrderId, goods.Stock-1, colorReset)
|
// OrderId: GenerateOrderID(),
|
||||||
c.JSON(200, gin.H{
|
// TradeTime: time.Now(),
|
||||||
"message": "下单成功",
|
// }
|
||||||
"order_id": order.OrderId,
|
// if err := tx.Create(&userorder).Error; err != nil {
|
||||||
"stock": goods.Stock - 1,
|
// tx.Rollback()
|
||||||
})
|
// log.Printf("%s创建订单失败: %v%s\n", colorRed, err, colorReset)
|
||||||
}
|
// c.JSON(500, gin.H{"error": "创建订单失败"})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 4. 扣减库存(库存-1)
|
||||||
|
// if err := tx.Model(&Goods{}).Where("gid = ?", targetGID).Update("stock", goods.Stock-1).Error; err != nil {
|
||||||
|
// tx.Rollback()
|
||||||
|
// log.Printf("%s扣减库存失败: %v%s\n", colorRed, err, colorReset)
|
||||||
|
// c.JSON(500, gin.H{"error": "库存更新失败"})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 5. 提交事务
|
||||||
|
// if err := tx.Commit().Error; err != nil {
|
||||||
|
// tx.Rollback()
|
||||||
|
// log.Printf("%s提交事务失败: %v%s\n", colorRed, err, colorReset)
|
||||||
|
// c.JSON(500, gin.H{"error": "系统错误"})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// log.Printf("%s订单创建成功,订单ID: %s,剩余库存: %d%s\n", colorGreen, userorder.OrderId, goods.Stock-1, colorReset)
|
||||||
|
// c.JSON(200, gin.H{
|
||||||
|
// "message": "下单成功",
|
||||||
|
// "order_id": userorder.OrderId,
|
||||||
|
// "stock": goods.Stock - 1,
|
||||||
|
// })
|
||||||
|
//}
|
||||||
|
|||||||
6
model/usermodel/userOrder/userorder.go
Normal file
6
model/usermodel/userOrder/userorder.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package userOrder
|
||||||
|
|
||||||
|
type UserRequest struct {
|
||||||
|
UserID int `json:"user_id"`
|
||||||
|
Order string `json:"userorder"` // 对应商品标识:stock10000 ~ stock10004
|
||||||
|
}
|
||||||
@@ -7,120 +7,121 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"toutoukan/model/usermodel/userOrder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 请求体结构
|
// 请求体结构(Order字段对应目标商品标识)
|
||||||
type UserRequest struct {
|
|
||||||
UserID int `json:"user_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 响应体结构(根据实际接口响应调整)
|
// 响应体结构(根据实际接口响应调整)
|
||||||
type Response struct {
|
type Response struct {
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
|
// 可根据实际接口返回补充字段,如订单号、库存状态等
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
const totalUsers = 1000 // 总用户数
|
const totalBatches = 5 // 固定发送5批请求
|
||||||
const batchSize = 130 // 每批发送的请求数
|
const batchSize = 150 // 每批固定150个请求
|
||||||
const interval = 5 * time.Second // 每批请求的时间间隔
|
const interval = 5 * time.Second // 每批请求的时间间隔(可按需调整)
|
||||||
const duration = 20 * time.Second // 总持续时间
|
|
||||||
|
|
||||||
// 计算总批次数(确保在duration时间内发送完所有请求)
|
|
||||||
totalBatches := totalUsers / batchSize
|
|
||||||
if totalUsers%batchSize != 0 {
|
|
||||||
totalBatches++
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查总耗时是否符合预期
|
|
||||||
expectedDuration := time.Duration(totalBatches-1) * interval
|
|
||||||
if expectedDuration > duration {
|
|
||||||
fmt.Printf("警告:按当前设置将耗时 %v,超过预期的 %v\n", expectedDuration, duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
userID := 1 // 用户ID计数器
|
|
||||||
|
|
||||||
// 按批次发送请求
|
userID := 1 // 用户ID计数器,从1开始递增(确保每个请求用户ID唯一)
|
||||||
|
|
||||||
|
// 循环发送5批请求,每批对应不同的商品order(stock10000 ~ stock10004)
|
||||||
for batch := 1; batch <= totalBatches; batch++ {
|
for batch := 1; batch <= totalBatches; batch++ {
|
||||||
// 计算当前批次的请求数量(最后一批可能不足batchSize)
|
// 计算当前批次的目标商品order:第1批→stock10000,第2批→stock10001...第5批→stock10004
|
||||||
currentBatchSize := batchSize
|
targetOrder := fmt.Sprintf("stock1000%d", batch-1)
|
||||||
if userID+currentBatchSize-1 > totalUsers {
|
fmt.Printf("=== 开始第 %d 批请求 ===\n", batch)
|
||||||
currentBatchSize = totalUsers - userID + 1
|
fmt.Printf("当前批次目标商品: %s | 请求数量: %d 个 | 开始时间: %v\n",
|
||||||
}
|
targetOrder, batchSize, time.Now().Format("15:04:05"))
|
||||||
|
|
||||||
fmt.Printf("开始第 %d 批请求,共 %d 个,当前时间: %v\n",
|
// 并发发送当前批次的150个请求
|
||||||
batch, currentBatchSize, time.Now().Format("15:04:05"))
|
for i := 0; i < batchSize; i++ {
|
||||||
|
|
||||||
// 发送当前批次的请求
|
|
||||||
for i := 0; i < currentBatchSize; i++ {
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(uid int) {
|
// 捕获当前循环的uid和order(避免goroutine闭包引用循环变量问题)
|
||||||
|
currentUID := userID
|
||||||
|
currentOrder := targetOrder
|
||||||
|
go func(uid int, order string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
// 发送POST请求
|
// 发送单个POST请求
|
||||||
result, err := sendPostRequest(uid)
|
result, err := sendPostRequest(uid, order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("用户 %d 请求失败: %v\n", uid, err)
|
// 请求失败:输出错误日志(包含用户ID和商品标识)
|
||||||
|
fmt.Printf("❌ 用户 %d (商品%s) 请求失败: %v\n", uid, order, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 输出结果(可以根据需要调整输出频率,避免日志过多)
|
// 请求成功:输出响应结果(可按需调整日志粒度,避免刷屏)
|
||||||
fmt.Printf("用户 %d 响应: %+v\n", uid, result)
|
fmt.Printf("✅ 用户 %d (商品%s) 响应: 成功=%v, 消息=%s\n",
|
||||||
}(userID)
|
uid, order, result.Success, result.Message)
|
||||||
userID++
|
}(currentUID, currentOrder)
|
||||||
|
userID++ // 每生成一个请求,用户ID递增1
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最后一批不需要等待
|
// 等待当前批次所有请求完成(确保批次内请求全部处理后,再进入下一批)
|
||||||
|
wg.Wait()
|
||||||
|
fmt.Printf("=== 第 %d 批请求全部完成 | 完成时间: %v ===\n\n",
|
||||||
|
batch, time.Now().Format("15:04:05"))
|
||||||
|
|
||||||
|
// 非最后一批请求,等待指定间隔后再发送下一批(避免请求集中压测)
|
||||||
if batch < totalBatches {
|
if batch < totalBatches {
|
||||||
// 等待指定间隔后再发送下一批
|
fmt.Printf("等待 %v 后发送下一批请求...\n\n", interval)
|
||||||
time.Sleep(interval)
|
time.Sleep(interval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待所有请求完成
|
fmt.Println("🎉 所有5批请求已全部完成!")
|
||||||
wg.Wait()
|
|
||||||
fmt.Println("所有请求已完成")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送POST请求
|
type UserRequest1 struct {
|
||||||
func sendPostRequest(userID int) (*Response, error) {
|
UserID int `json:"user_id"`
|
||||||
url := "http://localhost:9096/user/kill"
|
Order string `json:"userorder"` // 对应商品标识:stock10000 ~ stock10004
|
||||||
|
}
|
||||||
|
|
||||||
// 创建请求体
|
// 发送POST请求(接收用户ID和商品order,构造请求体)
|
||||||
requestBody := UserRequest{
|
func sendPostRequest(userID int, order string) (*Response, error) {
|
||||||
|
// 目标接口地址(根据实际部署调整)
|
||||||
|
targetURL := "http://localhost:9096/user/kill"
|
||||||
|
// 1. 构造请求体(绑定当前用户ID和目标商品order)
|
||||||
|
requestBody := userOrder.UserRequest{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
|
Order: order,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换为JSON
|
// 2. 将请求体序列化为JSON格式
|
||||||
jsonBody, err := json.Marshal(requestBody)
|
jsonBody, err := json.Marshal(requestBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("JSON序列化失败: %v", err)
|
return nil, fmt.Errorf("JSON序列化失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送POST请求
|
// 3. 发送POST请求(设置Content-Type为application/json)
|
||||||
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonBody))
|
resp, err := http.Post(
|
||||||
|
targetURL,
|
||||||
|
"application/json",
|
||||||
|
bytes.NewBuffer(jsonBody),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("请求发送失败: %v", err)
|
return nil, fmt.Errorf("请求发送失败(网络/连接问题): %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close() // 确保响应体关闭,避免资源泄漏
|
||||||
|
|
||||||
// 解析响应(无论状态码如何都尝试解析,以便获取详细信息)
|
// 4. 解析接口响应(无论状态码是否为200,均尝试解析,便于排查问题)
|
||||||
var response Response
|
var response Response
|
||||||
decoder := json.NewDecoder(resp.Body)
|
decoder := json.NewDecoder(resp.Body)
|
||||||
if err := decoder.Decode(&response); err != nil {
|
if err := decoder.Decode(&response); err != nil {
|
||||||
return nil, fmt.Errorf("响应解析失败: %v", err)
|
return nil, fmt.Errorf("响应解析失败(格式不匹配): %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查响应状态码
|
// 5. 检查HTTP状态码(非200视为异常,返回详细信息)
|
||||||
// 状态码异常时,返回包含完整响应的错误信息
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
// 将完整响应转为JSON字符串,便于查看
|
// 将响应内容转为格式化JSON,便于查看完整错误信息
|
||||||
responseJSON, _ := json.MarshalIndent(response, "", " ")
|
responseDetail, _ := json.MarshalIndent(response, "", " ")
|
||||||
return &response, fmt.Errorf(
|
return &response, fmt.Errorf(
|
||||||
"状态码异常: %d, 响应内容: %s",
|
"HTTP状态码异常: %d | 接口响应详情: %s",
|
||||||
resp.StatusCode,
|
resp.StatusCode,
|
||||||
responseJSON,
|
responseDetail,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 6. 请求成功,返回解析后的响应
|
||||||
return &response, nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
15
utill/scripts/killscripts.go
Normal file
15
utill/scripts/killscripts.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package scripts
|
||||||
|
|
||||||
|
var Luascript_forkill = `
|
||||||
|
local key = KEYS[1]
|
||||||
|
local jian = tonumber(ARGV[1])
|
||||||
|
local dingdan = ARGV[2]
|
||||||
|
local nums = tonumber(redis.call("get", KEYS[1]) or "0")
|
||||||
|
if nums > 0 then
|
||||||
|
redis.call("DECRBY", KEYS[1], jian)
|
||||||
|
redis.call("LPUSH", KEYS[2], dingdan)
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
`
|
||||||
Reference in New Issue
Block a user