-
慕盖茨4494581
如果您不想实现自己的包装器,可以使用该netutil.LimitListener函数进行环绕net.Listener:-connectionCount := 20l, err := net.Listen("tcp", ":8000")if err != nil { log.Fatalf("Listen: %v", err)}defer l.Close()l = netutil.LimitListener(l, connectionCount)log.Fatal(http.Serve(l, nil))
-
阿晨1998
这个技巧是实现你自己的net.Listener。我在这里有一个监听器示例(请参阅 waitConn 和 WaitListener),它跟踪连接(但不限制它们),您可以将其用作实现的灵感。它将被塑造成这样:type LimitedListener struct { sync.Mutex net.Listener sem chan bool}func NewLimitedListener(count int, l net.Listener) *net.LimitedListener { sem := make(chan bool, count) for i := 0; i < count; i++ { sem <- true } return &net.LimitedListener{ Listener: l, sem: sem, }}func (l *LimitedListener) Addr() net.Addr { /* ... */ }func (l *LimitedListener) Close() error { /* ... */ }func (l *LimitedListener) Accept() (net.Conn, err) { <-l.sem // acquire // l.Listener.Accept (on error, release before returning) // wrap LimitedConn return c, nil}type LimitedConn struct { /* ... */ }func (c *LimitedConn) Close() error { /* ... */ c.sem <- true // release}本质上,这样做是创建您自己的 net.Listener 实现,您可以将其提供给Serve,它仅在可以获取信号量时调用底层 Accept;如此获取的信号量仅在(适当包装的)net.Conn关闭时才释放。请注意,从技术上讲,这种信号量的使用对于 go1.2内存模型是正确的;在Go 的未来版本中,更简单的信号量将是合法的。
-
温温酱
借助通道,您可以限制活动连接的数量。1.在服务器启动时创建一个通道并将相同数量的限制计数(在您的情况下为 20)值放入该通道。2.在处理一个请求时从通道中删除一个值。网络上的一个例子type limitHandler struct { connc chan struct{} handler http.Handler}func (h *limitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { select { case <-connc: h.handler.ServeHTTP(w, req) connc <- struct{}{} default: http.Error(w, "503 too busy", StatusServiceUnavailable) }}func NewLimitHandler(maxConns int, handler http.Handler) http.Handler { h := &limitHandler{ connc: make(chan struct{}, maxConns), handler: handler, } for i := 0; i < maxConns; i++ { connc <- struct{}{} } return h}