Golang限制请求频率 + 接受超时信号后停止发送请求

直接跑一下看看呢

package main

import (
    "context"
    "fmt"
    "strconv"
    "sync"
    "time"
)

func main() {
    timeCtx, cancle := context.WithTimeout(context.Background(), time.Second*10)
    defer cancle()
    Test(timeCtx)
}

func Test(ctx context.Context) {
    finish := make(chan bool)
    list := []string{}
    for i := 0; i < 100000; i++ {
        list = append(list, strconv.Itoa(i))
    }
    taskList := make(chan string, len(list))
    // 为啥要close管道-因为不close下面的range是不会出来的
    defer close(taskList)
    for _, v := range list {
        taskList <- v
    }
    timeOut := make(chan bool)
    go func() {
        var wg sync.WaitGroup
        wg.Add(len(list))
        // 限频3个消费者
        for i := 0; i < 100; i++ {
            // 起3个协程去跑
            go func() {
                for v := range taskList {
                    select {
                    case <-timeOut:
                        func() {
                            defer wg.Done()
                        }()

                    default:
                        func() {
                            defer wg.Done()
                            ajax(v)
                        }()
                    }
                }
            }()
        }
        wg.Wait()
        fmt.Println(51)
        // 全部执行完成
        finish<-true
    }()
    fmt.Println(60)
    select {
    case <-ctx.Done():
        close(timeOut)
        // 超时
    case <-finish:
        // 执行完成
        fmt.Println("222")
        close(timeOut)        
    }
    // done
}

func ajax(v string) {
    time.Sleep(time.Second * 1)
    fmt.Println(v)
}

 

以上用于组装api接口请求

在最顶层的 timeout 抛出以后,下层会立即返回结果,并且终止待请求任务的发送;

通过消费者数量限定并行请求的数量 ;

实在没能想到其他更简单一些的方式、以及代码更简单清晰的方式 ~

context对象应用于多个层级的子协程,我这边的是一个按照配置的走的无限级递归调用的方式~

 

posted @ 2022-01-11 17:34  许伟强  阅读(119)  评论(0编辑  收藏  举报