golang 多个携程消费任务优化 (1)

现在需求是读取一批图片,然后批量上传到七牛云。

现在是第一版,思路就是起5个携程,然后对图片列表进行遍历循环,如果携程数使用超过5个就阻塞代码。

这里用到channel 信号量限流作用,就是往channel 写数据,如果channel 满了,就阻塞channel,直到对向从channel里边

把数据读取了。

    const maxGoroutines = 5
    guard := make(chan struct{}, maxGoroutines) // 限制并发量
    var wg sync.WaitGroup
    for _, m := range matches {
        if len(m) <= 1 {
            continue
        }
        rawUrl := m[1]
        // 取 path(去掉 host,只要路径)
        u, er := url.Parse(rawUrl)
        var path string
        if er == nil {
            path = u.Path
        } else {
            // 如果不是完整 URL,就直接用
            if strings.HasPrefix(rawUrl, "/") {
                path = rawUrl
            } else {
                path = "/" + rawUrl
            }
        }
        // 查询 Redis 是否已完成
        doneKey := fmt.Sprintf("picrew:done:%d:%s", postId, path)
        exists, er := start.RedisClient.Exists(context.Background(), doneKey).Result()
        if er != nil {
            fmt.Println("Redis 查询失败:", er)
            continue
        }
        if exists > 0 {
            //fmt.Printf("文件已存在%s\n", doneKey)
            continue // 已完成,跳过
        }

        wg.Add(1)
        guard <- struct{}{} // 占用一个协程名额
        // 启动协程处理 URL
        go func(url string) {
            defer wg.Done()
            defer func() { <-guard }() // 释放协程名额

            err = picrewService.UpdateQiniu(BaseUrl+url, url)
            fmt.Printf("图片地址: %s, 返回值: %v\n", doneKey, err)
            if err == nil {
                start.RedisClient.Set(context.Background(), doneKey, 1, 0)
            }
        }(path)
    }

    wg.Wait()

评论

(= ̄ω ̄=)··· 暂无内容!

回复

邮箱