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 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料