如何限制在go中实现的HTTP Server的连接数?

时间:2014-03-25 04:19:40

标签: go httpserver

我正在尝试在golang中实现HTTP服务器。

我的问题是,我必须将任何特定时间的最大活动连接数限制为20。

3 个答案:

答案 0 :(得分:12)

如果您不想实现自己的包装,可以使用netutil.LimitListener功能包围net.Listener: -

connectionCount := 20

l, 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))

答案 1 :(得分:5)

这样做的诀窍是实现自己的net.Listener。我有一个监听器here(请参阅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 memory model是正确的。一个更简单的信号量在Go的future versions中是合法的。

答案 2 :(得分:1)

在频道的帮助下,您可以限制活动连接的数量。

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
}