Commit 873bdca7 by hcy

并发问题

parent 43292f45
......@@ -68,6 +68,10 @@ func CommonController(ctx *gin.Context) map[string]interface{} {
}
//////////初始化公共变量 以及 批量查询///////////
redisLySkuArr := make(map[string]string) //redis.sku
redisZySkuArr := make(map[string]string) //redis.Self_SelfGoods
preSkuIds := make([]int64, 0) //归档sku
zyGoodsId := make([]string, 0, goodsSliceCount)
lyGoodsId := make([]string, 0, goodsSliceCount)
......@@ -79,17 +83,20 @@ func CommonController(ctx *gin.Context) map[string]interface{} {
}
}
//批量查询redis-sku信息
redisLySkuArr := gredis.Hmget("default_r", "sku", lyGoodsId)
if len(lyGoodsId) > 0 {
redisLySkuArr = gredis.Hmget("default_r", "sku", lyGoodsId)
//批量查询归档的sku
preSkuIds := make([]int64, 0)
for _, goodsId := range goodsIdArr {
if redisLySkuArr[goodsId] == "" {
preSkuIds = append(preSkuIds, gconv.Int64(goodsId))
}
}
}
if len(zyGoodsId) > 0 {
redisZySkuArr = gredis.Hmget("default_r", "Self_SelfGoods", zyGoodsId)
}
if len(preSkuIds) > 0 {
if len(preSkuIds) > 0 { //存在归档sku
var prevSkuArr []bson.M
prevSkuMongo := mongo.Conn("pre_sku")
......@@ -120,7 +127,7 @@ func CommonController(ctx *gin.Context) map[string]interface{} {
/////////////////多线程///////////////////////////
var wg sync.WaitGroup
ch := make(chan sync.Map, 500) //管道
ch := make(chan sync.Map, len(goodsIdArr)) //管道
semaphore := make(chan struct{}, 10) // 限制最大并发数为10
temp := make(map[string]interface{}) //最后输出计算结果
......@@ -130,27 +137,27 @@ func CommonController(ctx *gin.Context) map[string]interface{} {
if goodsId == "" {
continue
}
if len(goodsId) < 19 { //自营
zyGoodsId = append(zyGoodsId, goodsId)
if len(zyGoodsId) >= goodsSliceCount {
common.PrintDebugHtml(ctx, "zy增加协程1001:")
common.PrintDebugHtml(ctx, zyGoodsId)
common.PrintDebugHtml(ctx, "zy增加协程:"+goodsId)
//单个sku详情
if _, ok := redisLySkuArr[goodsId]; !ok {
temp[goodsId] = false
continue
}
skuStr := redisZySkuArr[goodsId]
wg.Add(1) //协程计数一
semaphore <- struct{}{} // 获取信号量
idsToProcess := make([]string, len(zyGoodsId))
copy(idsToProcess, zyGoodsId)
// 启动协程,传递独立的 context 和参数,而不是 gin.Context
go func(ctx context.Context, params service.RequestParams, goodsIds []string, ch chan sync.Map) {
go func(ctx context.Context, params service.RequestParams, skuStr, goods_id string, ch chan sync.Map) {
defer wg.Done()
defer func() { <-semaphore }() // 释放信号量
zyService.ZyGoodsDetail(ctx, params, goodsIds, ch)
}(ctx, requestParams, idsToProcess, ch)
zyService.ZyGoodsDetail(ctx, params, skuStr, goods_id, ch)
}(ctx, requestParams, skuStr, goodsId, ch)
zyGoodsId = zyGoodsId[:0]
}
} else { //联营
common.PrintDebugHtml(ctx, "ly增加协程:"+goodsId)
......@@ -170,7 +177,10 @@ func CommonController(ctx *gin.Context) map[string]interface{} {
// 启动协程,传递独立的 context 和参数,而不是 gin.Context
go func(ctx context.Context, params service.RequestParams, skuStr, goodsId, spuStr string, ch chan sync.Map, tag int) {
defer wg.Done()
defer func() { <-semaphore }() // 释放信号量
defer func() {
//println("释放信号:" + gconv.String(sd) + " time" + gconv.String(time.Now().UnixMilli()))
<-semaphore
}() // 释放信号量
lyService.LyGoodsDetail(ctx, params, skuStr, goodsId, spuStr, ch, tag)
}(ctx, requestParams, skuStr, goodsId, redisLySpuArr[spuId], ch, sd)
......
......@@ -674,3 +674,14 @@ func CheckIntSliceContains(target int, slice []int) bool {
}
return false
}
// 返回带小数点的时间戳,字符串
func ProTime() string {
now := time.Now()
// 获取秒级时间戳
seconds := now.Unix()
// 获取毫秒部分
milliseconds := now.UnixNano()/1e6 - seconds*1000
// 格式化为 "秒.毫秒" 格式
return fmt.Sprintf("%d.%03d", seconds, milliseconds)
}
......@@ -2,6 +2,9 @@ package service
import (
"context"
"github.com/gogf/gf/util/gconv"
"github.com/gomodule/redigo/redis"
"github.com/tidwall/gjson"
"go_sku_server/model"
"go_sku_server/pkg/common"
"go_sku_server/pkg/gredis"
......@@ -12,10 +15,6 @@ import (
"gopkg.in/mgo.v2/bson"
"sort"
"sync"
"github.com/gogf/gf/util/gconv"
"github.com/gomodule/redigo/redis"
"github.com/tidwall/gjson"
)
type LyService struct {
......@@ -37,7 +36,7 @@ type Power struct {
*/
func (ls *LyService) LyGoodsDetail(ctx context.Context, params RequestParams, skuStr, goodsId, spuStr string, ch chan sync.Map, tag int) {
//start_time := gconv.String(time.Now().UnixMilli())
start_time := common.ProTime()
redisConn := gredis.Conn("search_r")
redisConnSpu := gredis.Conn("spu")
// 连接prev_sku MongoDB
......@@ -273,7 +272,10 @@ func (ls *LyService) LyGoodsDetail(ctx context.Context, params RequestParams, sk
//退出通道
ch <- GoodsRes
//println("---tag:" + gconv.String(tag) + "-----goodsId:" + goodsId + "--start_time:" + start_time + " ---end_time:" + gconv.String(time.Now().UnixMilli()))
if (gconv.Int64(start_time) - gconv.Int64(common.ProTime())) > 2 {
println("---超时:" + gconv.String(tag) + "-----goodsId:" + goodsId + "--start_time:" + start_time + " ---end_time:" + common.ProTime())
}
}
// 获取活动
......
......@@ -75,14 +75,14 @@ func (ss *SampleService) GetSampleList(ctx *gin.Context) (data map[string]interf
func (ss *SampleService) GetGoods(ctx *gin.Context, goodsIds []string) map[string]interface{} {
// 提取请求参数
params := ExtractRequestParams(ctx)
//params := ExtractRequestParams(ctx)
// 创建带超时的 context
ctxWithTimeout, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
//抽取自营 或者联营 goods_id
zyService := ZiyingService{} //实例化自营查询
//zyService := ZiyingService{} //实例化自营查询
//lyService := LyService{} //实例化联营查询
ch := make(chan sync.Map) //管道
p := 0 //总共协程
......@@ -95,7 +95,7 @@ func (ss *SampleService) GetGoods(ctx *gin.Context, goodsIds []string) map[strin
if len(goodsId) < 19 { //自营
zyGoodsId = append(zyGoodsId, goodsId)
if len(zyGoodsId) >= 10 {
go zyService.ZyGoodsDetail(ctxWithTimeout, params, zyGoodsId, ch)
// go zyService.ZyGoodsDetail(ctxWithTimeout, params, zyGoodsId, ch)
zyGoodsId = zyGoodsId[:0:0]
p++
}
......@@ -109,7 +109,7 @@ func (ss *SampleService) GetGoods(ctx *gin.Context, goodsIds []string) map[strin
}
}
if len(zyGoodsId) > 0 {
go zyService.ZyGoodsDetail(ctxWithTimeout, params, zyGoodsId, ch)
//go zyService.ZyGoodsDetail(ctxWithTimeout, params, zyGoodsId, ch)
p++
}
if len(lyGoodsId) > 0 {
......
......@@ -34,7 +34,7 @@ type ZiyingService struct {
@param power[special_invoice] 增值税专用发票公司名字,活动价时需要,否则可能导致用户无法享受活动价 : 深圳是猎芯科技有限公司
@param power[verify_blacklist] 是否验证黑名单,用于折扣活动提交订单页面与后台下单 :true
*/
func (qs *ZiyingService) ZyGoodsDetail(ctx context.Context, params RequestParams, goodsIds []string, ch chan sync.Map) {
func (qs *ZiyingService) ZyGoodsDetail(ctx context.Context, params RequestParams, info, goodsId string, ch chan sync.Map) {
// 检查 context 是否已取消(超时或主动取消)
select {
case <-ctx.Done():
......@@ -51,23 +51,14 @@ func (qs *ZiyingService) ZyGoodsDetail(ctx context.Context, params RequestParams
redisConnSpu.Close()
}()
skuArr := gredis.Hmget("search_r", "Self_SelfGoods", goodsIds) //批量获取商品详情
fast := params.Fast // 从参数中获取,而不是从 gin.Context
GoodsRes := sync.Map{}
for goodsId, info := range skuArr {
// 在处理每个商品前检查 context 是否已取消
select {
case <-ctx.Done():
logger.Log("ZyGoodsDetail: 处理过程中context被取消", "sku", 1)
// 不要在这里发送,直接返回
return
default:
}
if gjson.Get(info, "goods_name").String() == "" {
//fmt.Print("zy goods_name为空-----",goods_id,skuArr)
GoodsRes.Store(goodsId, false)
continue
ch <- GoodsRes
return
}
//拼接属性
......@@ -193,12 +184,6 @@ func (qs *ZiyingService) ZyGoodsDetail(ctx context.Context, params RequestParams
A.Set("new_cost", gjson.Get(info, "new_cost").String()) //
A.Set("supplier_stock", gjson.Get(info, "supplier_stock").Int()) //
A.Set("self_supplier_type", gjson.Get(info, "self_supplier_type").Int()) //
//处理货期
//cnDeliveryTime := gjson.Get(info, "cn_delivery_time").String()
//if cnDeliveryTime == "" {
// cnDeliveryTime = "3-7工作日"
//}
A.Set("cn_delivery_time", "1-3工作日") // 货期
//查询品牌名称(作废,现在改成读联营的品牌库,之前有关联自营商品到spu_id)
......@@ -355,13 +340,5 @@ func (qs *ZiyingService) ZyGoodsDetail(ctx context.Context, params RequestParams
//最后写入sync map
(GoodsRes).Store(goodsId, A)
}
// 发送结果时也要检查 context,避免在超时后阻塞
select {
case <-ctx.Done():
logger.Log("ZyGoodsDetail: 发送结果前context已取消,直接返回", "sku", 1)
return
case ch <- GoodsRes:
// 成功发送
}
ch <- GoodsRes
}
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