如何限制使用Go实现的HTTP服务器的连接数?

huangapple go评论82阅读模式
英文:

How to limit the connections count of an HTTP Server implemented in Go?

问题

我正在尝试在Golang中实现一个HTTP服务器。

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

英文:

I am trying to implement an HTTP Server in Golang.

My problem is, I have to limit the maximum active connections count at any particular time to 20.

答案1

得分: 22

你可以使用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))
英文:

You can use the netutil.LimitListener function to wrap around net.Listener if you don't want to implement your own wrapper:-

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

答案2

得分: 5

这个技巧是实现自己的net.Listener。我有一个示例的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中,一个更简单的信号量也是合法的。

英文:

The trick with this is to implement your own net.Listener. I have an example of a listener here (see waitConn and WaitListener) that tracks connections (but doesn't limit them), which you can use as the inspiration for an implementation. It will be shaped something like this:

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 &lt; count; i++ {
        sem &lt;- true
    }
	return &amp;net.LimitedListener{
        Listener: l,
	    sem:      sem,
	}
}

func (l *LimitedListener) Addr() net.Addr { /* ... */ }
func (l *LimitedListener) Close() error { /* ... */ }
func (l *LimitedListener) Accept() (net.Conn, err) {
	&lt;-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 &lt;- true // release
}

Essentially what this is doing is creating your own implementation of net.Listener that you can give to Serve that only calls the underlying Accept when it can acquire the semaphore; the semaphore so acquired is only released when the (suitably wrapped) net.Conn is Closed. Note that technically this use of the semaphore is correct with respect to the go1.2 memory model; a simpler semaphore will be legal in future versions of Go.

答案3

得分: -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", http.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
}

希望对您有所帮助!

英文:

With the help of channel you can limit the count of active connections.

1.At the server start up time create a channel and put equal number of limit count(in your case 20) values into the channel.

2.Remove one value from the channel while serving one request.

One example from the web

type limitHandler struct {
	connc   chan struct{}
	handler http.Handler
}

func (h *limitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	select {
	case &lt;-connc:
		h.handler.ServeHTTP(w, req)
		connc &lt;- struct{}{}
	default:
		http.Error(w, &quot;503 too busy&quot;, StatusServiceUnavailable)
	}
}

func NewLimitHandler(maxConns int, handler http.Handler) http.Handler {
	h := &amp;limitHandler{
		connc:   make(chan struct{}, maxConns),
		handler: handler,
	}
	for i := 0; i &lt; maxConns; i++ {
		connc &lt;- struct{}{}
	}
	return h
}

huangapple
  • 本文由 发表于 2014年3月25日 12:19:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/22625367.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定