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 vs2022无法联网
  • ¥15 TCP的客户端和服务器的互联
  • ¥15 VB.NET操作免驱摄像头
  • ¥15 笔记本上移动热点开关状态查询
  • ¥85 类鸟群Boids——仿真鸟群避障的相关问题
  • ¥15 CFEDEM自带算例错误,如何解决?
  • ¥15 有没有会使用flac3d软件的家人
  • ¥20 360摄像头无法解绑使用,请教解绑当前账号绑定问题,
  • ¥15 docker实践项目
  • ¥15 利用pthon计算薄膜结构的光导纳