dongnanke4106 2019-09-16 20:59
浏览 83
已采纳

如何限制Go API的并发连接

i am starting up a Go API with listenandserve to accept HTTP requests.

How can I achieve the below goal?

  1. Allow maximum 100 simultaneous HTTP requests
  2. The 101st request (and any others) should wait for 10mins to attempt to fall into this '100 simultaneous' limit (ie hopefully some of the first 100 requests should finish)
  3. If 10mins pass and no available request 'slots' have opened up then return error for that request that has been waiting
  4. Order of which request 101...102...x that gets run next is unimportant

current version is completely un-go:

    timeout := time.After(10 * time.Minute)
    tick := time.Tick(15 * time.Second)
    fullcmdfirst := fmt.Sprintf("netstat -anp | grep procname | grep ESTABLISHED | grep -v grep | wc -l")
    outputfirst, err1first := exec.Command("/bin/sh", "-c", fullcmdfirst).CombinedOutput()
    if strconv.ParseFloat(string(outputfirst)) < 100 {
        return nil
    }

    // Keep trying until we're timed out or lock acquired
    for {
        select {
        // Got a timeout! fail with a timeout error
        case <-timeout:
            return errors.New("Error: timed out ")
        // Got a tick, we should check if we can acquire
        case <-tick:
            fullcmd := fmt.Sprintf("netstat -anp | grep procname | grep ESTABLISHED | grep -v grep | wc -l")
            output, err1 := exec.Command("/bin/sh", "-c", fullcmd).CombinedOutput()
            if strconv.ParseFloat(string(outputfirst)) < 100 {
                l.Printf("start req")
                return nil
            }
        }
    }
  • 写回答

1条回答 默认 最新

  • douquan1953 2019-09-17 13:59
    关注

    There's no need for the netstats or the tickers or any of that (it won't work anyway - as soon as netstat sees <100 connections nothing is stopping the next 100 request from all noticing and you ending up running 199 requests at once; plus, a request that's waiting to be handled is still going to turn up in netstat - throttling connections is a different problem altogether). Just use a buffered channel as a semaphore; it's already thread-safe.

    sem := make(chan struct{}, 100)
    
    func myHandler(w http.ResponseWriter, r *http.Request) {
        timeout := time.After(10 * time.Minute)
        select {
            case <- timeout:
                http.Error(w, "Sorry", http.StatusUnavailable)
                return
            case sem <- struct{}:
                w.Write([]byte("Hello"))
                <- sem
                return
        }
    }
    

    Note though that most clients will have already timed out long before the 10 minute mark.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 在不同的执行界面调用同一个页面
  • ¥20 基于51单片机的数字频率计
  • ¥50 M3T长焦相机如何标定以及正射影像拼接问题
  • ¥15 keepalived的虚拟VIP地址 ping -s 发包测试,只能通过1472字节以下的数据包(相关搜索:静态路由)
  • ¥20 关于#stm32#的问题:STM32串口发送问题,偶校验(even),发送5A 41 FB 20.烧录程序后发现串口助手读到的是5A 41 7B A0
  • ¥15 C++map释放不掉
  • ¥15 Mabatis查询数据
  • ¥15 想知道lingo目标函数中求和公式上标是变量情况如何求解
  • ¥15 关于E22-400T22S的LORA模块的通信问题
  • ¥15 求用二阶有源低通滤波将3khz方波转为正弦波的电路